6

この質問にはまだ回答済みのマークを付けていません。
現在承認されている回答は、報奨金の時間制限のために自動的に承認されました


このプログラミングゲームを参考に、現在制作中です。

上記のリンクからわかるように、私は現在、ユーザーがプログラム可能なロボットがアリーナで自律的に戦うゲームを構築しています。


ここで、ロボットが特定の角度で別のロボットを検出したかどうかを検出する方法が必要です (タレットがどこを向いているかによって異なります)。

代替テキスト http://img21.imageshack.us/img21/7839/robotdetectionrg5.jpg

上の画像からわかるように、ゲーム内でエミュレートする必要がある戦車の一種の視点を描画しました。その各ポイントをチェックして、別のロボットが視野内にあるかどうかを確認します。

ボットは、バトル アリーナ (別のキャンバス) で常に翻訳されている単なるキャンバスです。

タレットの方向 (現在向いている方向) を知っているので、そのパスにボットがいるかどうかを確認する必要があります (パスは、「視点」のような方法で定義する必要があります。上の赤​​い「三角形」の画像. この画像が、私が伝えようとしていることをより明確にしてくれることを願っています.

誰かがこの問題を達成するためにどのような数学が関係しているかを教えてくれることを願っています.


[アップデート]

教えていただいた計算を試してみましたが、正しく機能していません。画像からわかるように、 bot1 は Bot2 を見ることができないはずです。例を次に示します。

代替テキスト http://img12.imageshack.us/img12/7416/examplebattle2.png

上記のシナリオでは、ボット 1 はボット 2 が見えるかどうかを確認しています。詳細は次のとおりです ( Waylon Flinn の回答によると):

angleOfSight = 0.69813170079773179 //in radians (40 degrees)
orientation = 3.3 //Bot1's current heading (191 degrees)

x1 = 518 //Bot1's Center X
y1 = 277 //Bot1's Center Y

x2 = 276 //Bot2's Center X
y2 = 308 //Bot2's Center Y

cx = x2 - x1 = 276 - 518 = -242
cy = y2 - y1 = 308 - 277 =  31

azimuth = Math.Atan2(cy, cx) = 3.0141873380511295

canHit = (azimuth < orientation + angleOfSight/2) && (azimuth > orientation - angleOfSight/2)
       = (3.0141873380511295 < 3.3 + 0.349065850398865895) && (3.0141873380511295 > 3.3 - 0.349065850398865895)
       = true

上記の計算によると、Bot1 は Bot2 を見ることができますが、画像からわかるように、それらは異なる方向を向いているため、それは不可能です。

上記の計算で何が間違っていますか?

4

9 に答える 9

3

ロボット間の角度は arctan(x-distance, y-distance) です (ほとんどのプラットフォームは、角度調整を行うこの 2 引数の arctan を提供します。次に、この角度がロボットから離れた数値よりも小さいかどうかを確認する必要があります。現在の見出し。


編集 2020 : これは、質問の更新されたサンプル コードと現在削除されているイメージシャック イメージに基づく、より完全な分析です。

  1. Atan2: 2 点間の角度を求めるために必要な重要な関数は ですatan2。これは、ベクトルの Y 座標と X 座標を取り、そのベクトルと正の X 軸の間の角度を返します。値は常に -Pi と Pi の間に収まるようにラップされます。

  2. 見出しと向き: atan2、および一般的にすべての数学関数は、「数学的標準座標系」で機能します。これは、角度「0」が真東に対応し、角度が反時計回りに増加することを意味します。Pi / 2したがって、によって与えられるの「数学的角度」はatan2(1, 0)、点 (x=0, y=1) に一致する「真東から反時計回りに 90 度」の向きを意味します。「船首方位」とは、方位を表す航法上の考え方で、真北から時計回りの角度です。

    • 分析: 現在削除されているイメージシャックの画像では、191 度の「向き」が南南西の方向に対応していました。これは、実際には -101 度または -1.76 の三角法の「方向」です。したがって、更新されたコードの最初の問題は、「見出し」と「方向」の混同です。またはによって前者から後者を取得できます。orientation_degrees = 90 - heading_degreesあるいはorientation_radians = Math.PI / 2 - heading_radians、入力方向を航海方位座標系ではなく数学的座標系で指定することもできます。
  3. ある角度が他の 2 つのベクトルの間にあることを確認する:ベクトルが他の 2 つのベクトルの間にあることを確認することは、角度の値がその間にあることを確認するほど簡単ではありません。

    • 分析: あなたの例では、方向は 3.3、ビューの右端は方向 2.95、ビューの左端は 3.65 です。計算された方位角は 3.0141873380511295 で、たまたま正しいです (間にあります)。ただし、これは、「ヒット」として計算する必要がある -3 のような方位角の値では失敗します。解決策については、角度が 2 つの角度の間にあるかどうかの計算を参照してください。
于 2009-02-18T01:12:06.247 に答える
1

ボットのクラス (C# コード) 内で次のようにします。

/// <summary>
/// Check to see if another bot is visible from this bot's point of view.
/// </summary>
/// <param name="other">The other bot to look for.</param>
/// <returns>True iff <paramref name="other"/> is visible for this bot with the current turret angle.</returns>
private bool Sees(Bot other)
{
    // Get the actual angle of the tangent between the bots.
    var actualAngle = Math.Atan2(this.X - other.X, this.Y - other.Y) * 180/Math.PI + 360;

    // Compare that angle to a the turret angle +/- the field of vision.
    var minVisibleAngle = (actualAngle - (FOV_ANGLE / 2) + 360);
    var maxVisibleAngle = (actualAngle + (FOV_ANGLE / 2) + 360); 
    if (this.TurretAngle >= minVisibleAngle && this.TurretAngle <= maxVisibleAngle)
    {
        return true;
    }
    return false;
}

ノート:

  • +360 は、負の角度を対応する正の値に強制し、角度 0 の境界ケースを範囲テストしやすい場所にシフトするためにあります。
  • これはラジアン角のみを使用して実行できる可能性がありますが、それらは汚れていて読みにくいと思います:/
  • 詳細については、Math.Atan2のドキュメントを参照してください。
  • ゲーム デザインを念頭に置いて作成されているXNA Frameworkを調べることを強くお勧めします。ただし、WPF は使用しません。

これは、次のことを前提としています。

  • 視界を遮る障害物がない
  • Bot クラスには X プロパティと Y プロパティがあります
  • X プロパティと Y プロパティは、ボットの中心にあります。
  • Bot クラスの TurretAngle プロパティは、x 軸に対して反時計回りのタレットの正の角度を示します。
  • Bot クラスには、砲塔の視野を示す FOV_ANGLE と呼ばれる静的定数角度があります。

免責事項:これはテストされておらず、コンパイルのチェックもされていません。必要に応じて変更してください。

于 2009-03-06T20:50:42.493 に答える
1

同様のものを実装した後のいくつかの提案(ずっと前に!):

以下は、戦場にいるすべてのボットをループしていることを前提としています (特に良い方法ではありませんが、すばやく簡単に何かを機能させることができます!)

1) ボットが範囲内にあるかどうかを確認する方がはるかに簡単です。

int range = Math.sqrt( Math.abs(my.Location.X - bots.Location.X)^2 + 
            Math.abs(my.Location.Y - bots.Location.Y)^2 );

if (range < maxRange)
{
    // check for FOV
}

これにより、多くの FOV チェックを短縮し、シミュレーションの実行プロセスを高速化できる可能性があります。注意点として、より興味深いものにするために、ここでいくらかのランダム性を持たせることができます。これにより、特定の距離の後、見る機会がボットの範囲に直線的に比例します。

2)この記事には、FOV 計算に関するものが含まれているようです。

3) AI の卒業生として ... ニューラル ネットワークを試してみると、ロボットが範囲内にあり、有効なターゲットであるかどうかを認識するようにトレーニングできます。これにより、恐ろしく複雑で複雑な数学が無効になります。多層パーセプトロン[1][2]を持つことができます。ボットの座標とターゲットの座標をフィードし、最後に適切な発砲/非発砲の決定を受け取ります。警告: この方法論は達成するのが最も簡単ではなく、失敗するとひどくイライラする可能性があることをお伝えしなければなりません. この形式のアルゴリズムの (単純な) 非決定論的性質により、デバッグは苦痛になる可能性があります。さらに、バック プロパゲーション (トレーニング ケースを使用) または遺伝的アルゴリズム (完璧にするための別の複雑なプロセス) のいずれかを学習する必要があります。選択肢が与えられた場合、私は 3 番を使用しますが、それは誰にとっても違います!

于 2009-03-10T10:32:51.790 に答える
1

これにより、キャンバス 2 の中心がキャンバス 1 に当たるかどうかがわかります。canvas2 の幅を考慮したい場合は、もう少し複雑になります。簡単に言えば、中央を 1 回チェックするのではなく、canvas2 の関連するコーナーごとに 1 回ずつ、合計 2 回チェックする必要があります。

/// assumming canvas1 is firing on canvas2

// positions of canvas1 and canvas2, respectively
// (you're probably tracking these in your Tank objects)
int x1, y1, x2, y2;

// orientation of canvas1 (angle)
// (you're probably tracking this in your Tank objects, too)
double orientation;
// angle available for firing
// (ditto, Tank object)
double angleOfSight;

// vector from canvas1 to canvas2
int cx, cy;
// angle of vector between canvas1 and canvas2
double azimuth;
// can canvas1 hit the center of canvas2?
bool canHit;

// find the vector from canvas1 to canvas2
cx = x2 - x1;
cy = y2 - y1;

// calculate the angle of the vector
azimuth = Math.Atan2(cy, cx);
// correct for Atan range (-pi, pi)
if(azimuth < 0) azimuth += 2*Math.PI;

// determine if canvas1 can hit canvas2
// can eliminate the and (&&) with Math.Abs but this seems more instructive
canHit = (azimuth < orientation + angleOfSight) &&
    (azimuth > orientation - angleOfSight);
于 2009-03-11T00:43:27.923 に答える
1

現在のロボットに対する各ロボットの相対的な角度と距離を計算します。角度が現在の方向のしきい値内にあり、最大ビュー範囲内にある場合は、それを見ることができます。

唯一難しいのは、角度が 2pi ラジアンから 0 になる境界のケースを処理することです。

于 2009-02-18T01:12:13.347 に答える
0

あなたの砲塔は本当にその広い発砲パターンを持っていますか?弾丸がたどる経路は直線であり、弾丸が移動しても大きくなることはありません。砲塔のキルゾーンを表す砲塔の方向に単純なベクトルが必要です。各戦車には、脆弱な領域を表す境界円があります。次に、レイトレーシングの場合と同じように進めることができます。単純な光線/円の交差。ドキュメント「2Dでの線形コンポーネントと円形コンポーネントの交差」のセクション3を参照してください。

于 2009-03-05T05:00:58.540 に答える
0

更新された問題は、との異なる「ゼロ」方向から発生しているようorientationですazimuth。0の場合orientationは「真っ直ぐ上」を意味するようですが、azimuth0の場合は「真っ直ぐ右」を意味します。

于 2009-03-12T02:31:56.967 に答える