I was just wondering.. What would be the best code method for creating - say - a number of menus that you can navigate around? Thanks for any info on this subject in advance.![]()
This is a discussion on Best "Menu" method? within the Game Programming forums, part of the General Programming Boards category; I was just wondering.. What would be the best code method for creating - say - a number of menus ...
I was just wondering.. What would be the best code method for creating - say - a number of menus that you can navigate around? Thanks for any info on this subject in advance.![]()
GUI or console?
Sent from my iPad®
Can you be more specific on what type of libraries you're using to create this?
Sent from my iPad®
Ah, I purposely didn't specify. I'm just talking about theoretically, if you're making any sort of program that has menu's in it, how would you go about doing it in the most efficient way? I hope I clearified that enough. >_<
I'm not really looking for "how would you do it with _____ library, etc... " I can try and figure that part out myself.![]()
Last edited by SSJMetroid; 12-06-2005 at 04:01 PM.
Wellll, if you really don't want to code anything much but have a GUI fast, use the Win32 API, its GUI heaven..
Other than that, I don't know much about GUI work.
Sometimes I forget what I am doing when I enter a room, actually, quite often.
Hmmm, it's a good thought, but I wasn't really intending to use "Windows API." :P
Never intended for it to be made fast. XD
I thought this would be an opertune time to demonstrate how a menu system can get out of control. The concept I had going here was very solid, but through coding I ended up adding a lot of functionality "hacks" that made the system kinda combursom.
EVENTS: drive everything , including the UI so, heres the class header
UI: Header fileCode://////////////////////////////////// // event.h // game processes class file // all entities that require some sort of // processing or handling inherit the event object #ifndef PR_EVENT #define PR_EVENT #include "global.h" // Objects that need to be managed will // inherit this as base class class CEventNode { friend class CEventList; public: CEventNode(); ~CEventNode(); void setThread(CThread *thread); virtual bool process(CEventList *owner) = 0; // if a process returns true it was handled and should be removed // else it remains in teh que for the next game tick protected: __int64 spawn; // onlything important relavent to all processes is when it was spawned // anything else is defined in subclasses static long int instanceCount; long int id; // event id - I have no idea of the potential ammount of events in a single game long should be fine CEventNode * next; // points to next event to be processed CEventNode * prev; // points to prev event (easier removal of nodes) CThread *thread; // thread spawning }; class ListCleanUp : public CEventNode { // a node that on process tells the managing list it's empty public: ListCleanUp(bool fullclean){ this->fullclean = fullclean; }; ~ListCleanUp() {}; bool process(CEventList *owner); private: bool fullclean; }; // Special CEventNode() that handles setting or removing a CThread // depreciated ? class CEventNodeThreader : public CEventNode { public: CEventNodeThreader(); ~CEventNodeThreader(); bool process(CEventList *owner); private: CThread *thread; }; // event/object managers will // inherit this as base class class CEventList { public: CEventList(); ~CEventList(); public: void add( CEventNode *e ); void empty(bool really); void ignore(); void remove( long int id ); void setOwner(CThread *owner); void spawnThread(CThread *thread); int size(); bool handle(); private: CThread *owner; CEventNode *head; CEventNode *tail; bool ignoreEvents; }; // not the traditional thread in multithreading // but more along teh lines of a guide line strand.... right. class CThread { public: CThread(); ~CThread(); bool Run(); void setProcedure(CThread *thread); // sets a procedure void removeProcedure(); protected: CThread * pActiveProcedure; CEventList list; public: char * name; }; #else #endif
[code]
///////////////////////////
// UI.h
// user interface header file
#ifndef PR_UI
#define PR_UI
#include "global.h"
#include "font.h"
// The functionality of the User Interface is such that
// at runtime the main windows thread spawns our top level
// menu. This top level menu is a UIMain object, that spawns it's own thread
// at this point the main window loop is waiting for this thread to return(finish)
// The menu is a running thread with a list of events that need to be processed before
// it can return to the main window loop and thus exit the application.
// the list contains UIMenuItem objects that inherit EventNode, the list is cycled through
// and the menu item performs as defined, some items might actually call for a new UIMenu
// to spawn create a sub menu - at this point the winmain thread is waiting for the Main menu,
// witch is now waiting on the submenu, the submenu then has it's own event list that needs to
// be processed before it returns. Generally an Exit menu item will be the trigger to end the
// event list and collapse back into teh calling thread. A UIMenuItem will also be capable of
// spawning a GameThreadEvent witch up can return to the calling menu several methods - manual
// escape, winning or losing - etc.
class UIMenuItem;
class UIMain : public CThread {
public:
UIMain();
~UIMain();
void addItem(UIMenuItem *item);
// thread process info
private:
// uhhhhhhh stuff
};
// UIMenuItem is an abstract interface for menu items
// that range from strings, to media items
// menu items actually decide if they are being
// interacted with by the user rather then the menu
// manager class doing so.
class UIMenuItem : public CEventNode {
public:
UIMenuItem();
~UIMenuItem();
// rather then obtain this global information manualy in each function,
// a interface method is being implimented in case at some future point
// i want this info obtain through strict process by authorized class managers
// this saves time for redoing the process in teh long run.
sKey getKey(int key); // checks global key structure for key activity
sMouse getMouse(); // grab mouse info from global structure
void setColor(float r, float g, float b);
void setPos(int x, int y);
void setSpawnEvent(CEventNode *e);
bool hotSpot(int textx, int testy);
protected:
// uhhh other stuff
CEventNode * spawn; // an event that spawns as a result of this thing being handled
int x, y; // screen position;
int width, height;
sRGB color;
};
// UIItemStaticText
// simple text lables
class UIItemStaticText : public UIMenuItem {
public:
UIItemStaticText();
~UIItemStaticText();
bool process(CEventList *owner);
public:
void setFont(char *name, int size);
void setString(char *string);
protected:
char *string;
GLFONT *pFont;
};
// UIItemTextOption
// text item that interacts with user
class UIItemTextOption : public UIItemStaticText {
public:
UIItemTextOption();
~UIItemTextOption();
bool process(CEventList *owner);
void setInteractColors(sRGB base, sRGB hightlight, sRGB down);
private:
sRGB highlightColor;
sRGB downColor;
};
#else
#endif
[/quote]
UI: function definitions
And actually using the UI in the Initialize()Code:#include "global.h" UIMain::UIMain() {}; UIMain::~UIMain() {}; void UIMain::addItem(UIMenuItem *item) { list.add(item); }; // thread process info UIMenuItem::UIMenuItem() { this->spawn=0; // nothing by default }; void UIMenuItem::setSpawnEvent(CEventNode *e) { this->spawn = e; // set an event to be triggered. }; UIMenuItem::~UIMenuItem() { }; sKey UIMenuItem::getKey(int key) { // this needs protection data entry in place // actually at this point its only read data // should be protected when writing return keys[key]; }; sMouse UIMenuItem::getMouse() { // read data return mouse; // this needs protection data entry in place }; // set render position top left of an item void UIMenuItem::setPos(int x, int y) { this->x = x; this->y = y; }; // set the color option void UIMenuItem::setColor(float r, float g, float b) { this->color.r = r; this->color.g = g; this->color.b = b; }; // test a pixel position against rectangle hotspot bool UIMenuItem::hotSpot(int testx, int testy) { if(testx > x && testx < x+width) if(testy > y && testy < y+height) return true; return false; }; // constructor for static text items // defaults to arial, size 14, "Menu Item" color black UIItemStaticText::UIItemStaticText() { string = "Menu Item"; this->pFont = new GLFONT("Arial", 14); this->height = 14; this->x = 20; this->y = 20; sRGB c = { 0, 0, 0 }; this->color = c; this->width = pFont->stringWidth(string); // calculate size of default }; UIItemStaticText::~UIItemStaticText() { }; // Static text is kind of a "permanent" event. // such that it is never handled and removed from the list // for this reason in order to exit from any thread that // contains a permanent event, a special exit event must // be spawned and processed in order to tell the thread to // forcefully empty it's event list and return true; bool UIItemStaticText::process(CEventList *owner) { glColor3f(color.r, color.g, color.b); pFont->display(x, y, string); return false; }; // set the font and size of static text item void UIItemStaticText::setFont(char *name, int size) { this->pFont = new GLFONT(name, size); this->height = size; this->width = pFont->stringWidth(string); // calculate size of new font }; // set teh string, of text. void UIItemStaticText::setString(char* string) { this->string = string; this->width = pFont->stringWidth(string); // calculate size of new string }; // set default highlight and down colors // initialize default string and font UIItemTextOption::UIItemTextOption() { sRGB h = { 1.0f, 0.0f, 0.0f }; // default highlight color is red this->highlightColor = h; sRGB d = { 1.0f, 1.0f, 0.0f }; this->downColor = d; }; UIItemTextOption::~UIItemTextOption() { }; // set colors for the text options, unfocused, focused and down void UIItemTextOption::setInteractColors(sRGB base, sRGB highlight, sRGB down) { this->highlightColor = highlight; this->downColor = down; this->color = base; }; bool UIItemTextOption::process(CEventList *owner) { sMouse mpos = getMouse(); font->display(this->x - 30, this->y, "width: %i", width); font->display(this->x + width, this->y, "|<- end|"); font->display(10.0f, 30.0f, "MB: %i, Mx: %i, My: %i, RECT(%i, %i, %i, %i)", mpos.button, mpos.x, mpos.y, this->x, this->y, this->x+this->width, this->y+this->height); if(this->hotSpot(mpos.x, mpos.y+this->height)) { // option have focus? glColor3f(this->highlightColor.r, this->highlightColor.g, this->highlightColor.b); if(!this->hotSpot(mpos.prevx, mpos.prevy)) // fist time having focus? { //ADDME: play mouse over sound } if(mpos.button == 1) { glColor3f(this->downColor.r, this->downColor.g, this->downColor.b); //ADDME: play mouse over sound //ADDME: spawn some event if(this->thread != 0) // if there is a thread to spawn owner->spawnThread(this->thread); // tell the list to spawn this thread if(this->spawn != 0) // if there is an event to spawn owner->add(this->spawn); // tell the list to spawn this event pFont->display(x, y, string); return false; } pFont->display(x, y, string); } else { // option does not have focus glColor3f(color.r, color.g, color.b); pFont->display(x, y, string); } return false; };
Code:// menu / process testing MainMenu = new UIMain(); MainMenu->name = "Main Menu"; // make a menu item // set properties UIItemStaticText *item = new UIItemStaticText(); item->setString("Hyperspace 2005"); item->setFont("Times New Roman", 20); item->setColor(0.25f, 0.50f, 0.75f); item->setPos(g_winWidth/2, g_winHeight/2); // add it to the menu MainMenu->addItem(item); UIItemTextOption *item2 = new UIItemTextOption(); item2->setString("Start A New Game"); //item2->setInteractColors(); item2->setFont("Verdana", 20); item2->setPos(g_winWidth/2, (g_winHeight/2)+22); // add it to teh menu MainMenu->addItem(item2); item2 = new UIItemTextOption(); item2->setString("Another menu item."); item2->setFont("Arial", 20); item2->setPos(g_winWidth/2, (g_winHeight/2)+44); MainMenu->addItem(item2); UIItemTextOption *exit = new UIItemTextOption(); exit->setString("Exit"); exit->setFont("Arial", 18); exit->setColor(0.01f, 0.01f, 0.8f); exit->setPos(g_winWidth/2, (g_winHeight/2)+66); exit->setSpawnEvent(new ListCleanUp(1)); MainMenu->addItem(exit); // Sub menu test UIMain *subMenu = new UIMain(); subMenu->name = "Sub Menu"; UIItemStaticText *subitem = new UIItemStaticText(); subitem->setString("This is a submenu!"); subitem->setFont("Times New Roman", 18); subitem->setPos(g_winWidth/2, (g_winHeight/2)); subMenu->addItem(subitem); UIItemTextOption *subitem2 = new UIItemTextOption(); subitem2->setString("Exit"); subitem2->setColor(0.3f, 0.9f, 0.4f); subitem2->setPos(g_winWidth/2, (g_winHeight/2)+22); subitem2->setFont("Sans Sarif", 20); subitem2->setSpawnEvent(new ListCleanUp(0)); subMenu->addItem(subitem2); // assign sub menu, to a button in main menu item2->setThread(subMenu); // officially associate the main menu as the primary game thread GameThread = MainMenu; // set the game thread pointer to teh MAIN Menu
c++->visualc++->directx->opengl->c++;
(it should be realized my posts are all in a light hearted manner. And should not be taken offense to.)
OH FYI: This UI is used in the program in this thread: Space Pong (Debug) Release
c++->visualc++->directx->opengl->c++;
(it should be realized my posts are all in a light hearted manner. And should not be taken offense to.)
Well why didn't you specify this in the original post?Originally Posted by SSJMetroid
You know what date is on this coin? 1958. It's been travelling twenty two years to get here.
And now it's here.
And I'm here.
And it's either heads or tails.
And you have to say...
Call it.
My bad. ^^;;;
[Edit:]
Btw: Thanks for that UI example, Jeremy. That's sorta the kind of example I needed. You rock, dude.![]()
Last edited by SSJMetroid; 12-07-2005 at 01:13 PM.
Windows is GUI hell, not GUI heaven.
Arrogance breeds bad code