Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: State machines or Screens?  (Read 14138 times)

0 Members and 1 Guest are viewing this topic.

Hair_FTW

  • Newbie
  • *
  • Posts: 6
    • View Profile
State machines or Screens?
« on: September 16, 2011, 01:25:55 am »
So i'm kind of new to SFML, i've done some stuff but only in one screen/state and not oop.

I was going to make a game with various levels and menus (for learning porposes) and i was wondering which mettod should i use? State Machines or the cScreen class?

State Machines on SDL: http://lazyfoo.net/articles/article06/index.php
cScreens: https://github.com/SFML/SFML/wiki/TutorialScreens

I've never used one neither the other, so which one should i learn? cScreen can only be used in SFML so maybe it's better to learn State Machines? Also State Machines seems more oop-drive i think, while cScreens seems more like an easy and fast solution (kind of transforming non-oop code into a kind-of-oop code).

What do you think? Should i go for State machines or cScreens class?
Cheers

thePyro_13

  • Full Member
  • ***
  • Posts: 156
    • View Profile
State machines or Screens?
« Reply #1 on: September 16, 2011, 05:31:09 am »
I think you should consider that both of your links are implementations of State Machines.

You should learn State Machines. The specifics of the lazyfoo example and the cScreen example are just implementation details.

Hair_FTW

  • Newbie
  • *
  • Posts: 6
    • View Profile
State machines or Screens?
« Reply #2 on: September 16, 2011, 09:04:06 pm »
Isn't Lazy Foo's example a generic State Machine? I though so.

Do you know any good tutorial on State Machines?

Walker

  • Full Member
  • ***
  • Posts: 181
    • View Profile
State machines or Screens?
« Reply #3 on: September 17, 2011, 03:53:38 am »
Quote from: "thePyro_13"
I think you should consider that both of your links are implementations of State Machines.


The links you provided are both tutorials on state machines. Lazyfoo's even goes into different types before explaining the very robust system he suggests using.

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
State machines or Screens?
« Reply #4 on: September 17, 2011, 10:56:03 am »
I have to say Screens look way more complicated and way more inflexible. I would go for state machines. It's quite easy. Can you write a Stack data type and an update function? There you go. The data types itself handles the behaviour you want.
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

Haikarainen

  • Guest
State machines or Screens?
« Reply #5 on: September 17, 2011, 11:49:50 am »
I just have an enum in my root-class (OOP, Always!) wich says INTRO, MENU, LOADING, GAME etc. And then in my Menu-class i have an enum like  MAIN, OPTIONS, VIDEO, GRAPHICS etc.

Then in update and draw i just switch the enum. Makes it easy to make everything fit seamlessly into each other(resourceloading, maploading etc).. Also in the beginning of update and draw i make sure to do stuff like
Code: [Select]

If(!this->Environment->Map->IsLoaded() && this->State == GAME){ this->State = MENU; }


This way i dont have to deal with the states all the time ( if i just do Map->Unload() it'll return to menu automatically)

keyforge

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
State machines or Screens?
« Reply #6 on: September 18, 2011, 08:15:34 pm »
Quote from: "Haikarainen"
I just have an enum in my root-class (OOP, Always!) wich says INTRO, MENU, LOADING, GAME etc. And then in my Menu-class i have an enum like  MAIN, OPTIONS, VIDEO, GRAPHICS etc.

Then in update and draw i just switch the enum. Makes it easy to make everything fit seamlessly into each other(resourceloading, maploading etc).. Also in the beginning of update and draw i make sure to do stuff like
Code: [Select]

If(!this->Environment->Map->IsLoaded() && this->State == GAME){ this->State = MENU; }


This way i dont have to deal with the states all the time ( if i just do Map->Unload() it'll return to menu automatically)


This is ok for less complex games, but as your games complexity increases you might want to make a state machine.

My take on the state machine is to create an interface class GameState, which has virtual functions for input, updating, and rendering. Creating a game state is basically inheriting GameState and implementing the virtual functions (Input for events, update for game logic, and render for drawing stuff).

Next I make a class called StateStack, which holds a vector of GameStates. The StateStack class has functions for pushing and popping states, getting a pointer to the active state, etc. Popping a state off the StateStack will activate the new bottom of the StateStack.

Then in your game loop you'll want to have it setup like so:
Code: [Select]

mStateStack.Push(new Map_GameState);

while(running) {
  while(logic timestep stuff) {
    while(pollevent(evt)) {
      mStateStack.GetTop()->OnEvent(evt, input);
    }

    mStateStack.GetTop()->OnUpdate(delta);
  }
 
  mStateStack.GetTop()->OnRender(window);
  window.Display();
}

You might want to do some research on Stacks too.
Need a place to upload your code, files or screenshots? Use SFML Uploads!

Vit

  • Newbie
  • *
  • Posts: 14
    • View Profile
State machines or Screens?
« Reply #7 on: October 20, 2011, 12:28:04 pm »
A bit of a bump, but related to the topic:
In my game, I've implemented a state machine system similar to the one keyforge described. However, I've run into a problem - returning values from a state being popped to the new (previous?) state. As an example, my game allows the player to name their character. This means I need a name input state. However, I can't think of a good way to pass the result of the name entry back to the character creation state... Any suggestions?

thePyro_13

  • Full Member
  • ***
  • Posts: 156
    • View Profile
State machines or Screens?
« Reply #8 on: October 20, 2011, 01:48:30 pm »
You could pass references to relevant(or parent) states in the state creation request.

Or maybe create a shared event queue for states to transfer data between themselves. Though that might be more trouble than it's worth.

keyforge

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
State machines or Screens?
« Reply #9 on: October 20, 2011, 04:36:16 pm »
Vit,

Another way I've seen it done is to have a state machine that only stores a pointer to one state, and each state has a virtual function called Run() which returns a pointer to whatever state should come next, so if you clicked the play button it would return a Game state, and that Game state could have functions to choose a certain level, so you could return a Game state object after calling Game->SetLevel() so that object has the current level saved.

Code: [Select]

static void GameState::Start(GameState* state)
{
      while(state)
      {
            GameState* next = state->Run();
            delete state;
            state = next;
      }
}


Code: [Select]

if(myLoadLevelButtonWasPressed)
{
      Game_GameState* gameState = new Game_GameState();
      gameState->SetLevel(myInputBox.GetString());
      return gameState;
}

if(myExitButtonWasPressed)
{
      return 0;
}


You should call GameState::Start(new Intro_GameState(pass render context, or anything you need here) at the beginning of your application, and your game states have full control of the rest of the programs flow.
Need a place to upload your code, files or screenshots? Use SFML Uploads!

TheCake

  • Newbie
  • *
  • Posts: 19
    • View Profile
State machines or Screens?
« Reply #10 on: October 21, 2011, 09:59:08 am »
Hello

This subject highly interests me. I've been confronted to state machine designs issues (I'm still a beginner in game programming). For my last project, I used the implementation given by the LazyFoo tutorial.

My main problem was that retrieving data from a previous state was a real pain in the ***. It seems Vit got a similar problem.
My question is : if you pass the previous state pointer to the constructor of the new one, is there another way than casting the pointer (which is an abstract GameState class pointer) to be able to get some data ?
I never really used casting, and in my mind, if you need to cast, this means the program design is flawed. Is it true ? Or is casting something common ?

Thanks for your advices, I hope what I asked was understandable (I don't speak english very often ...).

PeterWelzien

  • Newbie
  • *
  • Posts: 38
    • View Profile
State machines or Screens?
« Reply #11 on: October 21, 2011, 10:53:55 am »
In my state machine each state creates whatever state to come next. Eg. MainMenuState creates a PlayGameState and push it on the state stack when the player hits "Play". And PlayGameState creates a GameOverState. That way the main menu can insert the player name in the PlayGameState class. And PlayGameState can insert the final score in the GameOverState class.
/Peter Welzien

TheCake

  • Newbie
  • *
  • Posts: 19
    • View Profile
State machines or Screens?
« Reply #12 on: October 21, 2011, 11:26:59 am »
Thank you PeterWelzien, I think I'll try something that follows your idea.

keyforge

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
State machines or Screens?
« Reply #13 on: October 21, 2011, 09:42:00 pm »
Quote from: "TheCake"
Hello

This subject highly interests me. I've been confronted to state machine designs issues (I'm still a beginner in game programming). For my last project, I used the implementation given by the LazyFoo tutorial.

My main problem was that retrieving data from a previous state was a real pain in the ***. It seems Vit got a similar problem.
My question is : if you pass the previous state pointer to the constructor of the new one, is there another way than casting the pointer (which is an abstract GameState class pointer) to be able to get some data ?
I never really used casting, and in my mind, if you need to cast, this means the program design is flawed. Is it true ? Or is casting something common ?

Thanks for your advices, I hope what I asked was understandable (I don't speak english very often ...).


That design seems flawed. The states shouldn't know anything about each other. My 2nd design posted above is something you should consider, as it allows you to create a pointer to the next state you want, manipulate the pointer's variables (either via public variables or getters/setters), and then return it back as the next game state. The 1st design I posted above could also do this with a little tweaking.
Need a place to upload your code, files or screenshots? Use SFML Uploads!

TheCake

  • Newbie
  • *
  • Posts: 19
    • View Profile
State machines or Screens?
« Reply #14 on: October 25, 2011, 09:52:51 am »
I should have seen your second design earlier ... Because it's kind of similar to what PeterWelzien suggested. Thank you, this is what I'm going to consider for my next design.

But I have a new question. I saw some designs given in this thread that use a stack of states, with the running one one top of the stack. Is it really useful to store old states ? Do you have an example of situation where this could be necessary ?