2016-08-05 7 views
1

A *アルゴリズムを使用して、限られたハードウェア(CPU:Vortex86,256MB)上のポイントAからポイントBまでの良好なパスを見つけたいと考えています。私は固定された障害を持つ300x200のセルのグリッドを持っています。障害物を避けるためのヒットボックスはディスクです。サークルに関数を適用するためのトリックがありますか?

私はヒットボックスがA *で非常に頻繁に行われるように障害物と衝突しているかどうかをチェックする最適な方法を探しています。

最も明白な方法は次のようにディスクの全領域をチェックすることでした:

radiusは、ディスクおよびディスクの中央の center座標の半径である
bool check(std::function<bool(const Coordinates &)> collide) 
{ 
    const std::uint32_t RADIUS2 = radius * radius; 
    Coordinates cell(-radius, -radius); 

    for (; cell.x <= radius; cell.x++) 
    { 
     for (cell.y = -radius; cell.y <= radius; cell.y++) 
     { 
      if (cell.x * cell.x + cell.y * cell.y <= RADIUS2 && !collide(center + cell)) 
      { 
       return false; 
      } 
     } 
    } 

    return true; 
} 

もっと良い解決策は、ディスクの外周をチェックすることだけかもしれません。しかし、両方のソリューションは2 forのループを使用する必要があり、時間の大部分を占めるディスク領域には適合しません。

あなたはそれを賢明なやり方で解決する方法はありますか?

+4

マップを生成するときに障害物を膨らませることはできませんか?その後、衝突テストは単一ピクセルに減少します。 –

+0

どうやってそれをするのか分かりません。コーナーにあるディスクの四分の一のような障害物を想像してみましょう。どのようにあなたはそれを膨らませるのですか? – didil

+0

@didile障害物を膨らませるのは簡単です。障害物までの距離がR未満のすべてのセルを「インフレーション」とマークするだけです。一度だけ行うだけです。その後すぐに、このセルに入ることが許可されているかどうかをチェックします。 – Ilya

答えて

0

ネストされたループ内では、std::function::operator()を呼び出しています。これは間接的な呼び出しであり、抽象的な抽象的なペナルティはありません。今すぐ近代 CPUは、最初のいくつかの呼び出しの後にその分岐を正常に予測する分岐予測を持つでしょう。しかし、あなたの古いチップはすぐそこに苦しむでしょう。

だから、本当にこれを避ける必要があります。幸いにも、最初のコメントはすでに頭の爪に当たっています。障害物を回避するためのゾーンを計算することで、ヒットテストを効率的に事前計算することができます。

また、障害が移動しないと仮定すると、ヒットテストの結果を各セルにキャッシュすることができます。これは、最初に小さな部品しか必要としない大きなグリッドを使用している場合に特に効果的です。

+0

効果的に障害物、グリッド上の固定された障害物または移動するものを変更する方法として 'std :: function'を使いますソースまたはその両方。 – didil

関連する問題