I have a class called StateMachine, which controls all possible Entity States.
I then have a class called State which is a base class for unique Entity classes, e.g Attack State, Flee State.
When a new unique State is created (within the StateMachine), it passes in a StateMachine pointer, which will then be stored in the State base class, so that each unique State created can access its State Machine.
When I attempt to access the pointers members (using -> operator) it simple doesn't come up with any public methods, and I don't know why.
If anyone has any clue it would be greatly appreciated.
StateMachine.h
using STATE_PTR = std::shared_ptr<State>;
// Class to implement a finite state machine using the state desing pattern
class StateMachine
{
public:
StateMachine();
~StateMachine();
void OnEnter(STATE_NAME sn);
void OnExit();
void OnEvent(STATE_SYMBOL & ss);
void OnTick(float st);
void ChangeState(STATE_NAME const & sn);
void RegisterState(ENTITY_CLASS const & ec);
typedef std::map<STATE_NAME, STATE_PTR> STATE_REGISTRY;
private:
STATE_REGISTRY state_registry;
STATE_NAME current_state;
};
StateMachine.cpp
using namespace::std;
StateMachine::StateMachine()
: state_registry()
{
current_state = STATE_NAME::UNKNOWN;
}
StateMachine::~StateMachine()
{
state_registry.clear();
}
void StateMachine::OnEnter(STATE_NAME sn)
{
current_state = sn;
if (state_registry[current_state] != nullptr)
{
state_registry[current_state]->OnEnter();
}
}
void StateMachine::OnExit()
{
if (state_registry[current_state] != nullptr)
{
state_registry[current_state]->OnExit();
}
}
void StateMachine::OnTick(float st)
{
}
void StateMachine::OnEvent(STATE_SYMBOL & ss)
{
state_registry[current_state]->OnEvent(ss);
}
void StateMachine::RegisterState(ENTITY_CLASS const & ec)
{
switch (ec)
{
case ENTITY_CLASS::PLAYER_TANK :
state_registry.insert(std::make_pair(STATE_NAME::STATE_1, std::make_shared<PlayerTankState1>(this)));
state_registry.insert(std::make_pair(STATE_NAME::STATE_2, std::make_shared<PlayerTankState2>(this)));
break;
case ENTITY_CLASS::ENEMY_TANK :
state_registry.insert(std::make_pair(STATE_NAME::STATE_3, std::make_shared<EnemyTankState1>(this)));
state_registry.insert(std::make_pair(STATE_NAME::STATE_4, std::make_shared<EnemyTankState2>(this)));
state_registry.insert(std::make_pair(STATE_NAME::STATE_5, std::make_shared<EnemyTankState3>(this)));
break;
default:
break;
}
}
void StateMachine::ChangeState(STATE_NAME const & sn)
{
state_registry[current_state]->OnExit();
current_state = sn;
state_registry[current_state]->OnEnter();
}
State.h
class StateMachine; // Forward decloration of the StateMachine class
// Base class for all states of the game system
class State
{
protected:
State(StateMachine * p)
: mp_Owner(p)
{}
public:
virtual ~State() {}
virtual void OnEnter() = 0;
virtual void OnExit() = 0;
virtual void OnTick(float) = 0;
virtual void OnEvent(STATE_SYMBOL) = 0;
StateMachine * mp_Owner;
};
EnemyTankState.cpp (Unique State)
EnemyTankState1::EnemyTankState1(StateMachine * p)
: State(p)
{
}
EnemyTankState1::~EnemyTankState1()
{
}
void EnemyTankState1::OnEnter()
{
cout << "Hi From Enemy Tank: Partolling State" << endl;
}
void EnemyTankState1::OnExit()
{
cout << "Bye From Enemy Enemy Tank: Partolling State" << endl;
}
void EnemyTankState1::OnTick(float dt)
{
}
void EnemyTankState1::OnEvent(STATE_SYMBOL ss)
{
switch (ss)
{
// Takes Enemy Tank to Attacking State
case STATE_SYMBOL::SYMBOL_2 :
mp_Owner->
break;
}
}
Within the code sample above, the line mp_Owner-> is what is giving me grief, as it is not opening up a list of public methods as you would expect when using a class pointer.
Any help would be much appreciated. Sorry for the long chunks of code, I couldn't think of any other way of getting my problem across.
Related
For a task, I am planning to implement a state machine in C++ .
I am trying to keep a context object which provides following:
a state_ object to keep track of current state
a TransitionTo() method to facilitate transition to new state.
When I wrote the sample implementation and tested it out, I am facing double free error.
I needed help from the community in guiding me on what might be going wrong.
Thanks a lot.
#include <iostream>
#include <string>
class State;
/* Context class and method implementation */
class Context
{
State* state_;
public:
explicit Context(State* state);
void TransitionTo(State* newState);
};
Context::Context (State* state): state_ (nullptr)
{
this->TransitionTo(state);
}
void Context::TransitionTo(State* newState)
{
std::cout <<"Requesting state transition to " << newState->stateName<<"\n";
std::string previous_state_name = "None";
if (this->state_ != nullptr)
{
previous_state_name = this->state_->stateName;
delete this->state_;
}
this->state_ = newState;
std::cout << "State changed from "<< previous_state_name << " to "<< this->state_->stateName << "\n";
this->state_->set_context(this);
}
/* State class and method implementation */
class State
{
protected:
Context* context_;
public:
std::string stateName;
void set_context(Context* newContext);
virtual ~State();
};
State::~State()
{
std::cout << stateName <<" state deleted \n";
delete context_ ;
}
void State::set_context(Context *newContext)
{
this->context_ = newContext;
}
/* Declaring different states which are derived from State */
class HappyState : public State
{
public:
HappyState();
};
HappyState::HappyState()
{
stateName = "Happy";
}
class NeutralState : public State
{
public:
NeutralState();
};
NeutralState::NeutralState()
{
stateName = "Neutral";
}
class SadState : public State
{
public:
SadState();
};
SadState::SadState()
{
stateName = "Sad";
}
/* Test the implementation */
int main()
{
Context* ctx = new Context(( new NeutralState()));
ctx->TransitionTo(new HappyState());
ctx->TransitionTo(new SadState());
return 0;
}
When I run this code, I am getting following output:
Output snapshot
I found the mistake which was indeed a very silly one.
I was deleting the context_ in ~State() which deleted my original context.
I have the following code:
class ISubscriber;
class News {
public:
float getVersion() { return this->version; }
void setVersion(float state) { this->version= state; this->notifyAllSubscribers(); }
void attach(ISubscriber *observer) { this->subscribers.push_back(observer); }
void notifyAllSubscribers() {
for (vector<ISubscriber*>::iterator it = subscribers.begin(); it != subscribers.end(); it++){
(*(*it)).update();
}
}
private:
vector<ISubscriber*> subscribers;
float version;
};
class ISubscriber {
public:
News *news;
virtual void update() = 0;
};
class Subscriber1 : public ISubscriber {
public:
Subscriber1(News *news) { this->news = news; this->news->attach(this); }
void update() override { cout << "Subscriber1: A new version of the newspaper has been launched (v" << this->news->getVersion() << ")" << endl; }
};
class Subscriber2 : public ISubscriber {
public:
Subscriber2(News *news) { this->news = news; this->news->attach(this); }
void update() override { cout << "Subscriber2: A new version of the newspaper has been launched (v" << this->news->getVersion() << ")" << endl; }
};
int main(int argc, char *argv[]) {
News newspaper;
newspaper.setVersion(2.1f);
Subscriber1 sb1(&newspaper);
Subscriber2 sb2(&newspaper);
return 0;
}
But strange errors happened:
The first error points to this code (*(*it)).update(); in news class.
Why that errors happened, what's the reason?
(*(*it)).update(); requires the type ISubscriber to be complete, just the forward declaration is not enough.
You could move the defnition of ISubscriber before the one of News, and give a forward declaration of News before that.
class News;
class ISubscriber {
public:
News *news;
virtual void update() = 0;
};
class News {
public:
float getVersion() { return this->version; }
void setVersion(float state) { this->version= state; this->notifyAllSubscribers(); }
void attach(ISubscriber *observer) { this->subscribers.push_back(observer); }
void notifyAllSubscribers() {
for (vector<ISubscriber*>::iterator it = subscribers.begin(); it != subscribers.end(); it++){
(*(*it)).update();
}
}
private:
vector<ISubscriber*> subscribers;
float version;
};
I'm making a state machine for switching game states (playing->menu->setup) in my game engine, but I'm getting a segmentation fault. I can change the game state fine from upper level, but how can I change the game state from within a game state?
Here's a minimal code example:
#include <iostream>
#include <vector>
class GameStateManager;
class GameState {
public:
GameState(GameStateManager* StateManager) {
StateManager = stateManager;
};
virtual ~GameState();
virtual void update() = 0;
GameStateManager* stateManager;
};
class GameStateManager {
public:
GameStateManager();
~GameStateManager();
void changeGameState(GameState* state) {
if(!running) {
running = true;
}
// Cleanup the current state
if(!gameStates.empty()) {
for(unsigned int i = 0; i < gameStates.size(); i++) {
delete gameStates[i];
}
gameStates.clear();
std::cout << "Cleaning up GameState" << std::endl;
}
// Store and initialize the new game state
gameStates.push_back(state);
};
void update() {
if(!gameStates.empty()) {
gameStates.back()->update();
}
};
std::vector<GameState*> gameStates;
bool running;
};
class PlayState : public GameState {
public:
PlayState(GameStateManager* stateManager) : GameState(stateManager) {};
~PlayState();
void update() override {
// On some flag, initiate the next level
nextLevel();
};
void nextLevel() {
stateManager->changeGameState(new PlayState(stateManager));
};
};
int main() {
GameStateManager stateManager;
stateManager.changeGameState(new PlayState(&stateManager));
while(stateManager.running) {
for(unsigned int i = 0; i < 10000; i++) {
std::cout << "Round: " << i << std::endl;
// Segmentation fault here
stateManager.update();
// This works
//stateManager.changeGameState(new PlayState(&stateManager));
}
stateManager.running = false;
}
return 0;
}
for some reason the stateManager is not being set in the GameState constructor.
so try this:
class GameState {
public:
GameState(GameStateManager* StateManager) : stateManager(StateManager)
{
};
virtual ~GameState();
virtual void update() = 0;
GameStateManager* stateManager;
};
I have a problem with a c++ code I just written. The code is a sample of the Builder design pattern. I created an abstract builder class, and two classes inherited from this class: MonsterBuilder and RuffianBuilder. I created a Builder class, this class receives a Monster or a RuffianBuilder, and constructs a new instance of these classes. The problem comes here: if the MonsterBuilder class is used to build a new instance the program terminates with an error (a.exe has stopped working). If the Builder receives a RuffianBuilder, it constructs a new instance without an error. Here is the sample code:
#include <iostream>
class Character
{
private:
// Attributes
int dex;
int str;
int end;
// skills
int lockpick;
int guns;
int sneak;
/***************************************** Setters ********************************************************/
// Attribute setters
public:
void setStrength(const int &s)
{
this->str = s;
}
void setDexterity(const int &d)
{
this->dex = d;
}
void setEndurance(const int &e)
{
this->str = e;
}
// Skill setters
void setLockpick(const int &s)
{
this->lockpick = s;
}
void setSneak(const int &s)
{
this->sneak = s;
}
void setGuns(const int &s)
{
this->guns = s;
}
int getGuns()
{
return this->guns;
}
int getStrength()
{
return this->str;
}
};
/* Abstract builder */
class CharacterBuilder
{
protected:
Character * int_character;
public:
Character * getCharacter()
{
return int_character;
}
void buildCharacter()
{
int_character = new Character;
}
virtual void buildSkills() = 0;
virtual void buildAttributes() = 0;
};
class MonsterBuilder : public CharacterBuilder
{
public:
virtual void buildSkills()
{
int_character->setLockpick(10);
int_character->setSneak(12);
int_character->setGuns(50);
}
virtual void buildAttributes()
{
int_character->setStrength(5);
int_character->setDexterity(5);
int_character->setEndurance(5);
}
};
class RuffianBuilder : public CharacterBuilder
{
public:
virtual void buildSkills()
{
int_character->setLockpick(10);
int_character->setSneak(12);
int_character->setGuns(50);
}
virtual void buildAttributes()
{
int_character->setStrength(5);
int_character->setDexterity(5);
int_character->setEndurance(5);
}
};
class Builder
{
public:
void setBuilder(CharacterBuilder * builder)
{
this->builder = builder;
}
Character * getCharacter()
{
return builder->getCharacter();
}
void buildCharacter()
{
//std::cout << builder->buildSkills;
builder->buildSkills();
builder->buildAttributes();
}
private:
CharacterBuilder * builder;
};
int main()
{
Builder B;
RuffianBuilder R;
MonsterBuilder Mo;
B.setBuilder(&R);
B.buildCharacter();
std::cout << B.getCharacter()->getGuns();
std::cout << B.getCharacter()->getStrength();
B.setBuilder(&Mo);
B.buildCharacter();
//std::cout << B.getCharacter()->getStrength();
return 0;
}
What causes this problem? Could somebody explain it?
Reading uninitlalized variable will cause undefined behavior.
I added builder->buildCharacter(); to Builder::buildCharacter() and then this code seems working well.
class Builder
{
public:
void setBuilder(CharacterBuilder * builder)
{
this->builder = builder;
}
Character * getCharacter()
{
return builder->getCharacter();
}
void buildCharacter()
{
//std::cout << builder->buildSkills;
builder->buildCharacter(); // add this line
builder->buildSkills();
builder->buildAttributes();
}
private:
CharacterBuilder * builder;
};
I have a parent Menu class and children MainMenu, SettingsMenu, PauseMenu, etc.
I want to be able to hold them all in a vector...
I can do
std::vector<Menu*> myVector;
and then typecast each one when I push_back in the vector
pMainMenu = new MainMenu;
myVector.push_back((Menu*)pMainMenu);
and it compiles but something's not working right down the road...
It doesn't have to be a vector but I want to be able to iterate through them.
I'm always trying to implement the Observer pattern and I'm having difficulties with inheritance as well in that area!
For the Observer pattern I have an Observer class and Game inherits Observer. I have a Subject class inherited by InputComponent. Subject has a vector of Observer* called vObserver and a function called addObserver(Observer* observer) and adds the passed pointer in vObserver. I also have a function called Notify(event e), which iterates through vObserver and calls their onNotify functions.
So in Game, I have an InputComponent instance called inputComp. I do inputComp.addObserver(this) and inputComp.vObserver.size() is 1. Good. I have a call to Notify in InputComponent which does get triggered, but when it executes, the vObserver.size inside Subject is 0... idk what I'm doing wrong
EDIT:
class Menu
{
public:
virtual void draw() = 0;
virtual void onMouseMove(int x, int y) = 0;
virtual void onMouseButton(int button, bool is_down) = 0;
friend class InputComponent;
friend class MainMenuInputComponent;
protected:
SDL_Renderer* _renderer;
std::vector<Button> vButton;
std::vector<SDL_Texture *> vTexture;
};
class MainMenu : public Menu
{
public:
MainMenu(SDL_Renderer* renderer);
virtual void draw();
virtual void onMouseMove(int x, int y);
virtual void onMouseButton(int button, bool is_down);
friend class MainMenuInputComponent;
};
class InputComponent: public Subject
{
public:
virtual void processInput()
{}
static bool isMouseWithin(int mouseX, int mouseY, SDL_Rect rect)
{
if (mouseX >= rect.x && mouseX <= rect.x + rect.w && mouseY >= rect.y && mouseY <= rect.y + rect.h)
return true;
else
return false;
}
};
class MainMenuInputComponent : public InputComponent
{
public:
MainMenuInputComponent(MainMenu* owner)
:_owner(owner){}
virtual void processInput();
virtual void onBtnClick(std::string btnName);
MainMenu* _owner;
};
class Game : public Observer
{
public:
Game();
void initSDL();
void initGame();
void processGameInput();
void renderGame();
void update();
virtual void onNotify(Events e);
SDL_Window* myWindow;
SDL_Renderer* myRenderer;
std::vector<MainMenuInputComponent> vInputComponent;
std::stack<MainMenu*> menuStack;
};
Game::Game()
{
initSDL();
initGame();
}
void Game::initGame()
{
//Create the Main Menu
MainMenu* pMainMenu = new MainMenu(myRenderer);
//Add menu to the stack
menuStack.push((pMainMenu));
//Add it's components to respective arrays
MainMenuInputComponent inputComp = MainMenuInputComponent(pMainMenu);
vInputComponent.push_back(inputComp);
//Add Observer/Subject relationship.
inputComp.addObserver((Observer*)this);
int bob = (int)inputComp.vObserver.size(); //to see if size went up
}
void Game::processGameInput()
{
if (!menuStack.empty())
{
for (int i = 0; i < (int)vInputComponent.size(); i++)
{
//Menu* compOwner = (Menu*)(vInputComponent[i]._owner);
//std::unique_ptr<Menu, std::default_delete<Menu>> a = menuStack.top();
if ((vInputComponent[i]._owner) == menuStack.top())
{
vInputComponent[i].processInput();
}
//vInputComponent[i].processInput();
}
}
else
for (int i = 0; i < (int)vInputComponent.size(); i++)
{
vInputComponent[i].processInput();
}
}
void Game::renderGame()
{
SDL_RenderClear(myRenderer);
MainMenu* bob = menuStack.top();
if (!menuStack.empty())
(menuStack.top())->draw();
SDL_RenderPresent(myRenderer);
}
void Game::onNotify(Events event)
{
switch (event)
{
case POP_MENU:
menuStack.pop();
break;
case GOTO_SETTINGS:
//Menu* pSettingsMenu =(Menu*)(new SettingsMenu(myRenderer));
//menuStack.push(std::unique_ptr<Menu>(pSettingsMenu));
break;
// Handle other events, and update heroIsOnBridge_...
}
}
class Subject
{
public:
void addObserver(Observer* observer)
{
vObserver.push_back(observer);
}
void removeObserver(Observer* observer)
{
//vObserver.erase(std::find(vObserver.begin(), vObserver.end(), 8));
}
std::vector<Observer*> vObserver;
protected:
void notify(Events e)
{
for (int i = 0; i < (int)vObserver.size(); i++)
{
vObserver[i]->onNotify(e);
}
}
};
class Observer
{
public:
virtual ~Observer() {}
virtual void onNotify(Events e) = 0;
};
If MainMenu publically inherits from Menu, then you shouldn't even need to type cast the pointer to MainMenu to Menu at all. That is, this should work:
class Menu {};
class MainMenu : public Menu {};
std::vector<Menu*> myVector;
MainMenu* pMainMenu = // ...
myVector.push_back(pMainMenu);
However, what you really should be doing is using something like shared_ptr or unique_ptr. Here's a more complete example, using shared_ptr:
#include <vector>
#include <memory>
#include <iostream>
class Menu
{
public:
virtual void on_event() = 0;
// virtual destructor needed for polymorphic base classes
virtual ~Menu() {}
};
class MainMenu : public Menu
{
public:
virtual void on_event()
{
std::cout << "Hello world! from MainMenu" << std::endl;
}
};
class PauseMenu : public Menu
{
public:
virtual void on_event()
{
std::cout << "Hello world! from PauseMenu" << std::endl;
}
};
class SettingsMenu : public Menu
{
public:
virtual void on_event()
{
std::cout << "Hello world! from SettingsMenu" << std::endl;
}
};
int main()
{
std::vector<std::shared_ptr<Menu>> myVector;
myVector.push_back(std::make_shared<MainMenu>());
myVector.push_back(std::make_shared<PauseMenu>());
myVector.push_back(std::make_shared<SettingsMenu>());
for(auto& menu : myVector) {
menu->on_event();
}
return 0;
}
Expected output:
Hello world! from MainMenu
Hello world! from PauseMenu
Hello world! from SettingsMenu
This should also work and gives you the bonus feature of taking care of memory management for you.