グリッド上のタイル全体の範囲トレース


8

私は現在グリッド上でA *パ​​スファインディングに取り組んでおり、生成されたパスをスムーズにすると同時に、それに沿って移動するキャラクターの範囲も考慮しています。私はパスファインディングにグリッドを使用していますが、キャラクターの動きは自由なローミングであり、厳密なタイル間の動きではありません。

よりスムーズで効率的なパスを実現するために、グリッド上でライントレースを実行して、タイル間に歩行不可能なタイルがあるかどうかを判断し、不要なコーナーを削っています。

ただし、ライントレースは範囲がゼロであるため、キャラクターの範囲を考慮せず、悪い結果をもたらします(ラインが見逃した歩行不可能なタイルを返さず、不要な衝突を引き起こしません)。

したがって、私が探しているのは、その下のタイルを決定するラインアルゴリズムではなく、タイル全体のエクステントラインの下のタイルを決定するアルゴリズムです。これは私の問題を視覚化するのに役立つ画像です!

これは私の問題を視覚化するのに役立つ画像です

誰かが何かアイデアを持っていますか?私はブレゼンハムのラインや他の代替品を使って作業してきましたが、この特定の問題を解決する方法はまだわかりません。


半分のタイル幅で2つのBesenhamのラインを使用します。
ジョナサンコネル

回答:


1

「タイル」のすべてのコーナーから、行きたいタイルのすべてのコーナーに線を引くとどうでしょう。これを4行ではなく3行に最適化することもできます。これはパス上のすべてのタイルを正しく検出しませんか?

よりスムーズなパスについては、「ステアリング動作」に関する記事、特にA *と組み合わせた次のリンクなどを確認してください。


0

数日前に私のゲームにこのアルゴリズムを実装しました!(-8

これが画像形式の私のアイデアです。

ここに画像の説明を入力してください

アルゴリズムは任意のサイズの長方形で機能することに注意してください。これは、長方形の1つのコーナーが常に最初にグリッドラインと衝突するという事実に基づいています。つまり、追跡できる光線は1つだけであり、必要なすべての交差を取得できます。

アルゴリズムの手順は次のとおりです。

  1. 長方形の「前方」コーナーを選択します。たとえば、図ではトレース方向が右上の象限にあるため、右上隅を選択します。
  2. このコーナーから目的地まで(幅がゼロの)光線をトレースします。レイとグリッドラインのすべての交差を反復処理する必要があります。
  3. レイとグリッドラインのすべての交点について、交点に長方形を配置します。その側面はグリッド線に正確に沿っており、いくつかのグリッドセルに接しています。これらは、この時点で長方形が衝突するタイルです!

光線が正確に垂直/水平である場合や、光線がコーナーに正確に当たる場合など、ここにはいくつかのエッジケースがありますが、難しくありません。


0

この手順は、元の質問を解決するブレゼンハムの改作です。

グリッド上でタイルサイズの線をトレース

final int cols = 64;
final int rows = 64;
color tiles = new color[cols*rows];

void squaretrace(int x1, int y1, int x2, int y2, color c) {
  if (x1==x2 && y1==y2) {
    tiles[x1+y1*cols] += c;
  } else {
    // make sure y1 is less or equal to y2
    if (y2 < y1) {
      int t = x1;
      x1 = x2;
      x2 = t;
      t = y1;
      y1 = y2;
      y2 = t;
    }
    // along y-axis
    if (x1==x2) {
      for(int y = y1; y <= y2; y++){
        tiles[x1 + y * cols] += c;
      }
    }
    // along x-axis
    else if (y1==y2) {
      int xLo, xHi;
      if(x1 < x2){
        xLo = x1;
        xHi = x2;
      }
      else{
        xLo = x2;
        xHi = x1;
      }
      for(int x = xLo; x <= xHi; x++){
        tiles[x + y1 * cols] += c;
      }
    }
    // northeast
    else if (x1 < x2) { 
      // NW and SE corner
      int dx = x2 - x1;
      int dy = y2 - y1;
      int m = 8;
      int k = (1<<m) * dx / dy;

      int minx = x1 << m;
      int maxx = (x1+1) << m;

      for (int y = y1; y <= y2; y++) {
        int xLo = minx >> m;
        if (y!=y1) minx += k;
        if (y<y2) maxx += k;
        int xHi = (maxx-1) >> m;
        for (int x = xLo; x <= xHi; x++) {
          tiles[x+y*cols] += c;
        }
        tiles[xLo+y*cols] += c;
        tiles[xHi+y*cols] += c;
      }
    }
    // northwest
    else {
      // NW and SE corner
      int dx = x2 - x1;
      int dy = y2 - y1;
      int m = 8;
      int k = (1<<m) * dx / dy;

      int minx = x1 << m;
      int maxx = (x1+1) << m;

      for (int y = y1; y <= y2; y++) {

        if (y<y2) minx += k;
        int xLo = minx >> m;
        int xHi = (maxx-1) >> m;
        if (y!=y1) maxx += k;

        for (int x = xLo; x <= xHi; x++) {
          tiles[x+y*cols] += c;
        }
        tiles[xLo+y*cols] += c;
        tiles[xHi+y*cols] += c;
      }
    }
  }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.