7. ECSで作り直し
はじめに
ECS(Entity Component System)という設計スタイルのことを知ったので、ECSを使って、このヴァンサバ風ゲームを作り直してみます。
ECSとは?
Entity Component Systemの基本
| 構成要素 | 説明 |
|---|---|
| Entity | 識別用のID。見た目も中身も持たない「ただの番号」 |
| Component | データのまとまり(位置、速度、体力など) |
| System | 複数のEntityを処理するロジック(移動、描画、AIなど) |
ECSの特徴は「データとロジックを分離」と「責任の分離」 です。
- EntityはID(number)のみです。
- Componentはデータのみを持ち、ロジックは一切入れません。
- Systemがロジックを受け持ちます。Phaserではupdateで毎フレーム呼び出されるものになります。
従来のオブジェクト指向との違い
| オブジェクト指向 | ECS | |
|---|---|---|
| プレイヤー | Playerクラスで位置・移動・描画を持つ | Entity + PositionComponent + SpriteComponent + MovementSystem |
| 継承 | クラスを継承して機能追加 | コンポーネントを付け替えて機能追加 |
| 柔軟性 | 低い(カチッとした構造) | 高い(動的に機能を変えられる) |
ヴァンサバ風ゲームに必要なECS構成
Phaser + TypeScriptで、ヴァンサバ風のトップビューゲームを作るとしたら、 以下のようなEntity / Component / System構成になります:
Entity(エンティティ)
- Player : 操作するプレイヤーキャラクター。1体だけ存在
- Enemy : 敵キャラ。大量に生成される
- Projectile : 武器から発射される弾。敵に当たったり時間経過で消える
- Item : ポーション、宝箱など
Component(コンポーネント)
- SpriteComponent: 対応するSpriteへの参照
- HealthComponent: HP、最大HPなど
- PlayerInputComponent: プレイヤーの入力状態(上下左右)
- WeaponComponent: 武器の種類、攻撃力、発射間隔、弾速など
- ProjectileComponent: 弾のスピード、ダメージ、寿命など
- EnemyComponent: 敵のスピード、ダメージ、種類など
- TargetComponent: プレイヤーEntityID+追跡用オフセット
PositionComponent(位置)やVelocityComponent(移動速度)を作る方法もあるが、 Phaserのspriteで管理した方が簡単。
System(システム)
- PlayerInputSystem: キー入力を読み取り、速度や方向を更新
- RenderSystem: Spriteにアニメーションやエフェクトを反映
- WeaponSystem: 一定間隔で弾を発射(武器ごとの発射管理)
- ProjectileSystem: 弾の移動と寿命管理
- EnemyAISystem: 敵がプレイヤーを追いかける処理
- CollisionSystem: プレイヤー・敵・弾・壁などすべての衝突を管理
- GameOverSystem: HPが0になったらゲームオーバー処理を発動
ECS以外の要素
その他、Manager(管理クラス)やEntity生成用のファクトリ関数も必要です。
- ComponentManager.ts: 全Entityのコンポーネントを一括管理する静的マネージャ
- EntityManager.ts: Entity(ID)の発行と削除を担当
- GameConfig.ts: 定数定義
- createPlayer.ts: プレイヤーEntityを生成し、必要なComponentを登録
- createEnemy.ts: 敵Entityを生成し、必要なComponentを持たせる
- createProjectile.ts: 弾Entityを生成し、速度やダメージなどを設定
まとめ
PlayerもEnemyもEntityでは単なるIDにすぎず、 PlayerクラスやEnemyクラスを作らないことに、最初は違和感がありました。
しかし、実際に作ってみると、Gameシーンでは、各Systemを初期化してUpdateで回すだけ。 各Systemが自分の担当範囲のことだけに集中できるので、全体として構造はかなりスッキリします。
今までの方法よりも開発がかなり速く進むようになり、おかげでかなり進みました。
実装したもの
- マップ画像や敵キャラ画像のリニューアル
- 敵キャラの追加(定期的にスポーン)
- プレイヤーの攻撃
- ゲームオーバー処理
- アセットローディング処理
