第9回:敵vsプレイヤー(5)

 特攻部隊だけではなく、弾を発射する敵も作ることにしましょう。弾を発射させるだけなら、特別難しいことはありません。弾頭クラスを作成し、そのクラスを敵の行動パターン内の任意のタイミングで新規作成するだけです。
#define ENEMYBULLET_PRIORITY 65000

class CEnemyBullet : public CCharactor
{
private:
    CPlayer *player;        // ターゲットとなるプレイヤークラス
    float move_x, move_y;   // 1フレームごとの移動距離
public:
    // sx,sy:初期位置 angle:移動方向 speed:移動方向
    CEnemyBullet(float sx, float xy, float angle, float speed);
    virtual void Init();
    virtual void Exec();
};
CEnemyBullet::CEnemyBullet(float sx, float sy, float angle, float speed)
{
    x = sx;
    y = sy;
    move_x = cosf(angle) * speed;
    move_y = sinf(angle) * speed;
}

void CEnemyBullet::Init()
{
    sprite.SetTexture((CTexture*)FindItemBox("ebullet"));
    player = (CPlayer*)FindItemBox("player");
}

void CEnemyBullet::Exec()
{
    // プレイヤーとの衝突判定
    if(player->HitTest(this) == true){
        player->Destroy();
        RemoveObject(this);
        return;
    }

    x += move_x;
    y += move_y;
    if(x < -50.0f || x > 700.0f || y < -50.0f || y > 520.0f){
        // 画面外に出たら削除
        RemoveObject(this);
        return;
    }

    sprite.Draw(x, y);
}
 プログラムを実行するときは、敵弾テクスチャの作成・読み込みを忘れないようにしましょう。

 以下の敵サンプルでは、下に移動しながら、1回だけプレイヤーに向かって弾を発射するようにしています。ちなみに、特定の場所と別の場所との角度を計算するにはatan2()を使います。
class CEnemy2 : public CEnemyBase
{
private:
    bool shoot; // 発射済みかどうかのフラグ
public:
    CEnemy2(float sx);
protected:
    virtual void Init();
    virtual void Exec();
};
CEnemy2::CEnemy2(float sx)
{
    x = sx;
    y = -16.0f;
    hardness = 1;
    shoot = false;
}

void CEnemy2::Init()
{
    CEnemyBase::Init();

    sprite.SetTexture((CTexture*)FindItemBox("zakotex"));
    sprite.SetSpriteSize(32, 32);
    sprite.SetFrame(6);
}

void CEnemy2::Exec()
{
    if(shoot == false && y > 100){
        float angle = atan2f(player->GetPosY() - y, player->GetPosX() - x);
        AppendObject(
            new CEnemyBullet(x, y, angle, 2.0f),
            ENEMYBULLET_PRIORITY, true);
        shoot = true;
    }

    y += 2.0f;

    if(y > 480.0f + 16.0f || x < -16.0f || x > 640.0f + 16.0f)
    {
        RemoveObject(this);
        return;
    }

    sprite.Draw(x, y);

    if(player->HitTest(this)){
        player->Destroy();
        this->Damaged();
    }
}