Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I wanted to use a game state management system similiar to this approach: Managing Game States in C++

But from what I've heard singletons are evil and should not be used in 99.9%.

Can you tell me how I could modify the method of the above article to work without singletons?

share|improve this question
8  
Singletons are a tool, just like anything else. There are lots of pros and cons arguments out there, you just have to figure out for yourself if the cons of using them is bad in your specific case. –  Tetrad Apr 12 '12 at 16:07
    
^ Agreed. For example, if I'm building a level editor then it makes sense to have a single, center point for all of my resources (art, sounds, etc.) so I would use a singleton. I think the whole "singletons are evil" mantra spawns from overuse. –  Mike C Apr 12 '12 at 16:19
4  
It spawns from them being the wrong tool for just about every job. You can provide global access to something without it needing to be a singleton. You can create a single instance of something without it needing to be a singleton. Hardly any uses of singletons actually need to be singletons - the example in the linked article is yet another one. –  Kylotan Apr 12 '12 at 19:00
1  
Although it is very clear to me why many C++ stuff shall be considered evil (i.e. define and pre-processor code in general, goto, etc.) I can't see why you say the same for the Singleton pattern. It does not violate the encapsulation principle and it is a very neat and elegant architectural solution (also easy to implement). –  www.Sillitoy.com Apr 13 '12 at 5:14
1  
When you make something globally available, that does actually break encapsulation, because everything that relies upon that state is now susceptible to changes caused from other parts of the program. If you instead passed in a reference then the dependency is made explicit. I can think of no example where a singleton wasn't just used as an attempt to dress up a global in object-oriented clothing. –  Kylotan Apr 13 '12 at 9:35
show 1 more comment

3 Answers

up vote 0 down vote accepted

It is possible to handle game state management without an actual manager for game states.

The way I implemented it in my game was to create a static function in the base class to get the first state.

The first state is usually fixed or could be a different one each time you start the game based on some external settings (like in my game). I let the base class's static function to decide which state should be returned.

Now for each state, I have this policy that every state should know what its next state should be. By having this feature within each state it is always possible to move forward from one state to the next. Going back to the previous state is simply advancing to the next state. Or if required you can store previous state instance in the current state and use that as the next state to go back to the previous state. Make sure to handle memory in that case. I would suggest using SharedPtr.

Every state would need an instance of the object which the updating of the current state. In my case this is the Game class. This way I am passing around the game class and can thus avoid the Game class to be a singleton.

So with this design you have a start point defined as static function and state management with each state. This is easy if you are building a game rather than if you are trying to build a framework that doesnt know about the individual states in advance and how to transition between them.

share|improve this answer
add comment

If you just want to avoid the singletons you could create instances of every game state you need in your initialization code. Then add these to a map inside the CGameEngine class - for example:

game.AddGameState("Intro", new CIntroState());
game.AddGameState("Menu", new CMenuState());
...

You could than add a method to the CGameEngine to retrieve the game state instances:

GameState* GetGameState(std::string stateName);

like this:

GameState* introState = game.GetGameState("Intro");

and you could use these with the existing methods to change the states however you like. You just have to take care of releasing the memory of all the allocated states in the deinitialization code of your game.

The downside of this approach (and the singleton approach in the linked article) is that all game state instances are residing in memory for the whole duration of the game. But this might not be a problem depending on your requirements and target platform.

share|improve this answer
    
Would it be also possible to let the GameStates dynamically create the next GameState simply by calling "engine->ChangeState(new GameState())"? I think the object will be automatically removed of memory when "states.pop_back()" is called. –  shad0w Apr 12 '12 at 18:10
    
The code on the linked site does not release the memory in the PopState or ChangeState methods. In theory you could rewrite the method to delete the pop-ed instance but then you get into more trouble: changing the game state normally happens while "executing" a game state i.e. inside the Update() method of the CMenuState you call game->PushState(new CGamePlayState()). So if you would like to pop the current state and automatically delete it you would delete the currently "executed" state. –  estrich Apr 12 '12 at 18:48
    
What's with the utterly pointless string typing and dynamic allocation? –  DeadMG Apr 12 '12 at 19:48
    
But I think vetor::pop_back calls the destructor of the object, so the memory should stay clean. –  shad0w Apr 13 '12 at 6:30
    
@shad0w yes, vector::pop_back will destroy whatever object-type is stored inside the vector. The problem is, that you are storing POINTERS to CGameState objects (vector<CGameState*>). This means that ONLY the pointer will be destroyed when pop-ed, but not the object itself - you have to manually delete it. –  estrich Apr 13 '12 at 18:47
show 3 more comments

One of the reasons that it's bad to use Singletons is that it's extremely difficult to decouple them from any design.

What I would do is just to make the Engine class take a regular reference to a state, and then declare the IntroState on the stack and pass it in.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.