第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();
    }
}
 これがプログラムの実行例です。