●黒猫徘徊アプリの実装
前回,CCatWndクラスの大枠部分の実装ができました.
開発目標である「黒猫徘徊」部分の実装を,CCatWndManagerの派生クラスを作って実装していきます.
●猫の状態で場合分け
CCatWndには複数のアニメーションパターンを登録できます.
当然,現在のアニメーション選択状況によって,やりたいことが変わってきます.
例えば,
- アプリ起動時には特定のアニメーションで猫が出現.
- 徘徊時はウィンドウ位置を都度動かす必要がある.
- 徘徊中止状態も欲しい…
等です.そのような処理分岐の記述が,圧倒的な長さを誇るif elseif… またはswitch case case… みたいなことになっていると,コードを見た瞬間に個人的に萎えるので,
「アニメーションパターン毎に状態クラスを用意」しておいて,これを切り替えることで猫の状態を遷移させることにします.
世間では「Stateパターン」とか呼ぶかもしれません.
猫状態の基本クラスを用意し,各状態クラスを派生させて作ります.基本クラスは↓のようなものです.
//DesktopMascotState class CDMState { public: virtual ~CDMState(){} public: virtual bool OnCreate( CCatWnd *pCatWnd ) = 0; virtual void OnSelect( CCatWnd *pCatWnd, class CDMManager *pManager ) = 0; virtual bool OnPreChangeAnimFrame( CCatWnd *pCatWnd, class CDMManager *pManager, unsigned int AnimID, unsigned int FrameIndex ){ return true; } virtual bool OnPopupMenu( CCatWnd *pCatWnd, class CDMManager *pManager, UINT ItemID ){ return false; } virtual bool OnOtherEvent( CCatWnd *pCatWnd, class CDMManager *pManager, UINT message, WPARAM wParam, LPARAM lParam ){ return false; } };徘徊アプリで状態毎に異なる処理が必要そうなタイミングに呼ぶための処理関数群が宣言されています.宣言順に上から
- 初期処理用(アニメーションの登録等)
- 状態選択されたとき用(アニメーションの切換え等)
- フレーム切り替わり時用(アニメーションが1周したら他の状態に移行とか)
- ポップアップメニューのイベントに対する処理用
- その他のメッセージ処理用
といった感じです.
(コードを書き忘れるとアニメーション切換えが起らなくなってしまう類のメソッドを純粋仮想関数にしてあります.)
●CCatWndManager派生クラスの実装
CCatWndManagerから派生させたクラスには,以下のように…
class CDMManager : public CCatWndManager { public: bool ChangeState( CCatWnd *pCatWnd, unsigned int indx );//m_CurStateIndexを書き換える private: unsigned int m_CurStateIndex;//現在の状態を選択するための値 std::vector< CDMState * > m_StatePool;//状態群.インスタンス生成時あたりで状態群をつくって保持しておく. bool IsValidStateIndex( unsigned int indx ) const { return ( indx < m_StatePool.size() ); } CDMState *GetCurState(){ return m_StatePool.at( m_CurStateIndex ); } };状態クラス群を保持していて,必要なタイミングでChangeState()で切り替えて使用します.
あとは適切なタイミングで
GetCurState()->XXX();
として今の状態クラスに処理を任せるようにしておけばOK.
例えば,フレーム画像変更時の処理は,//フレーム変更直前時 bool CDMManager::OnPreChangeAnimFrame( class CCatWnd *pCatWnd, unsigned int AnimID, unsigned int FrameIndex ) { if( IsValidStateIndex(m_CurStateIndex) ) { return GetCurState()->OnPreChangeAnimFrame( pCatWnd, this, AnimID, FrameIndex ); } else { return true; } }として,現在の状態クラスに処理を投げるだけです.
- Newer: 徘徊アプリの動作骨組(2)
- Older: 猫ウィンドウクラスを作る(5)