Codename: Haunted Light – GameStates
|
This week I have accomplished a couple of things. I changed what the Object-Manager stores. Previously it stored GameObjects but now it stores pointers to GameObjects. This prevents the object you want to store inside the Object-Manager from being destroyed when it gets copied over to the map container. Due to this change I also managed to fix a couple of memory leaks concerning the objects sprites and colliders not getting destroyed. Another thing I did was making the game scale according to what resolution you have. This change prevents the users who plays the game at higher resolution from having an advantage due to the increased field of view. But the main thing I did this week was the revamp of the State-Manager. Previously we had no way of pausing the game. If you wanted to take a break from the game you’d have to restart from the beginning again in-case you lost while you were gone. And that’s not acceptable. So now instead I have changed the way states are handled and gave each state a couple of new functions and member variables. New Functions
New member variables
How it works
Now we have all the functions and member variables which are needed to transition seamlessly between states. But how do we use them? The way they’re used In order to be able to use all the states you’ve created, you need to have a “State-Manager” which takes care of all the execution of state-functions. The State-Manager in Haunted Light have two member variables of the type vector.
The first member variable “m_states” holds all the states which the game has. The second one; “m_current” holds all the states which are active. When I want to add a state to the game I use the state-managers “Attach() function. This function takes one argument of the type State pointer. It then adds the state to the StateManagers vector container by writing e.g: “state_manager.attach(new GameState(m_system));” ( The argument “m_system” is a pointer of System class that holds all the necessary parts of the application which all the states need to have access to). But in order to play the game you want to have a “starting state”. To set the initial state I use the state-managers “SetState” function. This function also takes one argument but of the type std::string. When called this function goes through all the states inside “m_states” and call each states isType() function. isType whether the State is of the type that’s defined in the argument to the function. When the correct state is found then it’s “Enter()” function gets executed. From here the StateManager alternates between the current states Update() and Draw() function until the Update() function returns true. That means that it’s time to change state. Before the function returns true, then it can call the Pause() function to indicate that it is a “pause call” and through the member variable “m_next” define what the next state will be. Now, when the StateManager is going to change a state then it can do so in three different ways. The three ways
The last thing I’m going to cover is the way states are rendered. Whenever the Draw() function of the StateManager gets called. Then it goes thorugh each state inside the member variable “m_current” from the back. The StateManager then checks whether the state returns true on isBase(). If it does, then all the forthcoming states Draw() function gets called. This enables the game to be frozen in the background when you have a pause screen active. Now you know how our state-manager works in Haunted Light and next week I’ll cover another part of our development and to finish things of, here’s an up-to-date screen-capture of Haunted Light ~Lead Programmer, Per “Gimmic” Johansson |
