拡張タスクシステムの定義
本稿のサンプルゲームに依存する処理をまとめたTaskEx
クラスの宣言を見てください。多くのタスクに必要と思われるメンバ変数、DirectXに依存する描画関数、そしてグループ分けの機能を追加しています。
グループ分けのカラクリは簡単で、全てのタスクにグループ識別子を持たせるだけです。グループ分けの機能は必須であり、Task
クラスのメンバ変数にしようか迷ったのですが、最初の直感を信じてTaskEx
クラスのメンバ変数としました。好みによってTask
クラスのメンバ変数にしても問題ありません。
#pragma once #include"TaskSystem.h" #include"main.h" // for DirectX #include<math.h> #include<time.h> extern IDirect3DDevice9 *g_pD3DDevice; // main.cpp struct DATA { int id; float cx,cy; float hit_cw,hit_ch; float speed; DWORD life,max_life; float rot; BYTE alpha; }; class TaskEx : public Task { protected: int m_id; // グループ識別子 float m_cx,m_cy; float m_hit_cw,m_hit_ch; float m_speed; DWORD m_life,m_max_life; IDirect3DTexture9 *m_pTexture; float m_rot; BYTE m_alpha; public: TaskEx(void); static void InitTaskList(void); void Delete(int id); static void DrawTask(ID3DXSprite *pSprite); static void DrawTask(ID3DXSprite *pSprite,int id); static DWORD GetCount(int id); static void* GetTask(int id,DWORD number); void GetData(DATA *pData); virtual void Draw(ID3DXSprite *pSprite)=0; // 描画関数 }; enum // グループ識別子 { PLAYER,ENEMY,MYSHOT,ENEMYSHOT,EXPLOSION,CONTROLPLAYER, CONTROLENEMY,STAGE,LIFEBAR,SCORE,TITLE,GAMEOVER };
タスクリストとゲームの初期化
TaskEx
クラスのInitTaskList
メンバ関数は、Task
クラスのInitTaskList
メンバ関数を呼び出した後に、ゲームの初期化をします。ここでは、乱数の初期化、およびTitle
タスクの生成・追加をすることにしました。
#include"TaskSystemEx.h" #include"task.h" // for Title // タスクリストとゲームの初期化 void TaskEx::InitTaskList(void) { Task::InitTaskList(); srand((unsigned)time(NULL)); new Title(); }
全てのタスクを描画
タスクは、描画関数であるDraw
を呼び出すことにより描画します。描画関数の内部でタスクの追加や削除が行われることはありませんが(可能ですが、自主的に禁止しましょう)、処理関数に似せたプログラムとしました。
// 全てのタスクを描画 void TaskEx::DrawTask(ID3DXSprite *pSprite) { if(pSprite==NULL) return; TaskEx *task,*next; for(task=(TaskEx*)m_active; m_active; task=next) { task->Draw(pSprite); next=(TaskEx*)task->m_next; if(next==(TaskEx*)m_active) break; } }
指定したグループのタスクだけを描画
一部のグループのタスクを描画しない、などの用途に使います。
// 指定したグループのタスクだけを描画 void TaskEx::DrawTask(ID3DXSprite *pSprite,int id) { if(pSprite==NULL) return; TaskEx *task,*next; for(task=(TaskEx*)m_active; m_active; task=next) { if(task->m_id == id) task->Draw(pSprite); next=(TaskEx*)task->m_next; if(next==(TaskEx*)m_active) break; } }
自分以外の指定したグループのタスクだけを削除
ボスの敗北に同期してザコを一掃する、特殊攻撃により弾を一掃する、などの用途に使います。
// 自分以外の指定したグループのタスクだけを削除 void TaskEx::Delete(int id) { TaskEx *task,*next; for(task=(TaskEx*)this->m_next; task!=this; task=next) { if(task->m_id == id) { delete task; } next=(TaskEx*)task->m_next; } }
指定したグループのタスク数を返す
主にGetTask
メンバ関数と組み合わせて使います。
// 指定したグループのタスク数を返す DWORD TaskEx::GetCount(int id) { DWORD count=0; TaskEx *task,*next; for(task=(TaskEx*)m_active; m_active; task=next) { if(task->m_id == id) count++; next=(TaskEx*)task->m_next; if(next==(TaskEx*)m_active) break; } return count; }
指定したグループの指定した順番のタスクを返す
グループ識別子、および先頭を0とする順番によりタスクを指定し、取得するために使います。
// 指定したグループの指定した順番のタスクを返す // タスクは優先度の値が小さい順につながっている // number:先頭を 0 とする順番 void* TaskEx::GetTask(int id,DWORD number) { DWORD count=0; TaskEx *task,*next; for(task=(TaskEx*)m_active; m_active; task=next) { if(task->m_id == id && count++ == number) return task; next=(TaskEx*)task->m_next; if(next==(TaskEx*)m_active) break; } return NULL; }
自分のデータを取得
自分以外のタスクを取得した場合に、アクセス制限に阻まれて参照できないメンバ変数たちを読み取るために使います。参照されては困るもの(例えばポインタ)は渡さないようにしましょう。
// 自分のデータを取得 void TaskEx::GetData(DATA *pData) { if(pData==NULL) return; pData->id = m_id; pData->cx = m_cx; pData->cy = m_cy; pData->hit_cw = m_hit_cw; pData->hit_ch = m_hit_ch; pData->speed = m_speed; pData->life = m_life; pData->max_life = m_max_life; pData->rot = m_rot; pData->alpha = m_alpha; }
コンストラクタ
メンバ変数の初期化を行います。
// コンストラクタ TaskEx::TaskEx(void) { m_id=0; m_cx=0; m_cy=0; m_hit_cw=0; m_hit_ch=0; m_speed=0; m_life=0; m_max_life=0; m_pTexture=NULL; m_rot=0; m_alpha=0xff; }