2
\$\begingroup\$

I'm working on developing a game with C++, SDL, and OpenGL. I created the engine from scratch, and implemented my own state machine to handle menus and general gameplay. Each State gets pushed into a stack and the last one gets updated and drawn, after initialization on entry. They also handle input on a per-State basis. Right now I have a State for entry point, a 'Press Any Key' prompt, a main menu, as well as a new game menu where the player enters their name. I also batch my Sprites together for easy drawing. I simply pass a vector of Sprite pointers (as some animated sprites may be mixed in as well) to the drawing function which uploads the Sprites to a buffer and draws them. These vectors of Sprites are organized by batch type - mostly based on texture.

I'm moving on to the Exit Game menu, which displays a confirmation that the game will close and the player will be returned to their desktop. I wanted this menu to display on top of the Main Menu with a transparent black layer that darkens everything but the exit game prompt. I can figure out the drawing part easily enough, but the problem is that the Sprites are local to the same State that created them. I am having troubles trying to decide how to 'share' the main menu sprites with the Exit Game State. Likewise, I have the title screen background and logo. The logo animates as well. These two Sprites are visible to every title screen State. Which means I again need some way of continuously displaying a select few Sprites until further notice, such as on entry of the main game. When I get to cutscenes, I will typically need every Sprite used by the gameplay part of the game as well.

One idea I had was to store Sprites in the State Machine as opposed to the State itself. This would mean all Sprites are visible to every State, and the current State would decide which Sprites to delete and which to keep. This means that accessing the Sprites through the State would be a little more roundabout - some sort of access function through the State Machine.

EDIT: I've started implementing the first solution but putting Sprite batches into my Game Engine. The drawback is the scope of each Sprite is not so clearly defined per-State, they need to be directly deleted by the following State to determine which Sprites to keep and delete. It does also make identifying Sprites a little more difficult on transition, though I'm thinking of implementing a std::map of strings to Sprites as I'll need a naming system for cutscene scripting anyway.

I had another idea that would involve 'inheriting' Sprite batches from the previous State but that would also complicate identification of the Sprites.

ANOTHER UPDATE: I'm thinking of getting rid of AnimatedSprite as a distinct class. It just complicates the storage part. By merging it in with regular Sprites, Sprites can be animated but don't need to, and as for the extra storage needed for animations, I'm not too concerned as almost every one of my Sprites animates in some way. With this edit I store my sprites in a vector for batching, a map for naming, and a third optional pointer in my States that optimizes some menus by directly accessing Sprites rather than using map lookup. Going to try that and see how it works out.

\$\endgroup\$
3
  • \$\begingroup\$ I suppose my real question is, where would Sprites typically be stored when using a state machine? I'm leaning toward something like the first solution I came up with, but storing my Sprites in the game engine class, returning a pointer to that Sprite object when created, while also putting a pointer to the Sprite into the appropriate batch's vector. \$\endgroup\$
    – MathPRG
    Commented Jan 17, 2019 at 17:07
  • \$\begingroup\$ If that's your "real" question, you might want to edit your question so that it's more prominently featured, not tucked in the comments as an afterthought. ;) \$\endgroup\$
    – DMGregory
    Commented Jan 19, 2019 at 16:42
  • \$\begingroup\$ Well, I suppose I more mean that my question depends on the answer to that. Sorry for the confusion! \$\endgroup\$
    – MathPRG
    Commented Jan 20, 2019 at 1:36

1 Answer 1

1
\$\begingroup\$

One solution to this problem is by executing EACH state on the state machine, or having speicfic states (or transition states) that are defined to execute one before another. A typical implementation of this might include a stack to maintain the "current state" as it's top. This implementation gives you some nifty things out of box, at certain costs (if you don't work around them) in even the trivial case. However usually those costs would be minimal, unless you're stacking entire levels or large scenes in each state.

The way this works is like so, assuming that whatever state is currently pushed is now on the top of the stack, always render the top of the stack:

Game starts -> Main Menu scene is pushed
Click start game -> Game scene is pushed (now the stack has two scenes pointed)
You die -> Either the game scene is popped, and a game over screen is pushed, or simply a game over scene is pushed, which when popped you'd re-enter and restart the previous scene (the game scene) giving you a "restart" functionality for free.

How this translates to your code may not be eminently clear so I'll specify: Why only have one "current scene?" maybe scenes can be marked with transparent=true and the entire stack is checked in order from bottom to top, only being drawn when it should be. This would give you what you're looking for, plus more abilities for free. It should be worth noting of course that the stack would be maintaining all of your sprites and other things. Exactly what you want, however still worth noting that keeping multiple levels or large scenes this way stacked on top of each other isn't really what this pattern is designed for, and for that you should have some kind of scene that knows how to swap scenes like a SceneManager or LevelLoader scene.

\$\endgroup\$
3
  • \$\begingroup\$ Hmm... This does sound like a good solution but becomes a bit tricky when trying to use it with my batching system. Another one of my goals with this was to bring it down to a single call of the State handleInput, update, and draw functions every frame. I recently made my Game engine its own class (which should've come WAY sooner!) and Sprite creation, deletion, and updating is all done by the engine itself, while states are expected to specify when to create Sprites and start animations, plus they specify the batches to be drawn. I'll keep this in mind if anything comes up though, thanks! \$\endgroup\$
    – MathPRG
    Commented Jan 19, 2019 at 4:40
  • \$\begingroup\$ Thinking on it now, actually... I have to dynamically generate the Vertices vector for my Sprites every frame should they update anyway. Nothing says I can't dynamically generate that vector in the Game engine, allowing multiple States to contribute while doing the same amount of processing that gets done in the drawBatch function of my Graphics engine. Then I just clear it every frame. Thinking on it now this will probably work better and the result should be cleaner. Thanks! \$\endgroup\$
    – MathPRG
    Commented Jan 24, 2019 at 16:40
  • \$\begingroup\$ No problem! Feel free to message me directly or ask for implementation questions if you run into confusion \$\endgroup\$ Commented Jan 24, 2019 at 17:33

You must log in to answer this question.

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