Skip to content
第26回 前方の索敵と射程

1 / 1 前方の相手と射程 ​

このステップの目的

前方の相手のうち最も近い個体を選び、射程内で停止します。

第26回の到達版では、味方が敵の手前で止まります。開始時の敵1体は講師側の確認用です。敵がいないときといるときで、味方の停止位置を比べてください。

座標の方向 ​

味方は右へ進むので方向を1、敵は左へ進むので方向を-1とします。(相手X - 自分X) × 方向が0以上なら、相手は前方にいます。射程は中心のX座標の距離で測り、画像の幅を使いません。

索敵を実装する ​

Battle.cppのBattle::FindTargetを置き換えます。最初の候補を相手拠点にし、units_を調べて同じ所属とHPが0以下の個体を除きます。前方の相手で、現在の候補より近ければ対象を更新します。

戻り値Targetのunitは個体の位置を表し、-1は拠点を表します。distanceは0以上の距離です。小さな丸め誤差の範囲として-0.001以上も同位置と扱います。等距離では後に調べた個体を選ぶ仕様です。

移動処理はすでにFindTargetを呼ぶため、接続を書き足す必要はありません。ビルド後、出撃した味方が敵を通り抜けず、中心間距離が28で止まることを観察します。

射程を変える ​

LessonData.cppの射程28を56へ変えると、停止位置はどちらへ動くか予想してください。動作を確認し、画像のサイズと射程が独立している理由を説明します。確認後は28へ戻します。

実装後に比較する参考コード
Source/TowerDefense/Battle.cppcpp
Target Battle::FindTarget(const UnitInstance& unit) const
{
    const double direction = unit.team == Team::Ally ? 1 : -1;
    const double base = unit.team == Team::Ally ? tuning::EnemyBaseX : tuning::AllyBaseX;
    Target result{ -1, std::max(0.0, (base - unit.x) * direction) };
    for (std::size_t i = 0; i < units_.size(); ++i)
    {
        const auto& candidate = units_[i];
        if (candidate.team == unit.team || candidate.hp <= 0) continue;
        const double distance = (candidate.x - unit.x) * direction;
        if (distance >= -0.001 && distance <= result.distance)
            result = { static_cast<int>(i), std::max(0.0, distance) };
    }
    return result;
}
チェックリスト

今回の変更箇所を指し示し、観察した結果とその理由を説明できますか。実験後の値とファイルを確認して次へ進みます。

ゲームプログラミング実践