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

Author Topic: State machines and map transitions  (Read 3103 times)

0 Members and 1 Guest are viewing this topic.

Henri_

  • Newbie
  • *
  • Posts: 8
    • View Profile
State machines and map transitions
« on: November 11, 2015, 10:07:59 pm »
Hello there, I've implemented a [basic] FSM in my game and it currently does its job very well. Recently I have come across a "problem" that I need to show a "Loading map. Please wait..." screen for as long the map is being loaded asynchronously. How do people usually do this? Is it considered a State?

For instance, these are the current states (in order):
IntroState (splash) -> LoadingState (loads textures, sounds...) -> PlayingState (optionally goes to PausedState)

The above LoadingState shows some kind of a progress bar while the assets are being loaded in another thread. Another information that might be important is that states operate the machine, for example, when the LoadingState finishes loading all the assets, it tells the machine to go to the playing state. The PlayingState has a Map object. For reference, see here: https://github.com/YvesHenri/Chico/tree/master/Game/Includes/Core/Engine/State

My current approach (which is not yet commited to github) is to make the Map object a "LoadingObservable" and the PlayingState a "LoadingListener" (observer pattern), so that inside the load call it will notify all of its listeners and theyre responsible of telling the FSM to go to the next or to go back to the previous state in the queue. Is this how people usually do that? Are there any easier/better ways to do that?

If this sounds a bit confusing please feel free to ask. Also, I'm always open for criticisms, if you have any, on my code.


BlueCobold

  • Full Member
  • ***
  • Posts: 105
    • View Profile
Re: State machines and map transitions
« Reply #1 on: November 11, 2015, 10:14:28 pm »
Imo screw the concept of queues or stacks. That's not how a state machine works anyway. Typically they can go from any state to any other. Mostly they don't even need more than the last state (for example to return from pause to play), as they barely ever go back and mostly only go forward.
In our game, we don't use any queue or stack at all. There's one state at a time and we can go from one to another. While doing so, we're sometimes passing additional informations to a state in order to "resume" an old one (we don't resume, we just go forward to the a new state of the same type as the previous one by passing that info). Never had any issues and never had any memory overhead due to a queue which is filled, but unused.
« Last Edit: November 11, 2015, 10:16:59 pm by BlueCobold »

Henri_

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: State machines and map transitions
« Reply #2 on: November 11, 2015, 10:27:50 pm »
Hi there, BlueCobold. Thanks for the input.
I've seen a couple opinions over the internet about FSMs: stacks vs single states. Each of them have their cons and pros. Indeed I could opt for single states and have a pointer to the current state and it would be passed to any other state that needs them (PausedState, for example). This is basically how I've done but thats not the problem here. The problem is that I have no idea how to, or even if I have to, show transition effects (such as displaying the "Loading map. Please wait..." string), given that the PlayingState has a game Map object and it contains "teleports" that will trigger a map load. This is also supposed to work on forcibly load calls (when loading the game from a file, for example). Since the Map knows nothing about States, thats why I thought about using the Observer pattern, but I'm unsure if thats how people do that. By the way, you did not answer my question  :P

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: State machines and map transitions
« Reply #3 on: November 12, 2015, 02:44:51 am »
This is a sort of 'internal' or minor state within a major state?
You could use a flag or enum to keep track of current minor state and perform certain functions based on that enum/bool. e.g. if the enum states that map is loading, don't perform updates on gameplay.
 
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

BlueCobold

  • Full Member
  • ***
  • Posts: 105
    • View Profile
Re: State machines and map transitions
« Reply #4 on: November 12, 2015, 07:20:14 am »
In our game, transitions are a state themselves. That means that for example from the pause state to the game state, we have an intermediate state which renders both of the others to a renderbuffer and then uses these to make fancy transitions with it. When done, it switches to the 2nd state-parameter of the transition.

Mario

  • SFML Team
  • Hero Member
  • *****
  • Posts: 878
    • View Profile
Re: State machines and map transitions
« Reply #5 on: November 12, 2015, 08:33:02 am »
There are many different approaches for something like that. IMO you shouldn't even have to load your stuff asynchronously, unless it really takes a while and is hidden behind something else, like gameplay. If you've got a loading screen, just do it in your main thread.

One approach I'd try, is to keep other states clean of your loading mechanic:
  • States queue their preloaded resources in their init() or enter() function, which is called once the state activates.
  • Once that call is done, you could check how many resources there are to load, if it's above some threshold, a loading state is automatically pushed/entered, which will render the loading screen and load assets.
  • The loading state is left once all resources have been loaded/processed, returning control to the "new" state entered before.
As for transitions and such, this really depends on what kind of transitions you want (like fading to/from black or alpha blending).

Henri_

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: State machines and map transitions
« Reply #6 on: November 12, 2015, 08:01:54 pm »
This is a sort of 'internal' or minor state within a major state?
You could use a flag or enum to keep track of current minor state and perform certain functions based on that enum/bool. e.g. if the enum states that map is loading, don't perform updates on gameplay.

Hey, Hapax. From what I understood, this might be an internal or a small state. All it does is show a "Loading map. Please wait..." screen for as long the map is being loaded, as stated before a few times. If you looked at my github you would of have seen the state machine working flawlessly (as stated before as well), so opting for enums or whatever else is not what I'm struggling with.

There are many different approaches for something like that. IMO you shouldn't even have to load your stuff asynchronously, unless it really takes a while and is hidden behind something else, like gameplay. If you've got a loading screen, just do it in your main thread.

One approach I'd try, is to keep other states clean of your loading mechanic:
  • States queue their preloaded resources in their init() or enter() function, which is called once the state activates.
  • Once that call is done, you could check how many resources there are to load, if it's above some threshold, a loading state is automatically pushed/entered, which will render the loading screen and load assets.
  • The loading state is left once all resources have been loaded/processed, returning control to the "new" state entered before.
As for transitions and such, this really depends on what kind of transitions you want (like fading to/from black or alpha blending).

Hi, Mario. About asynchronous calls, I believe this is not "optional" but a must have. You should never have your game window frozen, not even for a few half seconds, but that just my opinion. However, in this case, the map loading does take a while (13 seconds in debugging and ~700 milliseconds on release) and is hidden behind the PlayingState, if that's what you meant.
The states themselves does load or do whatever else on their "init/enter" functions, but that applies only for the LoadingState (which is not the same as map loading) and it does work as expected (asynchronously with a progress bar). Having fade effects right now would just be a "plus". I'm making it very simple and focusing on only showing that "Loading...." string on screen.

I believe none of you got me right so I'll just try to explain clearer and again:
I'm stuck on the part that I will have to display the map loading screen (lets call it TransitionState) when the map loads, either from map.load() (forced) or from the map.update() function (dynamic), when the player enters in a teleport, for example. Like I said before, the only way I could come up with is to use the observer pattern. Map would be a LoadingNotifier and the PlayingState a LoadingListener. Is that right or are there any easier/other ways people usually do that? Hope its clearer now.

Thanks for all the input, all of you.

Mario

  • SFML Team
  • Hero Member
  • *****
  • Posts: 878
    • View Profile
Re: State machines and map transitions
« Reply #7 on: November 12, 2015, 08:23:58 pm »
How does your worker thread know what it has to do? Sounds like you're notifying the worker that there's stuff to do, so shouldn't the worker trigger the loading screen, because it knows how long it should take?

Henri_

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: State machines and map transitions
« Reply #8 on: November 12, 2015, 09:57:15 pm »
How does your worker thread know what it has to do? Sounds like you're notifying the worker that there's stuff to do, so shouldn't the worker trigger the loading screen, because it knows how long it should take?

The worker thread youre talking about is the one that the assets are being loaded? Also, there are 2 types of "loadings". The one that loads the assets (which is in LoadingState) and the map loading, which I am still thinking how to do that (for instance, I created the TransitionState that will load the map pointer and pop the machine stack afterwards when the loading is finished). You can see here: https://github.com/YvesHenri/Chico/tree/master/Game