Multiple Game modes and AppState initialization dependencies

Hello monkeys,

I’m not too good at architecturing my lil game so I would like some opinion on my following “idea”:

I want my game to be able to easily support different playing modes, such as race versus opponents, best lap race with a ghost looking car representing your best lap path, slalom and so on.

For that, I went the following road:

  • GameModeState that represents the type of game (slalom, simple race etc)
  • GameState that represents the steps of a GameModeState (lobby, first race, re-lobby, second race (for a campaign for example))
  • AppStates in which the initialization occurs for a GameState (one for building the track, one for building a vehicle, one for adding slalom gates, etc)
  • A GameManager that would do the switching from one GameModeState to another
  • A GameModeStateManager for each GameMode that would deal with switching from one GameState to another

The problem I face is that some of those AppStates require other AppStates to have been fully initialized before they can be initialized. For example, a public camera requires the vehicle to have been initialized via it’s LoadVehicleAppState.

So I thought:

  • Each AppState would have a list of AppStates required before initializing it.
  • I’d make a generic AppState whose update method would take care of attaching the other AppStates via it’s update method depending on if their dependency AppStates were already initialized. Once all AppStates would be initialized, it would detach itself.

Does this make you want to scream :D… any better way for:

  • multiple game modes
  • AppStates initialization when they depend on other AppStates being already initialized

Sounds okay, you could even let the single AppStates manage the ones they need themselves but having one where you can configure the “dependencies” sounds nice too. Implementing it is the best way to see if it works out :wink: You code, you learn :smiley:

2 Likes

Thx normen… I was afraid I was doing something awfully wrong but I’ll go ahead then and see where it brings me.

I’ve considered doing things with dependency lists a couple of times in my own work… but it turns out that it rarely comes up as most of the time dependencies are only coded in one place.

To me it sounds like you may have too many app states or that the break down may be done differently/better. For example, in the long run it is probably better to prefer more general app states that can be run all the time instead of 9 level-specific ones or whatever. This also makes it easy to add them in the proper order since most of them will be attached only once near startup.

For example, in Dragonfly Odyssey so far, I have 23 non-JME app states when the game is running (and 4 JME ones). 9 of these are attached when the app starts up and includes the MainMenuState. I have one GameAppState that attaches the others when the ‘play game’ starts. None of those app states are ‘mode’ specific. That main GameAppState swaps between two different camera movement states as needed (actually just mutually enables/disables them) and if I had multiple ‘levels’ or game modes then it’s the GameAppState that would manage that, too.

If you can find a similar path then you will be much happier in the long run as debugging and maintenance will be 100 times easier.

3 Likes

I suggest you to back with pencil and paper for a while:

  • “State” is a programming paradigm, a way to organize your execution, flows and data… that may suite your game well.
  • You should choose “bottom up or top down design” for your game with confident (when confuse read more) http://en.wikipedia.org/wiki/Top-down_and_bottom-up_design . Mainly depend on your game is “small” or “big”?

Some wisdom for states in gamedev, in JME3 and also in abstract level:

  1. You should categorize your states, and Data:
  • “GameMode” State which is only one of their kind at a time.
  • “Service” State which work underground
  • “Stateful” objects and data that may stick with one state and invalid or not useful in another. ( Should be cleaned or save in a Cache for sometime…)
  • “Stateless” objects and Data may work perfectly with any GameModes, Services and have variable lifespan.

Some characteristics of State paradigm are “over used” everywhere, but commonly:

  • “Node state” which has dependencies in other State (and Data), composed and a structure like graph
  • “Module state” which separated from each other, can be used by plugins.
  • “DrivenState” which drive by another Service like a StateMachine (compose of input, conditions and a pointer)
  • Transistions of State: blending, replacing, …
  • … other kind of States
  1. You should layout your states when design your game execution, flows and according to game mechanism.

For example: It’s should be easy to layout 2 dimension table of GameMode states as Column and Service states and Data as Row.

Professional game designer and engineer also come up with Graph diagram to resolve and organize dependencies states. They may also take a step forward to organize Data (of those State), one of common approach called Entity Component System (ECS) . In ECS, Data is like fragments, loosely depend in others and very composable. That characteristic make it ideal to work with as Data for “State” - system, as the State will contain and resolve the logic, but Data are stay out of the way…

“States design” is not the only way around, but is quite well adapt for wide range of cases. The job also may cause headache if you are not prepared or getting confused in the middle…May be back a little bit with pencil and paper and layout them first.

Cheers,

2 Likes

First, thx for your answer pspeed.

I’ve read your answer a couple times (because I’m obtuse) and will read it a couple more times to be sure I got it right.

A couple notes in the meantime just to be on the safe side:

  • by game mode, I mean one map race or a campaign of races or racing against oneself with a ghost car and so on.
  • Most of my AppStates are “generic”… to be used for multiple different game modes. Loading a vehicle, loading a circuit, listening to input, controlling the camera, controlling the rear-view are all generic (and most done already) since whatever the game mode, they will function the same way.
  • Some AppStates will only be used for some GameModes, such as adding slalom stuff, adding a ghost car, displaying the circuit editor (and later on, vehicle editor), and so on.

If I got you right, using an AppState to load the other AppStates is a good way. But, instead of AppStates having a list of dependencies, you would check dependencies when you specifically attach the specific AppState via code?

If I got you right, you would have >>one<< GameAppState responsible for all AppState attach/detach-enable/disable for all GameMode s and GameState s? Wouldn’t it end up bloated?

I have no doubt you architecture your stuff better, and I’m just finishing a huge, painful refactoring of most of my code where everything was >>way<< too inter-connected, so I’m trying to make sure I get you right.

Now, to read atomix answer and fry some brain cells on it :D.

-edit- wondering now if your main objection was about having GameStates instead of just enabling/disabling - attaching/detaching AppStates directly in the GameMode?

Some technical insights:

The StateMachine, which work as “a driver of your states”, which I may referred as StateMachineService is the main function of my framework Atom, which used Guava and Guice intensively, with these approaches you may interested in:

  • Dependencies and the creating of Module or Node state are handled by DependencyInjection (Guice specificly)
  • AppState and Service interfaces (of Guava) together make ServiceState. Warpers for JME specific functions called Managers (for Application facilities) and Helpers (for SceneGraph facilities).
  • Stateful objects and data are organized in Generic Map, Tree, Graph structures. The execution flow and rythme over data are push or pull unit by unit (as Actor, as Task, as Runnable), make them concurrently healthy. Also we can go complete no-string-attached with Entity System after.

Cheers,

1 Like
@loopies said: If I got you right, you would have >>one<< GameAppState responsible for all AppState attach/detach-enable/disable for all GameMode s and GameState s? Wouldn't it end up bloated?

How would it be bloated? At best, it’s managing only a handful of states. It doesn’t have to ‘check’ anything because you are the one writing the code and you will know what needs to come first.

Though, in general, I think for non-service-level app states you should keep dependencies to a minimum and decouple them as much as possible. But again, I have trouble thinking in the hypothetical here because I’ve never run across the use-case for game-logic states needing to access each other. My states only ever access the service-level stuff.

So maybe you have a set of mutually exclusive states for each “mode”, one app state per mode, but everything else is a service that is simply attached for all modes. In that case, you’d have one “main game” state that sets up all of the services and then figures out which ONE game mode state to attach. No bloat there.

1 Like

I’ve read your posts atomix and pspeed and thinking about them… need to rush out to help my nephew with some maths but will come back after that. Until then, thx for your insights :).

@ - pspeed:

My game flow is as follow:
a) home and config stuff such as options-controls-profiles-other stuff
b) user enters lobby mode (that would default towards one GameMode (let’s say simpleRace))
c) (optional) user changes GameMode (for example, campaign mode (succession of races))
d) user modifies play game options (GameMode options can differ)
e) user activates play game
f) play game AppStates are initialized
g) user dildoes around until an AppState decides it’s time to stop the race
h) in case of campaign game mode, an intermediary screen (later on with ability to buy boosters)
i) in case of campaign game mode, next race starts
j) when campaign ended or single race ended, a different screen (per game mode) is displayed
k) user can relaunch or change game mode or get back to a)

I was thinking implementing it by:
a) GameMode BasicMenus, with an AppState displaying the screen
b) switches to SimpleRaceGameMode, in SimpleRacelobbyGameState, with an AppState displaying the screen
c) switches to CampaignGameMode, in CampaignlobbyGameState, with an AppState displaying the screen
d) screenController records the options changes
e) switches to CampaignRaceGameState
f) CampaignRaceGameState AppStates are initialized
g) inputListener sends messages to services, which in turn, for example, send orders to vehicleAppState(s)
h) switches to CampaignIntermediaryGameState
i) switches to CampaignRaceGameState + AppStates initialization
j) switches to CampaignResultsGameState
k) switches to CampaignlobbyGameState or switches to SimpleRaceGameMode or BasicMenusGameMode

I just don’t see how I could handle multiple GameModes with different GameStates, different options and different screens and some specific AppStates during play from one (non-bloated) class. I would love to… just haven’t found a way. Not being a smartass… just an idiot :D.

Before the refactoring, I was having problems (resolved in a way I didn’t like) that made me think that attaching AppStates in the correct order wasn’t enough to make sure AppStates were initialized when needed.

@ - atomix:
I think I’m going bottom to top in the sense that I’m doing a too big game for me to be able to go at it any other way but incrementally, focusing on one system at a time. Also my first game and basically I knew nothing when I started apart from some experience in java.

I thought about using Spring for dependency injection but thought it was too cumbersome for that… and decided to forgo it for now. I’ll check your Guice see how fitting it is.

Not gonna use Guave… seems to be meant for people that have more clue about their needs than I do.

I used an ES at start but never understood why people were adamant only one component of one type (per entity) was ever needed and so went with the idea that I was not doing it right and therefore was going for the wall and ended ripping it out. I have no idea how to deal with 2 missiles hitting a car for example.

@ - both: not being a smartass… just frankly incompetent lol.
Maybe the best is for me to just go for it and embrace the impending doom :D.

How I might do it… and I guess if your using nifty then you might have an app state per screen which is useful there but still kind of unfortunate.

MainMenuState - the main landing point. Your SimpleApplication would setup basic service app states and the MainMenuState. For example, my DragonflyOdyssey’s app constructor looks like this:

[java]
public Main() {
super(new StatsAppState(), new DebugKeysAppState(), new BasicProfilerState(false),
new AnimationState(),
new SoundManager(),
new MainMenuState(),
new LightingState(0.35f),
new SkyState(),
new SkySettingsState(),
new MusicState(),
new PostProcessingState(),
new CreditsState(),
new ScreenshotAppState(“”, System.currentTimeMillis()));
}
[/java]

MainMenuState manages the main menu and potentially any subscreens… if you have an app state per screen then you could attach them in main, too. Really, though, I prefer to keep as few states here as makes sense. Since options are reusable (like for the in-game menu) then I might leave options as a separate state that MainMenuState attaches. These would always be attached and simply enabled/disabled as needed. (BaseAppState for the win)

In your case, probably a lobby state also. I don’t see any reason to have multiple lobby states. To me they shouldn’t be any different functionality-wise.

The player may use mode-specific UIs to configure the settings for the ultimate game they will run. This is not really an app state thing, though. You have a UI you pop up to get info that is mode-specific but it doesn’t need to be a state on its own. (If you are using nifty maybe you will have screen controller states but I consider that an artifact of nifty and not a ‘design’, really… so you may have a state per screen but lets not count those as real app states for this discussion. They are idiomatic byproducts of the boiler plate that makes nifty easier to deal with and are basically unnecessary in other libraries. Not knocking nifty but let’s not consider these in the same vein as the other app states which implement your app functionality.)

Once the player has configured the game they want to play through the game-mode specific UI, then that information is used to launch the game mode specific app state. SingleRaceState, CampaignState, whatever. They will manage all of that. At worst, they will be attaching some app states (probably shared by both) and monitoring the state of the game.

@loopies said: I used an ES at start but never understood why people were adamant only one component of one type (per entity) was ever needed and so went with the idea that I was not doing it right and therefore was going for the wall and ended ripping it out. I have no idea how to deal with 2 missiles hitting a car for example.

I’d have to know more about your example but in general if you need multiple things attached to an entity… then they aren’t components, they are entities. “But I want to have a bunch of gun turret components!!!” No, you want to have a bunch of gun turret entities. “But I want to attach a bunch of damage components.” No, you want to attach a bunch of damage entities… and those entities might have half a dozen components describing the type of damage. (Is it fire damage, electric damage, ongoing damage, does it have a debug name, does it have a creator component tying back to who dealt the damage, and so on.)

In all cases I’ve ever come across where “I want to have multiple components” comes up, the design opens up tremendously by doing it a different way. Components are attributes. So it’s very strange to have two of a kind.

1 Like

Ok,

what i usually do is very alike the approach of pspeed.

but i prefer to adapt and write my code in another ways, for some cases (the game is small, the team is small, the time limit is rough…). So there are another ways of course.

I usually do this for “big” and complex architecture game (involve services, database, a lot of 3rd libs). One word: GENERIC!

-“init” or “create the reference” to my “Global scope” States by inject into App instance.
-“start” of “trigger the running phase” of these Global State along with the start of the App, aka simpleInitApp method.
-“end” of “trigger the disposing phase” of Global states along with the end of some services, or end of the whole app.
-A Global state may have child states, a Generic State Container in charge of Drive those inner state.

  • Overal, they form a Collection or a Tree of states, you can see the form its various because of the depth of nesting.
  • The execution flow: usually refered as updateLoop or the “tick” or “rymthe” is also from outside, via a Generic iterator, mostly a Collection iterator for GlobalState, a Tree iterator for more than 2 two level of nesting.
  • Beside of that ordered execution routine, there are a few routine can be indicate as “Run as fast as possible routine” where Actor, Task and some other parallel facilities used to gather and distribute the CPU and GPU resource. This routine is picked by design depend in scenarios and analysis. Well, because they are not very controlabe!

Here is some SHOULD:

  • Along with Execution, Data should be aligned to serve whenever the State require them triggered. In a “big” game, you may want to place your Data handy, likely in a Cache (Pool, Singleton, Enums…).
    -The call to create, recreate, maintain and monitoring Data is from Services (not from the State), the State is likely to be a Consumer of that Data only. The more you make your State code become Consumer only, the bigger the Data need to be prepare beforehand, but the more convenient you reach the data, and cleaner the code become.
  • My team always think of a GAME, like a MediaPlayer, play back STATIC data in this way or other…
  • Dependencies of States are aligned with their structure. This HELP a lot! I saw you talking about you can not resolve your dependencies of Datas, UI Screens , etc… for the States. That’s because you not organize them good enough! In almost case and game genre, a TREE will have, and remember to put dependencies in sibling of a same root, same level, and not outside of that root. This pattern usually referred as Hierarchical State (Machine).
  • Dependencies of States CAN be resolve from OUTSIDE, that’s why a try of DI is worth for long term. If you don’t want to use DI in every places, you can use DI in the place you need. And it also will help.

Some THINKing (yes Design Pattern but don’t panic, this is a good dose :slight_smile: ):

  • CACHE
  • MEDIA PLAYER idea
  • Hierarchical State Machine
  • a god-like Factory, Creator of everything

… Yeah, and THANK me later… Just kiding
Cheers,

1 Like

@ - pspeed:

O.o I think I got it this time and I really like it. This is gold. Attach most AppStates at launch and enable/disable them when needed, with one specific AppState per GameMode (usually).

I use toneGodGUI so can totally have one AppState for all the “home” menus, one generic AppStates for lobby, one for eventual intermediate screen and one for results. I’ll focus later on on adding the possibility to change options while “racing”.

Okidoki, one entity per missile so it can have components describing it’s attributes. Makes sense.

I’m gonna check MonkeyTrap for how to do the services and see if I wanna retry ES.

Thx!!

@ - atomix:

A lot of what you wrote in your last post doesn’t really tick in my head, but I think some of the concepts will align while I check the monkeyTrap example. I’m bad at immediately understanding such stuff, but better at keeping it around in my head before it starts meaning something haha.

Thx!!

Is Zay-es net adapted to a speed race game? Or is it more adapted to stuff that are less needy in terms of very quick reactions?
I really like what I see in MonkeyTrap… learning a lot by reading it’s code… I’m just totally unable to evaluate how responsive the system is.

@loopies said: Is Zay-es net adapted to a speed race game? Or is it more adapted to stuff that are less needy in terms of very quick reactions? I really like what I see in MonkeyTrap... learning a lot by reading it's code... I'm just totally unable to evaluate how responsive the system is.

Zay-ES net can handle normal stuff but for ‘twitch’ style games you will need something else UDP based. (You can still use spidermonkey).

How many cars/objects do you have to track? For just a few, you may be able to just get away with packing their position+orientation together into a UPD message and blasting it out to the clients. The full topic is much more complicated, though… you need to buffer results, either interpolate or extrapolate, etc… Just like in the Valve articles I link all the time.

Sometime this month I’m going to try to package up my UDP-based networking stuff as an open source lib… but I’m not sure when. This is also primarily an exercise for cleaning up the new networking code for Mythruna so I can’t even promise that the ‘open sourcing’ part gets done this month.

1 Like