第8回:敵vsプレイヤー(4)

 敵対プレイヤーの処理はだいたいできましたが、プレイヤーの当たり判定でいくつか気になる点がありますので、これらを修正していくことにしましょう。

プレイヤーの当たり判定を小さくする

 今の状態では「スプライトのサイズ=当たり判定」のため、グラフィックの上では重なっていないのに、プレイヤーは爆発してしまいます。これを解決するには、CPlayerクラスにて、CCharactor::GetHitRect()をオーバーライドし、実際の領域より一回り小さい領域を、判定時に用いるようにさせるとよいでしょう。

class CPlayer : public CCharactor
{
    /* 省略 */

public:
    virtual void GetHitRect(RECTF &result);
};
void CPlayer::GetHitRect(RECTF &result)
{
    CCharactor::GetHitRect(result);
    result.Deflate(24.0f, 24.0f);
}
 ちなみに、ゲーム画面が敵の弾で覆い尽くされんばかりに飛び交うタイプのシューティング(弾幕シューティング)でプレイヤーが思いの外やられないのは、プレイヤーの当たり判定がびっくりするほど小さいためです。


弾幕シューティングの先駆け「怒首領蜂」におけるプレイヤーの当たり判定(赤色)

プレイヤーの当たり判定をなくす

 前回のムービーを見てお気づきになったとは思いますが、プレイヤーが爆発して画面上から消滅した後も、当たり判定の領域は残っているため、敵がプレイヤーがかつて存在していた位置を通過しようとするたびに爆発処理が行われています。また、プレイヤーがやられてゲーム進行が終わってしまっては、デバッグが非常に不便なので、プレイヤーが破壊された後や、特別な指示があった場合は、当たり判定を一切なくすようにしてしまいましょう。
class CPlayer : public CCharactor
{
    /* 省略 */
private:
    bool noenemy;   // 無敵状態のフラグ(trueなら無敵)
public:
    void SetNoEnemy(bool flag); // 無敵フラグを変更するための関数
}
CPlayer::CPlayer()
{
    /* 省略 */

    noenemy = false;    // テストプレイ時はtrueにしておくといい
    destroyed = false;
}

void CPlayer::GetHitRect(RECTF &result)
{
    if(destroyed == true || noenemy == true){
        // いかなるキャラクターとも重なることがない領域を設定
        result.SetRect(-10000.0f, -10000.0f, -10000.0f, -10000.0f);
    }else{
        CCharactor::GetHitRect(result);
        result.Deflate(24.0f, 24.0f);
    }
}

void CPlayer::SetNoEnemy(bool flag)
{
    noenemy = flag;
}
 今回は省略しますが、noenemyフラッグがtrue、つまり無敵状態の時は、プレイヤーキャラクターを点滅させるなどの処理があると、よりゲームをプレイする人にとってはわかりやすくなるでしょう。