Simple, game structuring problem

Started by
4 comments, last by Shayel 10 years, 10 months ago

Hello

I have my abstract CGameState class, which has 3 virtual functions: Logic, Events and Render. Then I have my CGame class, that contains the CGameState* object, the screen object and methods that change the state.

The main loop is like:

CurrentState->Events();

CurrentState->Logic();

CurrentState->Render();

Now, if during the application there is a need to change the state, I am using ChangeState method, which basically deletes the old CGameState* and creates the proper new one. For example:

void ChangeState(STATE_MENU)

{

delete CurrentState;

CurrentState=new CMenu;

}

And the CMenu inherites from the CGameState, to use its own Logic, Events, and Render methods.

Here goes the problem:

When there is a need to change the state, I have no access to the (Cgame game) object, because it contains the CurrentState object.. So I cannot use the ChangeState method :/ How can I do it?

Advertisement
I have my "Logic" (equivalent) function return a value that indicates whether the state should be changed or not. So the game calls "state->Logic" and then maybe calls "ChangeState" depending on the return value.
Have Logic() return a pointer to the game state that should execute next, rather than calling ChangeState directly. I usually structure my code something like this:

class GameState
{
public:
	virtual void event()=0;
	virtual GameState *logic()=0;
	virtual void render()=0;
};


void MainLoop::run(GameState *startstate)
{
	currentstate_=startstate;
	
	while(isRunning())
	{
		currentstate_->event();
		GameState *nextstate=currentstate_->logic();
		currentstate_->render();
		
		if(nextstate)
		{
			delete currentstate_;
			currentstate_=nextstate;
		}
	}
}
Note that you should always follow the format of not actually changing the current operating state until you are outside of your input/logic/render functions. If you were to call your Cgame::ChangeState method from inside CGameState::Logic(), then this would delete the object owning the Logic() method you are currently inside, potentially causing all sorts of problems. Instead, you should indicate that a state change is to be made as soon as it is safe to do so, and returning a pointer to the state to execute next is one way of doing so.

Thanks for the replies

I will change the ChangeState, so it is called outside the Render, Logic and Event functions. But now there is another question. What if the state could be set in both event section (player X'ed out, set to EXIT_STATE) and in the Logic section (player walked through the door, load next room)?

Then have either function return a pointer to the new state, and do some extra conditional checking to check both results and handle edge cases such as both methods returning a different pointer, for whatever reason.

I was thinking about creating the exit flag, so when user wants to exit(in the event part), the "exit" flag is set to true. Then on the beginning of the logic part, the flag is checked

if(exit) return STATE_EXIT;

.

.//rest of the logic part

.

.

This topic is closed to new replies.

Advertisement