1

私はテキスト ベース (コンソール) の WW2 戦略ゲームに取り組んでおり、2D 正方形グリッド マップ上に設定されています。マップ上のあるタイルから別のタイルへの視線を計算する方法が必要です。このJava の例を使用してコードを作成しました。これが私が書いたものです。

public function plotLine($x0, $y0, $x1, $y1, $size)
{   
    $arr = $this->getEmptyMap($size);
    $xDist = abs($x1 - $x0);
    $yDist = -abs($y1 - $y0);
    if($x0 < $x1) {
        $xStep = 1;
    } else {
        $xStep = -1;
    }

    if($y0 < $y1) {
        $yStep = 1;
    } else {
        $yStep = -1;
    }

    $plotError = $xDist + $yDist;

    $arr[$x0][$y0] = 1;

    while($x0 != $x1 || $y0 != $y1) {
        // if(2 * $plotError > $yDist) {
        //  // Horizontal step
        //  $plotError += $yDist;
        //  $x0 += $xStep;
        // }

        // if(2 * $plotError < $xDist) {
        //  // Vertical step
        //  $plotError += $xDist;
        //  $y0 += $yStep;
        // }

        if(2 * $plotError - $yDist > $xDist - 2 * $plotError) {
            // Horizontal step
            $plotError += $yDist;
            $x0 += $xStep;
        } else {
            // Vertical step
            $plotError += $xDist;
            $y0 += $yStep;
        }           


        $arr[$x0][$y0] = 1;
    }

    $this->line = $arr;
}

注: getEmptyMap は、多次元配列を 0 で埋めるだけです。

入力として (0, 0, 4, 4, 4) を使用したテスト結果:

1100
0110
0011
0001

私は行をマッピングする方法を試しました: 1 つは Franz D. が使用した通常の実装 (現在、上記の例ではコメントアウトされています)、もう 1 つは Franz D. が示した変更された実装です。どちらも私が探している結果を私に与えていません。「アンチエイリアシング」の一種。はんだが 0,0 から 2,2 を見て、1,2 と 2,1 に建物がある場合、2,2 にあるものはすべて見えないようにする必要があります。コメントアウトされた実装は建物を完全に無視し、変更は 2,1 に「ヒット」しますが、1,2 にはヒットしません。線の下と線の上の両方に「ヒット」するようにコードを調整するにはどうすればよいですか?

4

1 に答える 1

1

あなたが直面している「問題」は、正確な対角線を見るときの特別なエッジケースが原因で発生します。これを処理するには、2 つの (単純な) 方法しかありません。

1) 対角線は、水平および垂直タイルを同時にインクリメントします。あなたのゲームでは、これは、基本的な方向がブロックされていても、ユニットが対角線を見ることができることを意味します.

2) 水平タイルまたは垂直タイルを優先するか、2 つのうちの 1 つだけをインクリメントするかを選択します。これは Franz D. のアルゴリズムで、最終的にあなたが書いて投稿に入れました。ここで、ifステートメントは対角線に対して true です。つまり、結果は次のようになります。

1100
0110
0011
0001

垂直を優先する場合は、次のように変更できます。

...
        if(2 * $plotError - $yDist < $xDist - 2 * $plotError) {
            // Vertical step
            $plotError += $xDist;
            $y0 += $yStep; 
        } else {
          // Horizontal step
            $plotError += $yDist;
            $x0 += $xStep;
        }  

...

if/else の両方の本体が交換され、状態>が変更さ<れたことに注意してください。

これで、結果は次のようになります。

1000
1100
0110
0011

隣接する枢機卿のいずれかをブロックするものが何もない場合にユニットが対角線だけを見ることができるようにしたい場合、最も簡単な解決策は、アルゴリズムの上記の両方のバリアントを使用し、それらの結果を 1 つのタイルの配列に結合することです。 .

最後の注意:座標のみに関心があり、その値には関心がない場合(説明したユースケースの場合のように)、抽出された(x, y)座標の単純な配列を代わりに使用する方が(メモリ)効率的かもしれません。結果(x, y)1.

ゲームで頑張ってください!

于 2016-11-21T18:50:46.133 に答える