[ create a new paste ] login | about

Link: http://codepad.org/svJw61KV    [ raw code | output | fork ]

C++, pasted on Jan 24:
#include <cstdio>
#include <bitset>

using namespace std;

template<typename T>
class State
{
public:
    virtual void enter(T&)=0;
    virtual void execute(T&)=0;
    virtual void exit(T&)=0;
};

template<typename T>
class StateMachine
{
public:
    StateMachine(T& owner)
    : owner_(owner)
    , current_(0)
    {
    }
    void change(State<T>* state) {
        if (current_) current_->exit(owner_);
        current_ = state;
        if (current_) current_->enter(owner_);
    }
    
    void update() {
        if (current_) current_->execute(owner_);
    }
private:
    T& owner_;
    State<T>* current_;
};


class Person;

class StandState : public State<Person>
{
public:
    virtual void enter(Person& person){ printf("StandState::enter\n"); }
    virtual void execute(Person& person);
    virtual void exit(Person& person){ printf("StandState::exit\n"); }
};

class MoveState : public State<Person>
{
    virtual void enter(Person& person){ printf("MoveState::enter\n"); }
    virtual void execute(Person& person){ printf("MoveState::execute\n"); }
    virtual void exit(Person& person){ printf("MoveState::exit\n"); }
};

class JumpState : public State<Person>
{
    virtual void enter(Person& person){ printf("JumpState::enter\n"); }
    virtual void execute(Person& person){ printf("JumpState::execute\n"); }
    virtual void exit(Person& person){ printf("JumpState::exit\n"); }
};

class Person
{
    StandState standState_;
    MoveState moveState_;
    JumpState jumpState_;
    StateMachine<Person> fsm_;
    
    enum {
        kStand,
        kMove,
        kJump,
        kMax
    };
    
    std::bitset<3> flags_;
    
public:
    Person()
    : fsm_(*this)
    , next_(0)
    {
        fsm_.change(&standState_);
    }
    
    void update() { fsm_.update(); }
    
    void setStand(bool enable) { flags_.reset(); flags_[kStand] = enable; }
    void setMove(bool enable) { flags_.reset(); flags_[kMove] = enable; }
    void setJump(bool enable) { flags_.reset(); flags_[kJump] = enable; }

    bool isStand() { return flags_[kStand]; }
    bool isMove() { return flags_[kMove]; }
    bool isJump() { return flags_[kJump]; }
    
    bool action();
    
    bool checkNextState();
    void setNextState(State<Person>* state) { next_ = state; }
    bool needChange() { return next_; }
    State<Person>* nextState() { State<Person>* next = next_; next_=0; return next; }
    void changeState() { assert(needChange()); fsm_.change(nextState()); }
private:
    State<Person>* next_;
};

bool Person::checkNextState()
{
    bool result = false;
    if (isStand()) {
        setNextState(&standState_);
        result = true;
    } else if (isMove()) {
        setNextState(&moveState_);
        result = true;
    } else if (isJump()) {
        setNextState(&jumpState_);
        result = true;
    }
    return result;
}

bool Person::action()
{
    bool result = false;
    if (needChange()) {
        changeState();
        result = true;
    }
    return result;
}

void StandState::execute(Person& person)
{
    printf("StandState::execute\n");
    
    person.setJump(true);
    
    if (person.checkNextState()) {
        person.action();
    }

}

int main()
{
    Person* person = new Person();
    
    for (int i = 0; i < 3; ++i) {
        person->update();
    }
    
    delete person;
    return 0;
}


Output:
1
2
3
4
5
6
StandState::enter
StandState::execute
StandState::exit
JumpState::enter
JumpState::execute
JumpState::execute


Create a new paste based on this one


Comments: