Skip to content

Instantly share code, notes, and snippets.

@prucha
Last active August 29, 2015 14:21
Show Gist options
  • Save prucha/23fe30edc70fa6c04faf to your computer and use it in GitHub Desktop.
Save prucha/23fe30edc70fa6c04faf to your computer and use it in GitHub Desktop.
A 'Finite State Machine' implemented in a Cinder App
// 'Finite State Machine' in Cinder
// --------------------------------
// Created by Milan Prucha on 14/05/2015.
/*
1) Create a new Cinder project in Xcode / Visual Studio.
2) Add the other h/cpp files (included below) to your project.
3) Then use the code in this cpp, in your main Cinder App cpp.
*/
#include "cinder/app/AppNative.h"
#include "cinder/gl/gl.h"
#include "StateMachine.h"
#include "StateName.h"
//States:
#include "AttractorLoopState.h"
//#include "GameLoopState.h"
//TODO: Add more State headers...
//(You should implement a number of 'States' for use with your 'StateMachine')
using namespace ci;
using namespace ci::app;
using namespace std;
class CinderApp : public AppNative {
public:
void setup();
void mouseDown( MouseEvent event );
void update();
void draw();
StateMachine* stateMachine;
};
void CinderApp::setup()
{
console() << "CinderApp::setup()" << endl;
//Create the 'Finite State Machine'
stateMachine = new StateMachine(this);
stateMachine->addState(new AttractorLoopState());
//stateMachine->addState(new GameLoopState());
//TODO: Add more states...
//set to initial state
stateMachine->changeState( StateName::ATTRACTOR_LOOP );
}
void CinderApp::update()
{
stateMachine->update();
}
void CinderApp::draw()
{
// clear out the window with black
gl::clear( Color( 0, 0, 0 ) );
stateMachine->draw();
}
void CinderApp::mouseDown( MouseEvent event )
{
console() << "CinderApp::mouseDown()" << endl;
stateMachine->mouseDown(event);
}
CINDER_APP_NATIVE( CinderApp, RendererGl )
// 'Finite State Machine' in Cinder
// --------------------------------
// Created by Milan Prucha on 14/05/2015.
//
// AttractorLoopState.cpp
#include "AttractorLoopState.h"
#include "StateName.h"
AttractorLoopState::AttractorLoopState()
{
console() << "AttractorLoopState::AttractorLoopState()" << endl;
this->name = StateName::ATTRACTOR_LOOP;
}
void AttractorLoopState::init()
{// Initialize the State
console() << "AttractorLoopState::init()" << endl;
}
void AttractorLoopState::enter()
{// Execute only when this state is entered
console() << "AttractorLoopState::enter()" << endl;
}
//looping methods
void AttractorLoopState::update() {/* Execute every CinderApp::update() loop */}
void AttractorLoopState::draw() {/* Execute every CinderApp::draw() loop */}
void AttractorLoopState::exit()
{// Execute only when state is exiting
console() << "AttractorLoopState::exit()" << endl;
}
void AttractorLoopState::mouseDown( MouseEvent event )
{
console() << "AttractorLoopState::mouseDown() - go to next state!" << endl;
stateMachine->changeState( StateName::GAME_LOOP );
}
// 'Finite State Machine' in Cinder
// --------------------------------
// Created by Milan Prucha on 14/05/2015.
//
// AttractorLoopState.h
#ifndef __CinderApp__AttractorLoopState__
#define __CinderApp__AttractorLoopState__
#include "StateMachine.h"
class AttractorLoopState : public StateMachine::State
{
public:
void init();
void enter();
void draw();
void update();
void exit();
void mouseDown( MouseEvent event );
AttractorLoopState();
~AttractorLoopState();
};
#endif /* defined(__CinderApp__AttractorLoopState__) */
// 'Finite State Machine' in Cinder
// --------------------------------
// Created by Milan Prucha on 14/05/2015.
//
// StateMachine.cpp
#include "StateMachine.h"
StateMachine::StateMachine(App* newApp)
{
app = newApp;
init();
}
StateMachine::~StateMachine()
{
//Destructor
}
void StateMachine::init()
{
console() << "StateMachine::init()" << endl;
_currentState = NULL;
_prevState = NULL;
}
string StateMachine::getPreviousStateName()
{
return this->_prevState->name;
}
void StateMachine::update()
{
//console() << "StateMachine::update()";
if(_currentState)
{
_currentState->update();
}
else
{
console() << "StateMachine::update() - _currentState is NULL! :(" << endl;
}
}
void StateMachine::draw()
{
if(_currentState)
{
_currentState->draw();
}
else
{
console() << "StateMachine::draw() - _currentState is NULL! :(" << endl;
}
}
void StateMachine::mouseDown(MouseEvent event)
{
_currentState->mouseDown(event);
}
void StateMachine::addState(State* newState)
{
console() << "StateMachine::addState()" << endl;
newState->stateMachine = this;
newState->init();
states.insert( std::make_pair(newState->name, newState) );
}
StateMachine::State* StateMachine::getCurrentState()
{
return _currentState;
}
void StateMachine::changeState(string stateName)
{
auto search = states.find( stateName );
if(search != states.end())
{
console() << "StateMachine::changeState() - :) found State: " << stateName << ", first: " << search->first << ", second: " << search->second << endl;
if(_currentState)
{
_currentState->exit();
}
_prevState = _currentState;
_currentState = search->second;
_currentState->enter();
}
else
{
console() << "StateMachine::setCurrentState() - :( Can't find State: " << stateName << endl;
}
}
// 'Finite State Machine' in Cinder
// --------------------------------
// Created by Milan Prucha on 14/05/2015.
//
// StateMachine.h
#ifndef __CinderApp__StateMachine__
#define __CinderApp__StateMachine__
#include <stdio.h>
#include <unordered_map>
#include "cinder/app/AppNative.h"
using namespace std;
using namespace ci::app;
class StateMachine
{
public:
class State
{
private:
public:
virtual void init() {}
virtual void enter() {}
virtual void exit() {}
virtual void mouseDown( MouseEvent event ) {}
virtual void draw() {}
virtual void update() {}
StateMachine* stateMachine;
string name;
};
public:
unordered_map <string, State*> states;
App* app;
string getPreviousStateName();
State* getCurrentState();
void addState(State* newState);
void update();
void draw();
void mouseDown(MouseEvent event);
void changeState(string stateName);
StateMachine();
StateMachine(App* newApp);
~StateMachine();
protected:
void init();
State* _currentState;
State* _prevState;
string _backStateID;
};
#endif /* defined(__CinderApp__StateMachine__) */
// 'Finite State Machine' in Cinder
// --------------------------------
// Created by Milan Prucha on 14/05/2015.
//
// StateName.cpp
#include "StateName.h"
const std::string StateName::ATTRACTOR_LOOP = "attractor_loop";
const std::string StateName::GAME_LOOP = "game_loop";
//TODO: Add more State Names...
// 'Finite State Machine' in Cinder
// --------------------------------
// Created by Milan Prucha on 14/05/2015.
//
// StateName.h
#ifndef __CinderApp__StateName__
#define __CinderApp__StateName__
#include <stdio.h>
class StateName
{
public:
static const std::string ATTRACTOR_LOOP;
static const std::string GAME_LOOP;
//TODO: Add more State Names...
};
#endif /* defined(__CinderApp__StateName__) */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment