1
\$\begingroup\$

So far I am making a game in C++ and SDL, and the way to switch between the different menus and the actual game is via a Finite State Machine, AKA a stack where I put each state (MenuState, GameState...) on top, and only render and update the top of said stack.

Now I need to load assets such as images, and I am thinking of creating a class for each state which will hold all the address of the textures, sound, etc and pass it to each state so that it can render, play sound, etc, properly.

Something like a GameAsset class that I pass to GameState(GameAsset ga) when I create one, so that GameState::render() can do its work fast.

Is there any better way (easier to implement, faster, whatever) to do this ? It seem like it's stretched out for me, as I haven't made games on this scale before. Will this become unmaintainable or whatever ?

Thanks.

\$\endgroup\$
1
\$\begingroup\$

First consideration: as retrieving the GameAssets inside GameState::render will be done only once per frame, there's no consideration of efficiency to be had -- no sensible solution will have any impact.

That aside, let's consider our options. GameState::render is a member function, so there are three ways it can retrieve an object:

Global variable

The usual one. You'd have a global GameAssets *gGameAssets;, that is assigned to the GameAssets instance once constructed. This is technically the simplest solution, but global variables are usually frown upon because maintenance is an issue: that simplicity means that absolutely no dependency is visible from the outside, so you don't know that GameState::render needs and uses gGameAssets. Moving on.

Member variable

GameState would hold a GameAssets * as a member variable. The pattern you've shown, providing the GameState with its GameAssets upon construction, is known as Dependency Injection. It's pretty good maintenance-wise: the caller governs which GameAssets goes to which GameState, and the dependency is visible.

Function parameter

This one is not always practical, but it should be in this case. There's a good chance that GameState::render is the only function from GameState that needs the GameAssets, and that the function calling GameState::render also has access to the GameAssets. How about just passing a parameter, i.e. GameState::render(GameAssets &assets)? Now the dependency is both explicit and tightly localized to the render call.

The choice

It's simple: from bottom to top, pick the first practical solution :)

\$\endgroup\$
  • \$\begingroup\$ Thanks you for your answer. I'm going to do a mix of 2 and 3, when it's practical. A global variable just doesn't feel right :) \$\endgroup\$ – user96649 Mar 30 '17 at 5:41
  • \$\begingroup\$ Particularly, in case where a single object is using assets, it make sense to store it in that object. But if it's a tons of them, it's best to send them the parameters, as those objects have to be stored, and any more data stored in them will increase the memory usage too much. \$\endgroup\$ – user96649 Mar 30 '17 at 7:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.