タイルを組み合わせてみてください。たとえば、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);
}
}