2

だから私はゲームでの衝突検出に Box2D を使用しています。地形に関する情報を含むタイルマップがあります。今のところ、道路または草のいずれかを持つ単なる char[][] です。さて、各レベルの開始時に、さまざまな地形を表す四角形を作成したいと考えていましたが、これらの四角形を最適化したかったのですが、明らかにかなりのアルゴリズムが必要です。

私の最初のアプローチは、レベルの開始時にマップ内のすべてのタイルに対して個別の地形を作成することでした。FPS が 5 に低下しました。

私の 2 番目のアイデアは、プレイヤーがマップに沿って移動するときに地形用にさまざまな長方形を単純に作成し、見えなくなった長方形を削除することでした。それでも多くの長方形になりますが、かなり少なくなります。

2 番目の方法はまだ試していませんが、知りたいのですが、大きなタイルマップを使用して地形に対して衝突検出を効率的に実行する簡単な方法はありますか?

ありがとう。

4

1 に答える 1

4

タイルを組み合わせてみてください。たとえば、16 個のタイルに対して 16 個の長方形のコリジョン ボリュームがある場合...

* * * *
* * * *
* * * *
* * * *

これらのタイルを組み合わせて 1 つの大きな長方形にすることができます。

さて、タイルが変な配置になっていると、もっと難しくなります。おそらく、このように...

**---
****-
*--**
-*-*-

最近、四分木スイープとプルーンを使用して、ゲームでこの問題を解決しました。(スイープとプルーニングは厳密には必要ではなく、最適化です。)

クワッド ツリーは、正方形のタイルをより大きな長方形に分割し、クワッド ツリーが生成する長方形を繰り返し処理し、幅が同じ場合はそれらを結合します。次に、それらを再度繰り返し処理し、同様の高さで結合します。それらを結合できなくなるまで繰り返し、コリジョン ボリュームを生成します。

これは、より最適な削減について私が尋ねた質問へのリンクです。難しいように聞こえるので、おそらくこれを実装しませんが、現在のアプローチはうまく機能しています。

いくつかのコード:

do {
    lastCompressSize = currentOutput;
    this.runHorizontalCompression(this.output1, this.output2);
    this.output1.clear();
    this.runVerticalCompression(this.output2, this.output1);
    this.output2.clear();
    currentOutput = this.output1.size;
    iterations += 1;
}while (lastCompressSize > currentOutput);

public void runHorizontalCompression(Array<SimpleRect> input,
        Array<SimpleRect> output) {
    input.sort(this.xAxisSort);
    int x2 = -1;
    final SimpleRect newRect = this.rectCache.retreive();
    for (int i = 0; i < input.size; i++) {
        SimpleRect r1 = input.get(i);
        newRect.set(r1);
        x2 = newRect.x + newRect.width;
        for (int j = i + 1; j < input.size; j++) {
            SimpleRect r2 = input.get(j);
            if (x2 == r2.x && r2.y == newRect.y
                    && r2.height == newRect.height) {
                newRect.width += r2.width;
                x2 = newRect.x + newRect.width;
                input.removeIndex(j);
                j -= 1;
            } else if (x2 < r2.x)
                break;
        }
        SimpleRect temp = this.rectCache.retreive().set(newRect);
        output.add(temp);
    }
}

public void runVerticalCompression(Array<SimpleRect> input,
        Array<SimpleRect> output) {
    input.sort(this.yAxisSort);
    int y2 = -1;
    final SimpleRect newRect = this.rectCache.retreive();
    for (int i = 0; i < input.size; i++) {
        SimpleRect r1 = input.get(i);
        newRect.set(r1);
        y2 = newRect.y + newRect.height;
        for (int j = i + 1; j < input.size; j++) {
            SimpleRect r2 = input.get(j);
            if (y2 == r2.y && r2.x == newRect.x
                    && r2.width == newRect.width) {
                newRect.height += r2.height;
                y2 = newRect.y + newRect.height;
                input.removeIndex(j);
                j -= 1;
            } else if (y2 < r2.y)
                break;
        }
        SimpleRect temp = this.rectCache.retreive().set(newRect);
        output.add(temp);
    }
}
于 2013-07-25T02:14:35.747 に答える