11. 敵キャラの追加とWave処理
はじめに
現在は、スライムが定期的にスポーンして襲ってくるだけですが、敵キャラを増やして、Waveを実装したい。
方針
- EnemyConfigで敵データを定義
- WaveConfigでWaveデータを定義
- WaveSystemを追加して、Waveデータにそって敵をスポーン
- createEnemyでEnemyTypeによって異なる敵を作成
実装
EnemyConfig.ts
- EnemyTypeで種類を定義
- EnemyConfigで種類ごとのパラメータを定義
export type EnemyType = "slime" | "spider" | "bat";
export const EnemyConfig = {
enemies: {
slime: {
maxHp: 10,
speed: 50,
damage: 5,
},
spider: {
maxHp: 30,
speed: 100,
damage: 5,
},
bat: {
maxHp: 20,
speed: 120,
damage: 8,
},
...
},
};WaveConfig.ts
- 各Waveの情報(長さや敵の数や種類)をWavesに定義
- poolでは敵の種類ごとの比率をしていする
- 直接、出現数を指定する方法もあり
import { EnemyType } from "./EnemyConfig";
export interface WaveConfig {
duration: number | null; // 継続時間、エンドレスならnull
total: number; // 敵の合計数
spawnInterval: number; // 出現間隔
pool: Partial<Record<EnemyType, number>>; // 敵の種類と出現確率(合計100)
}
export const Waves: WaveConfig[] = [
{ duration: 30_000, total: 30, spawnInterval: 1_000, pool: { slime: 100 } },
{ duration: 40_000, total: 50, spawnInterval: 800, pool: { slime: 70, spider: 30 } },
...
{ duration: null, total: 9999, spawnInterval: 500, pool: { bat: 100 } },
];WaveSystem.ts
- updateで現在のwaveに応じて敵をスポーン
- wave情報に応じて、どの敵をスポーンするか決定
- 今回はpoolの比率に応じてランダムで決めている
- 別の方法として、wave開始時に長さtotalの配列を作ってしまうのもあり
コードは長くなるので概要のみ
export class WaveSystem {
...
private waveIndex = 0;
private elapsed = 0; // Wave経過時間
private spawnTimer = 0; // 次のスポーンまでのタイマー
private spawned = 0; // スポーンした数
update(delta: number) {
const wave = Waves[this.waveIndex];
if (!wave) return; // すべてのWaveが終了
// elapsed,spawnTimerを更新
...
// spawnIntervalが経過するごとに敵をスポーン (spawnEnemyByPoolを呼ぶ)
...
// 設定時間が経過、または敵の全滅をチェックしてWaveを終了 (nextWaveを呼ぶ)
...
}
private spawnEnemyByPool() {
// プールから敵をランダムに選択
...
// プレイヤーの周囲200~400pxランダムに出現
...
createEnemy(this.scene, x, y, playerEntity, type);
}
private nextWave() {
// 次のWaveの準備
...
// イベント発火
this.scene.game.events.emit("WaveStarted", { waveIndex: this.waveIndex });
}
}createEnemy.ts
敵の生成を行います。spriteとanimationのkeyを切り替えるだけです。
export function createEnemy(
scene: Phaser.Scene,
x: number,
y: number,
targetEntity: Entity,
enemyType: EnemyType
): number {
const entity = EntityManager.createEntity();
// enemyTypeごとのスプライト設定
const sprite = scene.physics.add.sprite(x, y, enemyType);
sprite.play(enemyType);
sprite.setOrigin(0.5);
sprite.setCollideWorldBounds(true);
// enemyTypeごとのパラメータ設定
const { maxHp, speed, damage } = EnemyConfig.enemies[enemyType];
ComponentManager.set("enemyTag", entity, {});
ComponentManager.set("sprite", entity, { sprite });
ComponentManager.set("target", entity, { targetEntity });
ComponentManager.set("health", entity, { hp: maxHp, maxHp });
ComponentManager.set("speed", entity, { speed });
ComponentManager.set("damage", entity, { damage });
// イベント発火
scene.game.events.emit("EnemyCreated", { entity, sprite });
}まとめ
これだけで複数の敵が襲ってくるようになりました。次は敵ごとに移動パターンを変えます。
