第7回:敵vsプレイヤー(3)
プレイヤーと敵の衝突を判定
敵とプレイヤーが衝突したときは、プレイヤーと敵の破壊処理をともにおこないます。衝突判定においては、CEnemy::Exec()が呼ばれるたびにプレイヤーがどこにいるかを調べることになるため、プレイヤークラスのポインタをCEnemyBase::Init()で読み取っておくことにします。
class CEnemyBase : public CCharactor
{
protected:
CPlayer *player; // プレイヤークラスのポインタを追加
int hardness;
virtual void Init();
public:
virtual void Damaged();
};
void CEnemyBase::Init()
{
player = (CPlayer*)FindItemBox("player");
}
プレイヤーが敵に衝突された際の破壊処理をCPlayerクラスに追加します。今回行うプログラム手法(CEnemyBaseクラス内で常にCPlayerクラスへのポインタを監視する)では、CPlayerクラスを削除してしまうとCPlayerへの参照が見つからず、プログラムエラーになってしまいます。そのため、CPlayerクラス内にdestroyedフラグを用意しておき、このフラグがオンである(つまりプレイヤーが破壊された)場合は、CPlayer::Exec()での処理を一切行わないようにすることで、この問題を回避しています。
class CPlayer : public CCharactor
{
/* 省略 */
private:
bool destroyed;
public:
void Destroy();
}
#include "Explosion.h"
CPlayer::CPlayer()
{
/* 省略 */
destroyed = false;
}
void CPlayer::Exec()
{
// 関数の先頭に追加
if(destroyed == true) return;
/* 省略 */
}
void CPlayer::Destroy()
{
destroyed = true;
// 爆発クラスの追加
AppendObject(new CExplosion(x, y), EXPLOSION_PRIORITY, true);
}
続いてCEnemyBaseの派生クラス(CEnemy1)のExec()において、プレイヤーとの衝突処理を行います。
void CEnemy1::Exec()
{
/* 省略 */
sprite.Draw(x, y);
if(player->HitTest(this)){
player->Destroy();
this->Damaged();
}
}
これがプログラムの実行例です。