States, game and menu classes

Post your questions, suggestions and experiences regarding game design, integration of external libraries here. For irrEdit, irrXML and irrKlang, see the
ambiera forums
Post Reply
Galhad
Posts: 13
Joined: Sat Mar 20, 2010 6:20 pm
Location: Zielona Gora, Poland

States, game and menu classes

Post by Galhad »

Hi, I want to make a simple game. I searched on this forum and I found game called Jetpac and states. So I wrote states like in Jetpac, but I dont know how to correctly use it. I have game class(inherited from IEventReceiver) that contains main menu class, states and changeState function. Main menu inherited from IGUIElemnt. So how to for example close Irrlicht device when user click quit(button in main menu)? I can check in game::onEvent function who called event (and set some buttons constant id), but is it correctly in OOP?
ChaiRuiPeng
Posts: 363
Joined: Thu Dec 16, 2010 8:50 pm
Location: Somewhere in the clouds.. drinking pink lemonade and sunshine..

Post by ChaiRuiPeng »

it shows how to do that in example 5

here's a little snippet from that example

Code: Select all

			case EGET_BUTTON_CLICKED:
				switch(id)
				{
				case GUI_ID_QUIT_BUTTON:
					Context.device->closeDevice();
					return true;

ent1ty wrote: success is a matter of concentration and desire
Butler Lampson wrote: all problems in Computer Science can be solved by another level of indirection
at a cost measure in computer resources ;)
Galhad
Posts: 13
Joined: Sat Mar 20, 2010 6:20 pm
Location: Zielona Gora, Poland

Post by Galhad »

This isnt problem. I know that. But menu cant call function from game class. Game contains menu. What should I do?
EDIT
Sorry I forgot that menu has its own OnEvent function for its childs
serengeor
Posts: 1712
Joined: Tue Jan 13, 2009 7:34 pm
Location: Lithuania

Post by serengeor »

Galhad wrote:This isnt problem. I know that. But menu cant call function from game class. Game contains menu. What should I do?
EDIT
Sorry I forgot that menu has its own OnEvent function for its childs
Maybe you should try to set up something simpler, like a console app that would switch states or call functions based on the input, then when you understand how it works, try to do the same with irrlicht. But don't start doing stuff with irrlicht untill you understand the very basics of c++, like classes inheritance, containers, Polymorphism and some basics of how to use templates.
Working on game: Marrbles (Currently stopped).
Galhad
Posts: 13
Joined: Sat Mar 20, 2010 6:20 pm
Location: Zielona Gora, Poland

Post by Galhad »

Guys, maybe I asked the wrong.. I understand oop and templates. Maybe code of app help, but I dont know is it make sense to copy all code here.. Game class is event receiver, so events go to it first. I dont know exactly which gui element called event(for example user clicked quit, I know that this is menu event, but in game class I dont know which from menu). So if I give this buttons id, and I will check later id in Game event receiver will it solve problem and it will be still OOP?
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

well, this is not a question of being OOP or not, you simply don't understand how states work (as far as I understand you)... :lol:

a state usually is stored in a variable either a global one (many will say "no, don't use globals") or a variable inside your event receiver...
as long as nothing happened the state (the variable) is set to (eg) STATE_NOTHING...
then when an event happenes the state is set to a new value, maybe to STATE_CLOSE when you click on an exit button...

the state variable must be accessible from everywhere, so either it's global or you provide a function in the event receiver that returns the state value...

so from the main loop you can check the state variable and act on it's value (eg. close the program when the value is STATE_CLOSE)...

I hope this helps ;)
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
ChaiRuiPeng
Posts: 363
Joined: Thu Dec 16, 2010 8:50 pm
Location: Somewhere in the clouds.. drinking pink lemonade and sunshine..

Post by ChaiRuiPeng »

Galhad wrote:Guys, maybe I asked the wrong.. I understand oop and templates. Maybe code of app help, but I dont know is it make sense to copy all code here.. Game class is event receiver, so events go to it first. I dont know exactly which gui element called event(for example user clicked quit, I know that this is menu event, but in game class I dont know which from menu). So if I give this buttons id, and I will check later id in Game event receiver will it solve problem and it will be still OOP?
if you really understood oop like you say you do you could look through the tutorials and it would answer aaaaaallll your questions you typed there and then some :wink:
ent1ty wrote: success is a matter of concentration and desire
Butler Lampson wrote: all problems in Computer Science can be solved by another level of indirection
at a cost measure in computer resources ;)
pippy3
Posts: 155
Joined: Tue Dec 15, 2009 7:32 am

Post by pippy3 »

Complicated state managers quickly turn into a nightmare, hybrid (I think) posted his favorite solution which was used a template and a tree to represent states. I found it to clunky to work right.

I recommend a simple solution, here's mine:

Code: Select all

/** 
 StateMngr class 
 */
class StateMngr {
private:
	// state the game is in
	STATES gameState;
	
	// the scene manager
	scene::ISceneManager* smgr;
	
	gui::IGUIEnvironment* guienv;	// the gui to create buttons
	
	Settings* mainSettings;
	
	State* state;
public:
	// construictor
	StateMngr(IrrlichtDevice* device,
			  Settings* inmainSettings
			  ) :
	mainSettings(inmainSettings)
	{
                // init game here
		smgr = device->getSceneManager ();
		guienv = smgr->getGUIEnvironment();
		gameState = STATE_MENU;
	};
	
	~StateMngr() {
	};
	
	// --- Returns the state this game is in ---
	STATES getState() {return gameState;}
	
	// --- update the current state ---
	void update (irr::EKEY_CODE k) {
		if (!state) return;
		state->update(k);
		
		if (state->getState() != state->currentState()) {
			printf("change State %d %d\n", state->getState(), state->currentState());
			STATES newState = state->getState();
			delete state; // remove old state
			state = 0;
			
			switch (newState) {
				case STATE_NONE:
					state = new EndState(smgr);
					break;
				case STATE_PLAYING:
					state = new PlayState(smgr);
					break;
				case STATE_EDIT:
					state = new EditState(smgr);
					break;
				case STATE_MENU:
					state = new MenuState(smgr);
					break;
				case STATE_OPTIONS:
					state = new OptionsState(smgr);
					break;
				default:
					break;
			}
		}
	};
};
#endif


#ifndef _STATE_PARENT_H_
#define _STATE_PARENT_H_

// States of the game
enum STATES {
	STATE_NONE = 0,      // doing nothing
	STATE_PLAYING,       // Playing in game
	STATE_EDIT,          // Creating / editing a map
	STATE_MENU,          // Upon start, select where to go
	STATE_OPTIONS,       // edit game options
	STATE_INGAMEOPTIONS  // edit game options
};

/** State class 
 */
class State {
protected:
	STATES gameState;
public:
	virtual ~State() {
		printf("state delete \n");
	}
	
	virtual void update(irr::EKEY_CODE k) = 0;
	
	// what state I want to be in
	STATES getState () const { return gameState; };
	
	// what state I actually am
	virtual STATES currentState () = 0;
};
#endif

Just extend state and implement virtual functions, then add a STATE enum. Simple.

(I left out the other state classes for simplicity.)
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

No, I did not participate in this discussion IIRC.
ChaiRuiPeng
Posts: 363
Joined: Thu Dec 16, 2010 8:50 pm
Location: Somewhere in the clouds.. drinking pink lemonade and sunshine..

Post by ChaiRuiPeng »

personally i dont find states too attractive... they make me feel like im severaly restricting my gameplay.

my design has a more emergent functionality. now that is a bit dangerous though.. since it could cause bizzare behvaiour, since im not explicitly defining the state of my system but letting it define its own state "by itself".

other concept thing that i am sure will cause some crashes in my design is my event system. it is so convoluted trEventType objects are actually instanced and registered with dynamically generated IDs. all trEvent objects of one type of event have a pointer to an instance of a trEventType.

the trEventFactory manages registration of events keeps tabs on the global count and has a table alphabetized by event name so when a new event needs an event of some type it either goes to that table or is dynamically assigned an event type instance with optimized methods through one of its peers of its parent trEventNode

pretty crazy and not sure it will even work if you ask me :lol:

EDIT: those ideas were so crazy i couldnt think of a starting point to start testing that kind of design. so i decided to just hardcode a small game and then reverse engineer that game to get it to fit into the design style i first mentioned.
ent1ty wrote: success is a matter of concentration and desire
Butler Lampson wrote: all problems in Computer Science can be solved by another level of indirection
at a cost measure in computer resources ;)
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
Galhad
Posts: 13
Joined: Sat Mar 20, 2010 6:20 pm
Location: Zielona Gora, Poland

Post by Galhad »

Thanks for replies :D
@pippy3
So eg. Options State class should contains gui options menu?
pippy3
Posts: 155
Joined: Tue Dec 15, 2009 7:32 am

Post by pippy3 »

Galhad wrote:Thanks for replies :D
@pippy3
So eg. Options State class should contains gui options menu?
yes, each state has a reference to the GUI items used. I simply cleared the UI state manager between states (on the deconstructor method.) Ultimately you should pass an Event struct on an event instead of a key, but since my game didn't need it I didn't bother with it.

By not clearing the scene manager, it allows for states like paused. If you're changing between two levels clear the scene and the ui manager.
Post Reply