35:列挙関数を作ってみよう
ゲームの規模が大きくなるにつれて、タスクリストには多種多様なデータが格納されるようになります。必要なデータを探し出す処理を逐一記述するのも面倒なので、必要なオブジェクトのみを抜き出す機能を追加することにしましょう。class CEnumeration
{
protected:
list<ListData>::iterator ipos, iend;
public:
virtual CGameObject* GetNext() = 0;
};
class CKeyEnum : public CEnumeration
{
private:
char keyword[NAME_SIZE];
public:
friend CGameObject;
virtual CGameObject* GetNext();
};
class CPrioEnum : public CEnumeration
{
private:
int start, end;
public:
friend CGameObject;
CGameObject* GetNext();
};
void CGameObject::CreateEnumeration(const char *keyword, CKeyEnum *cenum)
{
cenum->ipos = objectlist.begin();
cenum->iend = objectlist.end();
strcpy_s(cenum->keyword, NAME_SIZE, keyword);
}
void CGameObject::CreateEnumeration(int p_begin, int p_end, CPrioEnum *cenum)
{
cenum->ipos = objectlist.begin();
cenum->iend = objectlist.end();
cenum->start = p_begin;
cenum->end = p_end;
}
CGameObject* CKeyEnum::GetNext()
{
// キーワードとオブジェクト名の先頭が一致すれば
// そのオブジェクトのポインタを返す
char *p1, *p2;
while(ipos != iend){
p1 = keyword;
p2 = (*ipos).name;
while(*p1 != '\0'){
if(*p1 != *p2) break;
p1++;
p2++;
}
if(*p1 == '\0'){
CGameObject *g = ipos->gameobj;
ipos++;
return g;
}
ipos++;
}
// 見つからなければNULLを返す
return NULL;
}
CGameObject* CPrioEnum::GetNext()
{
// 指定範囲内の優先度値をもつオブジェクトがあれば
// そのオブジェクトのポインタを返す
while(ipos != iend){
if(ipos->priority > this->end){
ipos = iend;
return NULL;
}else if(ipos->priority >= this->start){
CGameObject *g = ipos->gameobj;
ipos++;
return g;
}
// 見つからなければNULLを返す
ipos++;
}
return NULL;
}
dynamic_cast
では<>内のクラスへの変換ができないときはNULLを返してくれるので、複数の種類のクラスが返される可能性がある場合はこれを使うとよいでしょう。
class CEnumTestStart : public CGameObject
{
protected:
void Init();
void Exec();
};
class CStringData : public CGameObject
{
public:
TCHAR str[10];
CStringData(LPCTSTR s){
_tcscpy_s(str, 10, s);
}
};
#include "EnumTest.h"
void CEnumTestStart::Init()
{
char name[NAME_SIZE];
for(int i = 0; i < 20; i++){
sprintf_s(name, NAME_SIZE, "teki_%d", i);
AppendObject(new CStringData(_T("敵です")), 1000 + i * 10, name, true);
i++;
sprintf_s(name, NAME_SIZE, "mikata_%d", i);
AppendObject(new CStringData(_T("味方です")), 1000 + i * 10, name, true);
}
RemoveObject(this);
}
void CEnumTestStart::Exec()
{
CKeyEnum e;
CreateEnumeration("mikata", &e);
CGameObject *g;
CStringData *s;
while(g = e.GetNext()){
s = dynamic_cast<CStringData*>(g);
if(s) DXTRACE_MSG(s->str);
}
PostQuitMessage(NULL);
}