0

Back around 2005, I spent a lot of time writing several indie games in C using SDL and I'd like to try again making some new games but in C++ instead of C. I have an unfinished game in C that I'm currently rewriting in C++ but I'm encountering some issues specific to classes instance initialization. Unfortunately, I was not able to find any answers anywhere on SO or on other website so I hope you professionals could have some helpful insights.

I have a class, StateManager, which keeps track of the game states stored in a vector of GameState. Once a state needs to be the active state, StateManager calls vector::push_back() and passes as argument the pointer to the new active state, in our case here GameplayState (child class of GameState)

Previous active state:

stateManager->ChangeState( GameplayState::Instance(stateManager) );

StateManager:

void StateManager::ChangeState(GameState* state) {
    // cleanup the current state
    if (!states.empty()) {
        states.back()->Cleanup();
        states.pop_back();
    }

    // store and init the new state
    states.push_back(state);
    states.back()->Init(this);
}

Now here comes whay I would like to acheive. My GameplayState class has several member classes which need to be initialized at the same time GameplayState is initialized, i.e. a Player class and a Map class. To work correctly, both classes need their constructors to get some data passed as parameters.

GameplayState.h extract:

class GameplayState : public GameState {
public:
    // Several unrelevant methods here

    static GameplayState* Instance(StateManager* stateManager) {
        gameplayState = GameplayState(stateManager);
        return &gameplayState;
    }

protected:
    GameplayState(necessary_parameters) :player(necessary_parameters), map(necessary_parameters) { }

private:
    static GameplayState gameplayState;

    Player player;
    Map map;
};

Player.h extract (Map works the same):

class Player {
public:
    Player(necessary_parameters);
    ~Player();
};

Compiler outputs errors each single time. My understanding is that given how the code works currently, the version of the contructor of GameplayState including a parameter, i.e. GameplayState::GameplayState(necessary_parameters), is never called because we never explicitly call it. My understand of how C++ works is that the default constructor, without any parameters will be called by default, so I have to find a way the call the version of the constructor with parameters but I was unable to find a solution given the Singleton structure here. I tried several ways for the whole day, without any success.

Do you maybe have an idea of a workaround please? It would be of tremendous help.

Thank you very much!

Tom

wohlstad
  • 12,661
  • 10
  • 26
  • 39
ThomK
  • 1
  • 1
    `gameplayState = GameplayState(stateManager);` this constructs a new `GameplayState` every time you call `Instance` – AndyG Aug 18 '22 at 16:31
  • This is a poorly implemented singleton. [Consider learning from something like this, a Meyers Singleton, instead](https://stackoverflow.com/a/1008289/4581301). Where you find `static S instance;` in Martin York's example, you want `static S instance{arguments go here};`. The tricky part is getting the arguments in because you only get one shot at it and you don't want to keep passing in arguments to a function that can't use them. Once a Meyers singleton is initialized, it stays initialized. – user4581301 Aug 18 '22 at 16:38
  • Leads to the question: You sure you want a singleton here? Doesn't seem to fit your use-case very well. – user4581301 Aug 18 '22 at 16:43
  • Thank you both very much for your answers. @user4581301 That's a very intesting link you provided, thanks. And I think you are right, I gave it some thought and indeed a singleton is probably not the most suitable here. My first guess was that every State should be unique, thus the singleton but in the end, it's way easier to do it without it. I tweaked the code and removed the singleton, passing a ` new GameplayState(stateManager) ` as parameter to ` vector::push_back() ` and everything works perfectly now. – ThomK Aug 18 '22 at 19:10

0 Answers0