I don't know if my question title makes sense, so apologies in advance for that. so... I'm trying to implement a state machine for a little game I'm trying to make using C++ and SFML.
I have a GameLoopObject
abstract class which needs a renderwindow
argument and has these virtual methods: update
, draw
, handleinput
and reset
.
Then I have a GameState
abstract class which inherits from GameLoopObject
, but doesnt add anything new yet so its basically the same as GameLoopObject
, for now.
Last, I have a GameStateManager
class which also inherits from GameLoopObject
and should handle my gamestates.
Now my problem is that I want to use a GameState
currentState
and a nextState
member variable in my GameStateManager
, but I can't seem to find the correct way/syntax to declare these and use them afterwards. I'd prefer leaving them empty (if that's possible in C++), as GameState
objects are being stored inside of them immediately after making a GameStateManager
object.
Basically, what I'm trying to do is something along the lines of this:
GameStateManager(sf::RenderWindow & w) :
GameLoopObject(w),
currentState(new GameState(w)),
nextState(new GameState(w));
Which gives me a "no default constructor exists for class "GameLoopObject" "
This is the rest of my code:
/*
* GameStateManager.hpp
*/
#ifndef GameStateManager_HPP
#define GameStateManager_HPP
#include "stdafx.h"
#include "GameLoopObject.hpp"
#include "GameState.hpp"
#include<string>
#include<map>
class GameStateManager : GameLoopObject {
private:
GameState currentState;
GameState nextState;
public:
std::map<std::string, GameState> gameStates{}; // list where all known gamestates are stored.
// methods
GameStateManager(sf::RenderWindow & w);
void AddGameState(std::string name, GameState * state);
void SetNext(std::string name);
void SwitchState();
void HandleInput();
void Update();
void Draw();
void Reset();
};
#endif //GameStateManager_HPP
/*
* GameStateManager.cpp
*/
#include "stdafx.h"
#include "GameStateManager.hpp"
GameStateManager::GameStateManager(sf::RenderWindow & w)
// : GameLoopObject(w)
{
GameState currentState(w);
GameState nextState(w);
}
void GameStateManager::AddGameState(std::string name, GameState * state)
{
gameStates.insert(std::make_pair(name, * state));
}
void GameStateManager::SetNext(std::string name)
{
//check if user wants to exit (close window with X)
if (gameStates.count(name))
{
nextState = gameStates[name];
}
}
void GameStateManager::SwitchState()
{
if (currentState != nextState)
{
currentState = nextState;
}
}
void GameStateManager::HandleInput()
{
// if(currentState != null)
currentState.HandleInput();
}
void GameStateManager::Update()
{
// if(currentState != null)
currentState.Update();
}
void GameStateManager::Draw()
{
// if(currentState != null)
currentState.Draw();
}
void GameStateManager::Reset()
{
// if(currentState != null)
currentState.Reset();
}
I see you have two issues here, both stemming from the fact that you can't declare an instance of an abstract class. The members of the class should be GameState
pointers. You also face the same issue when you call new GameState
, there is no constructor available here as GameState
is abstract.
I'm not sure whether your GameStateManager
is the owner of the current and next state. In the case that it is, you should change the type of your members to std::unique_ptr<GameState>
, otherwise just use a GameState*
.
Your constructor doesn't need to create a new GameState object to initialise these members if they don't own the states, in this case you would pass a pointer to an existing GameState
. However if they do, you must call new ConcreteGameState
where ConcreteGameState
is some derived class of GameState
that is not abstract.
EDIT: Looking at your member functions, you almost definitely want to a raw pointer.
EDIT 2:
Noticed you are currently privately inheriting from GameLoopObject
, you should change that to public by adding the keyword:
class GameStateManager: public GameLoopObject