Appearance
第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;
}チェックリスト
今回の変更箇所を指し示し、観察した結果とその理由を説明できますか。実験後の値とファイルを確認して次へ進みます。