Appearance
第22回 敵の物理と巡回状態
1 / 4 敵キャラクターの状態管理とライフサイクル
このステップの目的
敵単体のワールド座標、速度、向き、当たり判定、および活動状態(EnemyState)をカプセル化し、生成・更新・撃破というライフサイクルを制御する基盤を実装します。
状態列挙型によるライフサイクル管理
敵キャラクターは、ゲーム中に「出現し、ステージ上を巡回し、倒されて退場する」というライフサイクルを持ちます。この生存状態を表現するために、状態列挙型 EnemyState を定義します。
Enemy.hcpp
enum class EnemyState
{
Patrol, // 巡回活動中
Defeated // 撃破されて無効化
};単純な真偽値フラグ(bool)ではなく列挙型を採用することで、将来的に「気絶状態(Stun)」などの状態を追加する際にも、既存の構造を崩さずに拡張できます。
リセットと撃破による状態遷移
敵キャラクターの初期化処理(Reset)と撃破処理(Defeat)を実装します。
Enemy.cppcpp
void Enemy::Reset(const dxgame::Vector2& position)
{
position_ = position;
velocity_ = {};
remainderX_ = 0.0f;
remainderY_ = 0.0f;
onGround_ = false;
facingRight_ = false;
state_ = EnemyState::Patrol;
}
void Enemy::Defeat()
{
state_ = EnemyState::Defeated;
velocity_ = {};
remainderX_ = 0.0f;
remainderY_ = 0.0f;
}配列から要素を削除しない理由(論理削除)
敵が倒された際、配列から要素を削除して詰める処理(std::vector::erase など)を行うと、ループ処理中のイテレータ無効化やメモリ再配置の負荷が生じます。
状態を EnemyState::Defeated に切り替える論理削除を採用することで、IsActive()(=state_ == EnemyState::Patrol)の真偽を確認するだけで、更新・描画・当たり判定の処理ループから安全に対象外とすることができます。
当たり判定と描画矩形の分離
プレイヤーの設計と同様に、敵キャラクターにおいても当たり判定矩形(Hitbox)と描画矩形(DrawRect)を分離します。
Enemy.cppcpp
dxgame::Rect Enemy::GetHitbox() const
{
return tuning::enemy::Hitbox.MovedBy(position_);
}
dxgame::Rect Enemy::GetDrawRect() const
{
return tuning::enemy::DrawRect.MovedBy(position_);
}グラフィック素材のサイズ(描画領域)とゲームの衝突判定領域を独立して設定できるようにすることで、素材画像の余白に影響されない安定した衝突判定を維持できます。
チェックリスト
-
EnemyState列挙型を用いて敵の生存状態と撃破状態を管理できる - 敵を配列から物理削除せず、論理削除によって安全に処理対象から除外する理由を説明できる
- 敵の当たり判定矩形と描画矩形を分離し、見た目と衝突領域を独立して管理できる