Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411411 Posts in 69360 Topics- by 58415 Members - Latest Member: sophi_26

April 15, 2024, 08:59:05 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)How do I transition from one game state to another?
Pages: [1]
Print
Author Topic: How do I transition from one game state to another?  (Read 1137 times)
JK
Level 0
**



View Profile
« on: August 04, 2015, 07:03:29 AM »

So I have a base class called GameState. I have derived classes MenuState and PlayState.

I declare an object of GameState and set it equal to "new MenuState" or "new PlayState". The game loop looks like this.

while( gameIsRunning )
{
    game->HandleEvents();
    game->Update();
    game->Draw();
}

How do I transition from one to the other? Concerned Can I do it internally, or should I create a StateManager class?
Logged
ProgramGamer
Administrator
Level 10
******


aka Mireille


View Profile
« Reply #1 on: August 04, 2015, 07:13:38 AM »

You could make a function which changes the game state to whichever one you want, and in there you could handle things like freeing the old state's memory or making sure that the argument is valid before doing anything. you don't really need a state manager until you want to start having multiple states in memory at once, which is only really useful for technical stuff anyways.

I'm assuming of course that "game" is your pointer variable to the active game state. As long as you can change that pointer to either one of your states, you should be fine.
Logged

JK
Level 0
**



View Profile
« Reply #2 on: August 04, 2015, 07:24:33 AM »

Oh. Well that simplifies matters! Therefore...

void ChangeState(GameState *state)
{
    // logic for MenuState to PlayState transition here
    delete state;
    state = new PlayState;
}

I've never used the "new" and "delete" keywords before this particular game, so I don't know if that is correct syntax or not. If so, that's pretty nifty.
Logged
ProgramGamer
Administrator
Level 10
******


aka Mireille


View Profile
« Reply #3 on: August 04, 2015, 08:30:59 AM »

yes and no. You actually want to pass the pointer's address from your main code into the function, that way you still delete the old state but you also store the new one in the variable that was in your main scope. If my c++ memory is correct you simply need to add one star in front of the two "state"s in your code.

Let me just double check that though.

Edit: I did my homework and here's en example of what should work and how it does.
Code:
#include <iostream>
using namespace std;

void changeToFive(int **funcPointer);

int main()
{
    //making a pointer to int and initializing it with the adress of a new int
    int *pointer = new int;

    //Initializing the int which "pointer" points to with 3
    *pointer = 3;

    //Returns the value of the int which pointer points to
    cout << *pointer << endl;

    //Calls the function that gets you a brand new int!
    changeToFive(&pointer);

    //Returns the value of the int which pointer points to, again
    cout << *pointer << endl;

    //return 0, duh :)
    return 0;
}

void changeToFive(int **funcPointer)
{
    //Deleting the int which "pointer" pointed to
    //Also worth noting, in the function scope, "funcPointer" points to the pointer "pointer" back in the main scope
    delete *funcPointer;

    //Creating a new int and storing it inside "pointer", which "funcPointer" points to
    *funcPointer = new int;

    //Initialising the int which "pointer" points to with 5
    **funcPointer = 5;
}
« Last Edit: August 04, 2015, 08:58:06 AM by ProgramGamer » Logged

JK
Level 0
**



View Profile
« Reply #4 on: August 04, 2015, 11:33:23 AM »

Yea you're right, my game wouldn't compile after I tried the code in my original post. After performing some google foo I ended up changing the line to ChangeState(GameState *&state){/*stuff*/} and it works now  Smiley

Thanks a million for the huge refresher on pointer logic! I really wish I'd seen your reply earlier Coffee
Logged
Cheezmeister
Level 3
***



View Profile
« Reply #5 on: August 05, 2015, 11:06:25 PM »

Rather than deleting the old state and replacing it, you may wish to store a stack of states and push/pop as you transition. This comes in handy for example to show a pause screen.

Just something to think about down the line Wink
Logged

෴Me෴ @chzmstr | www.luchenlabs.com ቒMadeቓ RA | Nextris | Chromathud   ᙍMakingᙌCheezus II (Devlog)
JK
Level 0
**



View Profile
« Reply #6 on: August 06, 2015, 04:34:39 AM »

Rather than deleting the old state and replacing it, you may wish to store a stack of states and push/pop as you transition. This comes in handy for example to show a pause screen.

Just something to think about down the line Wink

Duly noted, friend. Thanks!
Logged
ProgramGamer
Administrator
Level 10
******


aka Mireille


View Profile
« Reply #7 on: August 06, 2015, 04:42:48 AM »

Yep, had not thought of that at all, I don't even actually know how to pop and push things from a stack. Still, I know pointers at least! Tongue
Logged

SamSerious
Level 0
***


View Profile
« Reply #8 on: August 07, 2015, 09:56:14 AM »

I call my states "screens" and those lend the design from java applets. kind of
Code:
class Screen
{
public:
 virtual std::string Name()=0;//a name, like e.g. "logo" or "main_menu"

 virtual bool Create()=0;//called once during initialization of the game
 virtual bool Resume()=0;//called before it's used
 virtual void Suspend()=0;//called before switching to other Screens
 virtual void Release()=0;//called once at the end of the game

 virtual Next Update()=0;//called 60times/s
 virtual void Paint()=0;//called as fast as it gets
};


now the magic is mostly the "Next" object that gets returned from the update function, it tells the game loop how to proceed with the screens
Code:
enum NextStack
{
 EN_NOP,
 EN_PUSH,
 EN_POP,
 EN_SWITCH
};
struct Next
{
  std::string Name;
  NextStack Action;
};
;

the initialization looks something like this
Code:
main(..)
{
std::vector<Screen*> Stack,Screens;

Screens.push_back(new Logo());
Screens.push_back(new Menu());
Screens.push_back(new HighScore());
....
for(size_t a=0;a<Screens.size();a++)
 if(!Screens[a]->Init())
 {
//handle init fail
 }

Screen* pCurrent = Screens[0];//just assume that's the logo, but for deving you might want to start straight in-game
if(!pCurrent->Resume())
{
//handle init fail
}

while(pCurrent)
{
 Next N = pCurrent->Update();
 switch(N.Action)
 {
 case EN_NOP:break;
 case EN_PUSH:
  pCurrent->Suspend();
  Stack.push_back(pCurrent);
  pCurrent = Screens.find(N.Name);//pseudo code, but lets keep it simple here
  if(!pCurrent)
  {
   //handle fail
  }
  pCurrent->Resume();
 break;
 case EN_POP:
  pCurrent->Suspend();
  pCurrent = Stack.pop_last();
  if(!pCurrent)
  {
   //handle fail
  }
  pCurrent->Resume();
 break;
 case EN_SWITCH:
  pCurrent->Suspend();
  pCurrent = Screens.find(N.Name);//pseudo code, but lets keep it simple here
  if(!pCurrent)
  {
   //handle fail
  }
  pCurrent->Resume();
  break;
 }

 if(time_left)
   pCurrent->Render();
}

for(size_t a=0;a<Screens.size();a++)
 !Screens[a]->Release();

the logo screen returns
Code:
Next Update()
{
  return CurrentTime-StartTime>10seconds?Next("menu",EN_SWITCH):Next("logo",EN_NOP);
}
the menu screen pushes itself and points at the "new game" screen, or "options" or "highscore", so if those end, those can "pop" to the previous state, that way also the game could push "options" or "highscore" and those would return to the game instead of the menu
This works not only for big states, if e.g. you had a game like GTA where you're roaming in a sandbox world, you could create "screens" for every mission type and push/pop those while the big "game" screen is kinda the stack base you return to all the time.
Logged
BlackseaOdyssey
Level 1
*



View Profile WWW
« Reply #9 on: August 10, 2015, 04:51:30 AM »

Definitely use a State Machine. Smiley
Logged

Allen Chou
Level 0
**



View Profile WWW
« Reply #10 on: August 10, 2015, 09:41:43 AM »

You can also try action lists.

I wrote a post about it, and there's a

of a lecture session from DigiPen's Game Engine Architecture Club.

It is possible to use an action list framework to simulate a full-blown state machine framework. Further, the lane structure can be used to simulate "stacked states" mentioned earlier in this thread: making a blocking action and push it in front of a lane simulates a state push; completing the blocking action and pop it off the front of the lane to allow the previous active action to kick back in simulates a state pop.
Logged

Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic