2D RTSのグループでのAI移動の終了位置の決定


8

私は、RTSゲーム(実際にはある種のゲームエンジンのデモ)を作成しました。このゲームでは、ユーザーがゲームで行う基本的な操作は、兵士の束を選択し、マップを右クリックして、指定された場所に移動します。これはJavaScriptであり、ここコード)で遊ぶことができます。

兵士が現在の場所から目的地にどのように移動するかという問題を無視して、私の質問は彼らの実際の目的地が何であるかを決定することについてです。これが私がこれまでに試したことです:

  • 試行1:選択したすべての兵士に、マウスをクリックした座標に移動するように伝えます。これは奇妙な振る舞いで、すべての兵士が不自然にターゲットの周りに集まります。
  • 試行2:選択されたすべての兵士の平均座標を見つけ、各兵士のその中心点からのオフセットを見つけ、最後にそのオフセットをマウス座標の周りに変換します。これは、選択した兵士が離れている場合、ターゲットに近づかないことを除いて、正常に機能します。
  • 試行3:マウス座標の周りにグリッドを作成し、選択した各兵士をグリッドのセルに配置します。各兵士が割り当てられたセルに到達すると、これはうまく機能します。ただし、グリッドセルには兵士が生成された順序で割り当てられるため、衝突する場合があります(つまり、右側のすべての兵士が左側に移動しようとします)。これは不自然に見えます。
  • 試行4:以前と同じようにグリッドを使用しますが、最初に兵士を場所別に並べ替えて、それらが適切に並ぶようにします。つまり、グループの下をクリックした場合、グループの最下部の兵士は、グリッドの最下部に配置されます。彼らの目的地に到達します。これはかなりうまく機能しますが、不具合が時々あり、その理由はわかりません。

次に、宛先座標を決定する関数を示します。

function moveSelectedSoldiersToMouse() {
  var w = 0, h = 0, selected = [];
  // Get information about the selected soldiers.
  myTeam.soldiers.forEach(function(soldier) {
    if (soldier.selected) {
      selected.push(soldier);
      w += soldier.width;
      h += soldier.height;
    }
  });
  var numSelected = selected.length, k = -1;
  if (!numSelected) return;
  // Build a grid of evenly spaced soldiers.
  var sqrt = Math.sqrt(numSelected),
      rows = Math.ceil(sqrt),
      cols = Math.ceil(sqrt),
      x = Mouse.Coords.worldX(),
      y = Mouse.Coords.worldY(),
      iw = Math.ceil(w / numSelected), // grid cell width
      ih = Math.ceil(h / numSelected), // grid cell height
      wg = iw*1.2, // width of gap between cells
      hg = ih*1.2; // height of gap between cells
  if ((rows-1)*cols >= numSelected) rows--;
  w = iw * cols + wg * (cols-1); // total width of group
  h = ih * rows + hg * (rows-1); // total height of group
  // Sort by location to avoid soldiers getting in each others' way.
  selected.sort(function(a, b) {
    // Round to 10's digit; specific locations can be off by a pixel or so
    var ax = a.x.round(-1), ay = a.y.round(-1), bx = b.x.round(-1), by = b.y.round(-1);
    return ay - by || ax - bx;
  });
  // Place the grid over the mouse and send soldiers there.
  for (var i = 0; i < rows; i++) {
    for (var j = 0; j < cols; j++) {
      var s = selected[++k];
      if (s) {
        var mx = x + j * (iw+wg) - w * 0.5 + s.width * 0.5,
            my = y + i * (ih+hg) - h * 0.5 + s.height * 0.5;
        // Finally, move to the end destination coordinates
        s.moveTo(mx, my);
      }
    }
  }
}

デモを表示しているときにこの関数をブラウザーのJavaScriptコンソールに貼り付けて、兵士の行動を変更することができます。

私の質問は、次のとおりです。各兵士が移動するターゲットの場所を決定するより良い方法はありますか?


「群れ」と呼ばれるものは、あなたにとって非常に有用であり、あなたが探している機能のタイプを提供するかもしれません。試してみてください:processing.org/examples/flocking.htmlまたは単にgoogle "flocking"または "Boids"。それはあなたを正しい方向に導くかもしれません。
ディーンナイト

2
関連:gamedev.stackexchange.com/questions/44361私が経験している「グリッチ」は、すでに主張されている位置に移動しようとしているユニットからのものだと思います。それらが移動している位置が別のユニットのターゲットになっていないことを確認してください。かなりまともな結果が得られるはずです。
MichaelHouse

@DeanKnight、群がる動作の仕組みは知っていますが、ボットがポイントAからポイントBに移動する方法を制御します。
IceCreamYou 2013

@ Byte56:リンクをありがとう。私は文字通りユニットをグリッドスロットに入れていません-実装では、複数のユニットを同じスポットに向ける方法はありません。問題はソートが時々混乱すること以上のものであるようです。
IceCreamYou 2013

1
別のアイデア: Swarm Pathfinding。この場合、各ユニットに異なるエンドポイントを与えることはありません。(他のすべてのユニットが邪魔をしているため)エンドポイントへのパスが残っていないときに停止するか、まったく停止せずに衝突検出にその仕事を任せます。
BlueRaja-Danny Pflughoeft 2013

回答:


2

これがあなたのアイデアに関する私の提案です。

試み1:この状況を修正するには、Spencerが提起した「十分に近い」アイデアを実装できます。私はエンドポイントの周りにバブルを描くようなことをします、それはすでにそこにあるユニットの数とサイズの比率に基づいて成長します。バブルが1つのユニットのサイズから始まり、最初のユニットがそこに到達すると、次の2つのユニットの半径が2倍になる、などと言います。

試行2:この修正は、グループ間の平均距離を取得し、それから外れ値の距離を削減することで、グループが最初よりも束になります(メトリックはより短い/平均よりも長い、それがまともなように見えるもの、またはおそらく軍の数/サイズに基づいて最大フォームサイズを再度設定)心配する必要がある唯一のことは、外れ値のパスを変更するときです。 d他のパスに干渉しないことを確認して確認する必要があります

試行3:試行4でこれを改善した

試み4:このようなサウンドは、グリッチが原因で発生しているものを見つけた場合に問題なく機能します。ただし、リアリズム/ミリタリースタイルの場合を除いて、動きをもう少し自然に見せるために、グリッド構成以外のspahesで遊ぶことをお勧めします。 "移動する前に、それはしばらくしてプレーヤーに迷惑になるかもしれません。

試行4は、問題のミリング動作を削除するのに最も近いようですが、必要なこと以外に調整を行わずに動きを流し続けるという観点から、私のお気に入りはおそらく試行2でしょう。

しかし、まったく別の解決策として、パスファインディングに関しては2種類のオブジェクトを持つことができます。各ユニット、および非表示の「分隊」オブジェクト。

分隊-他のソリューションと同様に、分隊オブジェクトをグループの中心に構築し、パスファインディングを使用してそれを目的に向けます。

ユニット-ユニットはゴールを完全に無視し、代わりにパスファインディングを使用して、分隊オブジェクトから特定の距離(またはフォーメーション、またはその他のメトリックが最も動きがよくなる)に保ちます。

これにより、パスファインディングのさまざまな側面が分離され、どのように見えるかをより細かく制御するために、どちらかを個別に微調整することができます。


すばらしい答えです。新しいアイデアをありがとう。スクワッド+ユニットのアプローチは興味深いものであり、おそらく「キャッチアップ」モードでユニットがより速く移動できる必要があります
IceCreamYou

ええ、解決策として、「分隊」オブジェクトの移動速度を、単一ユニットが移動できる最大値の少し下に設定し、必要に応じて、ユニットが遅れることなく移動できるようにします。
David M

2

試行3は機能する可能性がありますが、少し改良が必要です。

フォーメーションの概念について考えてください(グリッドが始まりです)。フォーメーションには、場所(つまり、クリック座標、またはターゲットの兵士/建物)と回転(これは固定、ランダム、または確定的)が必要です。フォーメーションは、選択した兵士の数と同じ数のポジションを持つ必要があります。

シンプルなフォーメーションの例は、ターゲットの周りの円です。スペースを均等に配置し、円の半径を大きくして、衝突せずにすべての兵士にフィットさせます。

次の問題は、どの兵士がフォーメーションのどの位置まで歩くかを決定することです。簡単な解決策は、各兵士を自分に最も近い位置に移動させることです。その兵士が別の兵士によってすでに「選択」されている場合は、次の最も近い位置をとります。

フォーメーションはかなり面白くなります。以下は、ズールー族のシャカによって大成功を収めた「雄牛の角形成」の画像です。(画像はTotalWarフォーメーションModからのものです

牛角形成


「次の問題は、どの兵士がフォーメーションのどの位置まで歩くかを決めることです。」実際、それがこの質問の問題全体です。:)グリッドではなく円の形成の提案に賛成ですが、それは数人以上の兵士には効果がなく、兵士を彼らに最も近い場所に移動すると、場所でユニットをソートする上記の解決策よりも多くの競合が発生します。
IceCreamYou 2013

0

ユーザーがクリックしたら、すべての兵士からクリックした場所にベクトルを描画します。各兵士について描画されたベクトルから平均ベクトル角度を取得し、各角度を同じ角度でその方向に個々のベクトルの長さに移動します。これにより、ユニットがフォーメーションで要所まで移動しているように見え、ユニットが固まらないようにする必要があります。

ユニットをフォーメーション外に移動したい場合は、クリックした場所に直接兵士の角度を向けることができます。しかし、衝突がなければ、ユニットは収束し始めます。これに対抗するには、衝突を追加し、ユニットがクリックされたポイントに「十分近づく」と、ユニットの移動を強制的に停止します。到着する最初のユニットはまさにそのポイントにあり、到着する最後のユニットは、十分に近づいたり、一定の時間が経過したりすると移動を停止するように指示される必要があります。

パスの長さとユニット速度を計算して、1つのユニットが到着するタイミングを決定し、その時間を一定量超えると、ユニットの移動を強制的に停止できます。その数で少し遊ぶ必要があります。


あなたが提案しているベクトル解は、上の私の試み2と同じです。この質問の要件の1つは、選択したユニットがフォーメーションに含まれていない可能性があることです。
IceCreamYou 2013

そして私は彼らがフォーメーションで動かない解決策について書きました。(2番目の段落)
スペンサー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.