ホームページ > ウェブフロントエンド > jsチュートリアル > 範囲内の最も遠い敵を攻撃する (タワーディフェンス)

範囲内の最も遠い敵を攻撃する (タワーディフェンス)

Linda Hamilton
リリース: 2024-12-12 12:59:11
オリジナル
502 人が閲覧しました

前の記事では、最大ヒープを使用して最も遠い敵を効率的に追跡する方法を示しました。この記事では、それをゲームの仕組みに組み込む方法を見ていきます。

イベント駆動型アプローチ

既存の実装では、イベント駆動型のアーキテクチャが使用されています。この記事では、敵のイベントに焦点を当てます。これらのイベントはスピンオフ アクションをトリガーします。

各敵はさまざまなイベントを経験できます。以下は、敵が通過する可能性のあるライフサイクルの例です:

Attacking the Furthest Enemy in Range (Tower Defence)

この記事に関しては、次の 2 つのイベントに興味があります:

  • emoneMoved: 敵の位置が変化したときに発生します。
  • emoneRemoved*: 敵がゲームから削除されたとき (例: 敗北したとき) に起動されます。

(※敵は様々な理由で削除される可能性があるため、イベント名は今後調整する予定です。)

プラン

さまざまなイベントがどのように相互作用するかを視覚化するために、イベント モデル図を作成しました。これは、物事がどのように接続されているかを理解するのに役立ちます。

Attacking the Furthest Enemy in Range (Tower Defence)

すべてのイベントに対して、それをトリガーするコマンドがあります。 (つまり、イベントはコマンドの結果です。) 場合によっては、イベントの結果として、データを更新する必要があります (緑色の付箋がこれを示しています)。 3 つすべてを組み合わせると、垂直スライスとなります。

私は緑色の付箋「タワーの範囲内の敵」に注目します。

実装

目標は、敵がタワーの範囲内にいるときはいつでも利用可能な敵を更新し、そうでない場合は敵を除去することです。

タワークラスを使用して作業します。このクラスには、敵を格納する変数があります。

export class Tower implements ITower {
    public enemies = new MaxHeap()

    constructor(id: number, coords: Coordinate) {
        this.id = id
        this.coords = coords

        // listeners will go here...
    }
ログイン後にコピー
ログイン後にコピー

Tower クラスにイベント リスナーを配置すると、ロジックが集中化され、タワーと敵の間のマッピングを維持する必要性が減ります。これにより、クラスがいくらか複雑になりますが、カプセル化が確実に強化され、デバッグが簡素化されます。現時点では、これが採用しやすい方向です。

アクション: 範囲内に敵を追加する

テスト: 敵の追加

まず、範囲内の敵がタワーの敵の山に追加されることを確認するテストを作成します。

it('should add an enemy to the tower when enemy is within range', () => {
    const tower = new Tower(1, { col: 0, row: 1 });
    const enemy = new TinyEnemy();
    enemy.currentPosition = { col: 0, row: 1 };

    triggerEnemyMovedEvent(enemy);

    expect(tower.enemies.length()).toBe(1);
});
ログイン後にコピー
ログイン後にコピー

実装: 敵の追加

対応する実装は次のとおりです:

window.addEventListener("enemyMoved", event => {
    const enemy: Enemy = event.detail.enemy;

    if (enemyWithinRange(this, enemy)) {
        this.enemies.insertOrUpdate(enemy.id, enemy.distanceTraveled);
    }
});
ログイン後にコピー
ログイン後にコピー

emoneMoved がトリガーされるたびに、敵をヒープに追加する必要があるかどうかをチェックします。すでにemoneWithinRange関数があるので、insertOrUpdate呼び出しを追加するだけです。


アクション: 範囲外の敵を追加しないようにする

テスト: 範囲外の敵を無視する

次に、タワーの範囲外の敵が追加されないようにします。

export class Tower implements ITower {
    public enemies = new MaxHeap()

    constructor(id: number, coords: Coordinate) {
        this.id = id
        this.coords = coords

        // listeners will go here...
    }
ログイン後にコピー
ログイン後にコピー

実装: 範囲外の敵を無視する

このシナリオは、emoneWithinRange を使用した以前のチェックですでにカバーされているため、追加のコードは必要ありません。


アクション: 敵を範囲外に排除する

テスト: 射程外の敵を排除する

今度は、射程外に出た敵がタワーの視界から取り除かれることをテストします:

it('should add an enemy to the tower when enemy is within range', () => {
    const tower = new Tower(1, { col: 0, row: 1 });
    const enemy = new TinyEnemy();
    enemy.currentPosition = { col: 0, row: 1 };

    triggerEnemyMovedEvent(enemy);

    expect(tower.enemies.length()).toBe(1);
});
ログイン後にコピー
ログイン後にコピー

実装: 射程外の敵の排除

window.addEventListener("enemyMoved", event => {
    const enemy: Enemy = event.detail.enemy;

    if (enemyWithinRange(this, enemy)) {
        this.enemies.insertOrUpdate(enemy.id, enemy.distanceTraveled);
    }
});
ログイン後にコピー
ログイン後にコピー

敵が範囲内にいた場合は、敵を排除できます。


アクション: ゲームから敵を削除する

テスト:emoneRemoved イベントの処理

最後に、ゲームから削除された敵がタワーのヒープからも削除されることを確認します。

it('should not add an enemy to the tower if enemy is out of range', () => {
    const tower = new Tower(1, { col: 0, row: 1 });
    const enemy = new TinyEnemy();
    enemy.currentPosition = { col: 0, row: 99 };

    triggerEnemyMovedEvent(enemy);

    expect(tower.enemies.length()).toBe(0);
});
ログイン後にコピー

実装: 敵の削除の処理

it('should remove an enemy from the tower when it moves out of range', () => {
    const tower = new Tower(1, { col: 0, row: 1 });
    const enemy = new TinyEnemy();
    enemy.currentPosition = { col: 0, row: 1 };

    // enemy within range
    triggerEnemyMovedEvent(enemy);
    expect(tower.enemies.length()).toBe(1);

    // enemy outside of the range
    enemy.currentPosition = { col: 0, row: 99 };
    triggerEnemyMovedEvent(enemy);

    expect(tower.enemies.length()).toBe(0);
});
ログイン後にコピー

イベントがトリガーされるたびに、敵が範囲内にいる場合は敵を排除できます。

結論

イベント駆動型のアプローチと最大ヒープを組み合わせることで、タワーが敵に動的に優先順位を付ける効率的な方法を実現しました。この実装はゲームのイベント システムとシームレスに連携し、リアルタイムの更新と応答性を保証します。

さらに、テストに関しては、イベント駆動型のアプローチを使用すると、内部コードをテストに結び付ける必要がなくなります。したがって、テストの脆弱性が軽減されます。動作の背後にあるコードを任意の方法でリファクタリングでき、イベント/リスナーが正しく設定されている限り、テストは合格するはずです。

この実装により、次のことが可能になります。

  • 攻撃機能の追加 (誰を攻撃するかが分かりました)
  • 敵のデータの保存方法を交換する

このアプローチを独自のタワーディフェンス ゲームに自由に応用してください。

以上が範囲内の最も遠い敵を攻撃する (タワーディフェンス)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート