2012年11月5日月曜日

ステートマシン

ゲーム開発でよく使うステートマシンクラス。
いつも使っているソースコードを載せておきます。

/**
 * ステートマシンで取り扱われる状態を表すクラス
 * 
 * @author munomura
 * @version $Id: State.java 181 2010-04-25 15:23:58Z nomusanjp $
 */
public abstract class State {
    public void enter(O owner){}
    public void execute(O owner){}
    public void exit(O owner){}
}

/**
 * ゲームのNPCなどステートマシンを表すクラス
 * 
 * @author munomura
 * @version $Id: StateMachine.java 181 2010-04-25 15:23:58Z nomusanjp $
 */
public class StateMachine{
    public O own;
    public State global;
    public State current;
    public State previous;
    boolean isFirstUpdate=true;
    
    public StateMachine(O own){
        this.own = own;
    }
    
    public void setCurrentState(State s){current = s;}
    public void setGlobalState(State s){global = s;}
    public void setPreviousState(State s){previous = s;}
    public State getCurrentState(){return current;}
    public State getGlobalState(){return global;}
    public State getPreviousState(){return previous;}

    public void update() {
        if(isFirstUpdate){
            if(global != null)global.enter(own);
            if(current != null)current.enter(own);
            isFirstUpdate = false;
        }else{
            if(global != null)global.execute(own);
            if(current != null)current.execute(own);
        }
    }
    
    public void changeState(State newState){
        if(newState == null)return;
        
        if(global  != null)global.exit(own);
        if(current != null)current.exit(own);
        
        previous = current;
        current  = newState;
        
        if(global  != null)global.enter(own);
        if(current != null)current.enter(own);
        isFirstUpdate = false;
    }
    
    public void revertToPreviousState(){
        changeState(previous);
    }

    boolean isInState(State st){
        return st.equals(current);
    }
    
    /**
     * グローバルと初期ステートを同時に設定する。
     * AI初期化時に使用。
     * 
     * @param global
     * @param firstState
     */
    public void setupState(State global, State firstState){
        isFirstUpdate = true;
        this.global = global;
        this.current = firstState;
    }
}



public class Dog extends NPC implements Recycleable {

    protected StateMachine stateMachine = new StateMachine(this);

    @Override
    public void updateState(){
        stateMachine.update();
    }
}

public class DogRound extends State {
    public static DogRound state = new DogRound();

    @Override
    public void enter(Dog own){
    }

    @Override
    public void execute(Dog own){
    }
    
    @Override
    public void exit(Dog own){
    }
}