1
\$\begingroup\$

I have a game design 'structure' question that I'd like to throw out there. This question is about various ways of designing game 'states', and specifically a system of 'levels'. Specifically, what is the best way to design a game that has multiple game states, as well as multiple 'levels' or 'stages' with varying degrees of similarity to each other?


For example:

1) Image you're making a 2D platformer with various game states (i.e.: splash screen, animation 'cutscene' sequence, main menu, playstate, pause menu, etc...).

2) Also consider that the game might make use of multiple 'instances' of various states. (For example, maybe you have a "MenuState" class, which is used for both the games 'main start menu' as well as the game's 'game over menu'...)

3.) Now, consider that the game will have multiple levels, which all play more or less the same way, and they all reflect the 'playstate' game state. (so, [level 2] and [level 6] are fundamentally the same in game play, but they probably contain very different details, sprites, music, enemies, bosses, etc..)

4.) Also, hypothetically speaking, what about if you had a second type of 'playstate' that acted in a fundamentally different way? (for example, maybe you have an overworld, or a fundamentally different type of level.)


This is essentially the crux of my question... I'll try to demonstrate what I'm talking about using generic pseudo-code:

So, in this game, we'd have a main(), some kind of StateManager class, and various classes for the different states:

int main()
{
init();
StateManager->handleEvents();
StateManager->handleLogic();
StateManager->checkGameState();
StateManager->handleRendering();
cleanup();
}

The main function would also be some sort of loop with FPS regulation and all that, but for the sake of clarity I'm just going to leave it like that. So main() uses the StateManager to do most of the work, and the state manager would then take care of switching states and it would pass it's event/logic/rendering responsibilities to whatever is the 'current state'. And because the state manager itself is something that I've been having difficulty working out the specifics, I'll leave that for another discussion entirely...

The main issue that I'm looking for help with is the class hierarchy of the various states, as well as when to use inheritance vs when to simply create an instance of an existing state...

Here's my current (limited) understanding of how I've been thinking it should be structured. Honestly, I need help with this part specifically, so I expect it to be slightly wrong:

  • GameState class (top of the state hierarchy, contains virtual event/logic/render functions)
  • SplashScreen, AnimSequence, Menu, PlayState classes (all of the classes ARE gamestates, and as such they should extend the GameState class)

That's all good and fine, but, here comes my main source of 'fuzziness'...

multiple very similar states:

  • In the situation where our game has multiple splash screens, animated sequences, menus, or playstates, how do we structure that relationship? My first instinct is to create instance objects of those various classes. For example, if we want to make multiple different menus that all function in similar ways, what is the proper way of doing that? Should we create new objects of the Menu class called mainMenu, saveMenu, deathMenu, etc.? Or is the correct way to do this via inheritance? Creating new, MainMenu, SaveMenu, and DeathMenu classes that extend the Menu class???

This has really been a source of confusion for me with Object Oriented programming. In this kind of situation, would I be smart to create a subclass or simply instance the existing class?

a system of levels and their interaction with the PlayState class:

  • Another point of confusion for me is the use of multiple 'levels' or 'stages' that play the same way, but have different layout, enemies, bosses, sprites, music, etc... Lets say we want to create a short game with 10 unique 2d platforming levels. Now, the thing that's giving me difficulty is how these 10 levels interact with the PlayState class. Would these 10 levels be instance objects of the PlayState class? Or would it be more beneficial to have a Level class, with 10 level objects, which are used by the PlayState class? Or maybe I'm thinking about this completely the wrong way and Levels are a subclass of PlayState, and each one is it's own unique playstate?

Overworlds and MiniGames as a Secondary PlayState:

  • Finally is the question of an secondary playstate... Regardless of whether it's an overworld, a different game mode, a minecart level, a minigame, or whatever. Would this second playstate just be a complete seperate subclass of the GameState class? For example, if we have our main PlayState (platformer game state) and we also want to have a top-down overworld, and a completely unrelated puzzle minigame, would these simply be other descendants of the GameState class, in the same 'tier' of the class hierarchy?

Thanks to anyone who has gone through the trouble of reading this compound question regarding various states, levels, and game class hierarchies. I know that the quality of opinions and information on this site are often very high, and I hope that this discussion will be as useful to other people with similar questions as it will be for me!


\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Generally, I'd want one class per, well, class of screen. So that'd be one for splash screens/animations (probably the base class for all screens, with support for background images and screen transitions), one for menus, and one for playstate. Each then can be parameterised by its contents - the difference between a main menu and an options menu, for example, are just the various different menu items it contains and the screen's transitions to other screens.

Generally, I'd make MenuScreens take a Menu item of some sort as an input, PlayStateScreens take a Level, and so on.

If you have a secondary gameplay, it may make sense to reuse the PlayStateScreen: the job of this screen is to oversee updates and draw items, so if it's still acting on game entities and drawing sprites in the same way as the main game, then it makes sense to reuse the same screen. If it's something like, say, BioShock's hacking - 2D instead of the main game's 3D, and interaction via pointer rather than mouse for looking - that's a good reason to use a different set of logics. A map view could go either way - if it's still manouvering round a tilemap, and you still want to draw entities with sprites and have scrolling support and so on - then you could use the same PlayState class, and just have entities which use different logic.

\$\endgroup\$
1
  • \$\begingroup\$ Great answer. That really helps me, thank you! So if I'm understanding this correctly, you're saying that the 'PlayState' class should have some way to load a 'level' data type? So when you want to change levels, you simply change the 'Level currentLevel;' by loading in a different level..? (if that makes any sense..) :D \$\endgroup\$ Commented Aug 7, 2012 at 2:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .