読者です 読者をやめる 読者になる 読者になる

hayateasdf's blog

C#,javascript,pythonなどいろいろ。広く浅く

ステートパターン

ステートパターン
オブジェクト指向ではモノをクラス化するが、ステートパターンでは状態をクラス化する。


前どっかの記事で見たようなテンプレートを使用した有限ステートマシンがうろ覚えで、適当なやつが完成したので、記録しておく。安全かどうかは知らん。なんかいけそうな気がする~~~

適当にフェードイン、フェードアウトをステート処理。

#include <memory>
#include <stdio.h>
#include <Windows.h>

template<class Self>
class IState
{
protected:
  Self* self_; 

public:
	virtual ~IState(){}
	virtual void enter(){}
	virtual void update(){}
	virtual void leave(){}
	void initialize(Self* self){ self_ = self; }
};

template<class Self>
class StateFacade
{
private:
  std::unique_ptr<IState<Self> > state_;

public:
	virtual ~StateFacade(){}
	void updateState()
	{
		if(state_)
			state_->update();
	}
	void changeState(IState<Self>* new_state, Self* self)
	{
		if(state_)
			state_->leave();

		if(new_state)
		{
			state_.reset(new_state);
			if(state_)
			{
				state_->initialize(self);
				state_->enter();
			}
		}
	}

};

class SceneTitle : public StateFacade<SceneTitle>
{
	class FadeInState : public IState<SceneTitle>
	{
		void enter(){ self_->alpha_ = 0.0f; }
		void update()
		{
			printf("%.2f, ", self_->alpha_);
			self_->alpha_ += 0.1f;
			if(self_->alpha_ >= 1.0f)
				self_->changeState(new FadeOutState, self_);
		}
	};
	class FadeOutState : public IState<SceneTitle>
	{
		void enter(){ self_->alpha_ = 1.0f; }
		void update()
		{
			printf("%.2f, ", self_->alpha_);
			self_->alpha_ -= 0.1f;
			if(self_->alpha_ <= 0.0f)
				self_->changeState(new FadeInState, self_);
		}
		void leave()
		{
			self_->count_++;
			printf("\ncount = %d\n", self_->count_);
		}
	};
private:
	float alpha_;
	int count_;

public:
	SceneTitle() : count_(0), alpha_(){ changeState(new FadeInState, this); }
	void update()
	{
		updateState();
	}
	bool isEnd(){ return count_ >= 10; }
};

int main()
{
	SceneTitle title;

	while(true)
	{
		title.update();
		if(title.isEnd())
			break;
		Sleep(50); // 時間は適当です。
	}

	return 0;
}

templateの「Self」部分が自身を渡す(this)ことでメンバに直アクセスするという荒業を使用。

ゲーム作成とかで使えそうなきガス!