Need help with GUI...

Started by
7 comments, last by Blazeroni 21 years, 3 months ago
Hello everyone, Right now I''m working on implementing a GUI in my game. The problem I''m having is connecting the various menus and buttons and such with actual game actions (ie. non-menu actions). For a simple example, say I had a dialog that changed the color of a unit or something arbitrary. What''s the best way to connect the action of changing the color with pressing the OK button? Would I put it in a menu control function? So, when the button was pressed the menu sends a notification to the function which then performs the action... If that''s the tactic, how does that function know which instance it''s supposed to change the color of? A pointer to that object? That means that the menu would have to contain a pointer to the object it''s a menu for, which also assumes that there''s a 1-to-1 relationship of menus and objects which may not be true. Anyways, you can see I''m a bit confused. I''ve had some other ideas, but I doubt they''re correct. Or if they are, they''re more complicated than they need to be. There must be a simpler, cleaner way to do it. Any insight would be appreciated. Thanks in advance. -Blazeroni
Advertisement
Hi there, I''m not sure how to fix your problem but over in the Articles & Resources section there is a series devoted to creating GUIs and you might have some luck there. Hope that helps. Good Luck!
The way i do it is whenever a button is clicked...like an exit button, it checks the text for certain instances...like "Exit" and what not...i don''t know what I would do about an ok button

<- Digital Explosions ->
"Discipline is my sword, faith is my shield
do not dive into uncertainty, and you may live to reap the rewards" - (Unreal Championship)
Well, here goes for some brainstorming...

It seems to me that you''re thinking procedurally, rather than thinking about objects. I''ve worked in Object-Oriented and it works remarkably well for games, here''s some ideas you might want to look into.

First off, You got ''units'', as you say. They obviously are entitled to being their own objects. And since you have many, no doubt you keep a list of these objects -somewhere-.

Your menu-run function should only run some code that runs through that list, whether it''s loaded with units or empty. Hmm, come to think of it, that color should be set during the game''s loading, so that a change is kept from one run to another? In that case you need a generic ''country#1 unit color'' for many objects? Interesting.


Oh, here''s a crazier OO way to do this: Have an ''EventParser'' in your system that parses mouse, keyboard and GUI input and converts them into ''events''. Then have a virtual base class called ''EventListener'' that will register themselves to the single EventParser in their constructor, unregister themselves in the destructor. Then the EventParser need only send its events to the objects that registered themselves. (Possibly a long list, but you can be sure nobody forgot themselves!)

Hehe, there''s ways to have fun with this... I hope this brainstorming helps!

=^.^= Leaders and teachers should remember: It is best to offer others what they Need, not what they Want.
=^.^= Leaders and teachers should remember: It is best to offer others what they Need, not what they Want.
>>>>
Would I put it in a menu control function? So, when the button was pressed the menu sends a notification to the function which then performs the action... If that''s the tactic, how does that function know which instance it''s supposed to change the color of? A pointer to that object? That means that the menu would have to contain a pointer to the object it''s a menu for, which also assumes that there''s a 1-to-1 relationship of menus and objects which may not be true
>>>>
A menu can return different types of information
I use is a menu object that, when I create it, I give it a function pointer. I then put the menu object onto a listEach update I run the function pointer(I separate the display of the menu with the processing)

  char *MainEdFunctions[] = { "Map Screen", "NPC Screen", "Source Art", "Save Tiles To Hard  Drive", "SpriteEditor", "Objects", "Walls", "Conversations", "Exit", "-1"};CPtrList *pMainEdFunctions = new CPtrList;  // add list of strings to be displayed during Render Menu{LoadStringsOntoList(MainEdFunctions, pMainEdFunctions);Mainrender(){RenderScene();if (pMenuList != NULL) RenderMenues();RenderMouse();  // graphics finished renderingProcessInterface();}ProcessInterface(){GetMouseStates();GetKeyBoardInfo();if (pMenuList != NULL)  {pTopMenu = GetTopMenuObject();(pTopMenu->functionpointerMenuFn)(ms_flags); }else{// if a key is hit or a mouse button clicked to create a menupTempNew = new MenuObject(17, 32, pMainEdFunctions, JTBN_BASIC, NONDESTRUCTIVE, OnEditFunctions, NULL);... Do other processing ...  this if..else means that only the menulist gets processed}int OnEditFunctions(int msFlags){pTopMenu = GetTopMenuObject();int nResult = pTopMenu->Process(ms_flags);if (nResult != NORESULT){//char *MainEdFunctions[] = { "Map Screen", "NPC Screen", "Source Art", "Save Tiles To Hard  Drive", // "SpriteEditor", "Objects", "Walls", "Conversations", "Exit", "-1"};#define EDIT_MAPSCREEN 0#define EDIT_NPCSCREEN 1if (nResult == CANCEL) DeleteMenuObject();else     switch (nResult)       {       case EDIT_MAPSCREEN:           SwitchToMapScreen();           break;       case EDIT_NPCSCREEN:           SwitchToNPCScreen();           break;// .......       )   DeleteMenuObject();}  


It''s not an easy process to get your head around. It requires you to chart the menu Object, understand function pointers, and compartmentalize the different actions. I used MFC as a guideline. To create a whole new menu takes about 10 minutes to hook everything up(lots of cut&pasting) and one minute to create a new option on the same menu.

ZoomBoy
Developing a iso-tile 2D RPG with skills, weapons, and adventure. See my old Hex-Tile RPG GAME, character editor, diary, 3D Art resources at Check out my web-site
burgc002:
Yeah, I looked through that but it didn''t really explain that. It talked about making the GUI work within itself and not so much about making it actually do something useful. It was alluded to but never explained.

Spacecat:
The units was just an example. Yes, I have my list of units and yes they each are assigned a color based on their ''country'', but that''s not really the point.
So, let me see if I got the EventParser idea right... You have an EventParser and everything that has a menu for it would be a subclass of the EventListener class. Hmm... So, say I had a Player object that needed a name. I have a simple menu that takes some text and has an OK button. When the ok button was pressed, an event would fire for it. Something like FireEvent(PLAYER_NAME) or something along those lines. The event would go through the parser and see what kind of event it is and notify the Player object. I''m not sure how the Player object gets the information or how it knows which Player object it is, if there''s more than one. Also, I''d probably need to know which menu object it came from so i could get the data. Perhaps FireEvent has along with it a void pointer so it would be FireEvent(menuObject, playerObject, PLAYER_NAME). Then I could go through the list of possible objects that have windows and see which one has the same pointer. Then I suppose since I know which object and which menu I could get the information from that window, cast the void pointer playerObject back to the Player class then do what was needed. That''s not a bad solution. A little convoluted, but it separates the menus, objects, and actions, which was my main goal.

ZoomBoy:
It''s a little hard to read code that''s been cut up. Let me see if I understand what you were saying. You''ve got your menu object that has a function pointer that takes an int called ms_flags. What are the flags for? What kind of information are they giving you? What happened in the menu (ie. buttons pressed, moved, closed, etc.) or is it something to do with what the menu is a menu for. I assume it''s the former because it seems very difficult and time consuming to use it for the latter. You say it takes 10 minutes to set up a menu. Is that just the time that it takes to get it functional? If so, it seems like there''s an easier way. If I''m offbase on your code and such, please correct me.

Thanks everyone. If you''ve got some more input, please keep it coming.

-Blazeroni
>>>>>
...You''ve got your menu object that has a function pointer that takes an int called ms_flags. What are the flags for? What kind of information are they giving you?
>>>
What the ms_flags variable and the GetMouseStates() function do is update the position of the mouse. I must admit it is a bit hidden with a few global mouse Variables(bad bad bad)

It is in the given function - OnEditFunctions - where the menu object and the mouse actions are processed with pTopMenu->Process(ms_flags) There the various mouse actions are tested(if the mouse is clicked outside of the menu, then the object is CANCELed, if the mouse is clicked on the menu, Process(ms_flags) finds which menu choice has been selected and Process(ms_flags) returns a number n showing the nth item has been chosen.
In the section below Process(ms_flags) in - OnEditFunctions - the return value is examined and if it''s not CANCELed, then you can put the return value through a switch statement .

>>>>
You say it takes 10 minutes to set up a menu. Is that just the time that it takes to get it functional? If so, it seems like there''s an easier way. If I''m offbase on your code and such, please correct me.
>>>>
Sorry about that 10 minute time, I usually include the time to decide "What the hell am I going to have on my menu?" That is a higher question of Menu design that is not part of this discussion.
If I''ve got all the menu options written down on a piece of paper, my list of actions is straight-forward
1) Type in the Text labels(the menu needs to print something out)
i.e. char *MainEdFunctions[] = { "Map Screen", "NPC Screen", "Source Art", etc.
2) Put the menu-text strings onto a list usually in a global setup function.
i.e.
void LoadAllMenuStrings()
{
LoadStringsOntoAList(MainEdFunctions, pMainEdFunctions);
LoadStringsOntoAList(SpriteEditFunctions, pSpriteEditFunctions);
LoadStringsOntoAList(ExitMenuOptions, pExitMenuOptions);
}
3) Find a place where the menuObject will created
i.e. pTempNew = new MenuObject(17, 32, pMainEdFunctions, JTBN_BASIC, NONDESTRUCTIVE, OnEditFunctions, NULL);
4) Cut and paste another OnSomethingElse() menu function, that I''ve already completed, and change the name to OnEditFunctions(...
5) I examine the switch statement and start changing menu actions. Here''s where the new menu, when you click on a choice, will do new things.

There are one or two other steps that I use that help my debugging but that''s it. Time for that 2 minutes if you can find the stuff right away.

ZoomBoy
Developing a iso-tile 2D RPG with skills, weapons, and adventure. See my old Hex-Tile RPG GAME, character editor, diary, 3D Art resources at Check out my web-site
Why not do it like windows, or any other gui?

If you have a dialog box, and an edit box where you type in your info, when you hit "ok" that ok button is a child of your dialog. dialog::onOk(){do this stuff in here} If you click on a button, your gui should find the child that you are clicking on at that position, and then send to that specific control the message that you sent, such as a left click. What it boils down to is that you need an "instance" for each gui control and window. each of those instances will keep the individual actions and non gui functions separate.

Try reading the gui article here. There are a couple of ways of building a fairly robust gui that I know of, one is to use macros that link function pointers, as in microsofts system, that responds to messages. The other method is similar, but instead, each child will inherit every function from its parent instead as in the article here at gdnet.
I appreciate the responses everyone wrote. They gave me a new perspective to look at the problem. I think I have a pretty good grasp of how to do what I want. Thanks again.

-Blazeroni

This topic is closed to new replies.

Advertisement