解決:
public static boolean[][] laserField = new boolean[(int) Static.WORLD_SIZE][(int)Static.WORLD_SIZE];
public static List<LaserData> laserData = new ArrayList<LaserData>();
public static void calcLaserBoundryAreas() {
laserField = new boolean[(int) Level.levelBounds.bounds.width+5][(int) Level.levelBounds.bounds.height+5];
for (int i=0;i<laserField.length;i++) {
for (int j=0;j<laserField[i].length;j++) {
if(i==0 || i==laserField.length-1 || j==0 || j==laserField[i].length-1)
laserField[i][j] = true;
else
laserField[i][j] = false;
}
}
for (LaserBlock lBlock : lBlocks) {
int cols = (int)lBlock.bounds.width;
int rows = (int)lBlock.bounds.height;
float startX = lBlock.position.x - (cols-1f)/2f;
float startY = lBlock.position.y - (rows-1f)/2f;
for (int i=0;i<cols;i++) {
for (int j=0;j<rows;j++) {
addLaserCell(startX+i, startY+j);
}
}
}
addLaserData();
}
private static void addLaserCell(float x, float y) {
int cellX = (int)(x- Level.levelBounds.bounds.lowerLeft.x+2);
int cellY = (int)(y- Level.levelBounds.bounds.lowerLeft.y+2);
if (cellX < 0 || cellX > laserField.length-1) return;
if (cellY < 0 || cellY > laserField[cellX].length-1) return;
laserField[cellX][cellY] = true;
}
private static void addLaserData() {
laserData = new ArrayList<LaserData>();
for (int i=1;i<laserField.length-1;i++) {
for (int j=1;j<laserField[i].length-1;j++) {
if (!laserField[i][j]) {
checkNeighbours(i,j);
}
}
}
optimiseLaserData();
}
private static void checkNeighbours(int x, int y) {
boolean u = laserField[x][y+1];
boolean ul = laserField[x-1][y+1];
boolean l = laserField[x-1][y];
boolean bl = laserField[x-1][y-1];
boolean b = laserField[x][y-1];
boolean br = laserField[x+1][y-1];
boolean r = laserField[x+1][y];
boolean ur = laserField[x+1][y+1];
/*
* TOP LEFT CORNER
*/
float posX, posY;
posX = Level.levelBounds.bounds.lowerLeft.x+x-2.5f;
posY = Level.levelBounds.bounds.lowerLeft.y+y-1.5f;
if(u && ul && l)
laserData.add(new LaserData(posX, posY, true, 0, 0));
else if(!u && ul && l)
laserData.add(new LaserData(posX, posY, false, 1, 0));
else if(!u && ul && !l)
laserData.add(new LaserData(posX, posY, true, 0, 2));
/*
* BOTTOM LEFT CORNER
*/
posX = Level.levelBounds.bounds.lowerLeft.x+x-2.5f;
posY = Level.levelBounds.bounds.lowerLeft.y+y-2.5f;
if(l && bl && b)
laserData.add(new LaserData(posX, posY, true, 0, 1));
else if(!l && bl && b)
laserData.add(new LaserData(posX, posY, false, 1, 1));
else if(!l && bl && !b)
laserData.add(new LaserData(posX, posY, true, 0, 3));
/*
* BOTTOM RIGHT CORNER
*/
posX = Level.levelBounds.bounds.lowerLeft.x+x-1.5f;
posY = Level.levelBounds.bounds.lowerLeft.y+y-2.5f;
if(b && br && r)
laserData.add(new LaserData(posX, posY, true, 0, 2));
else if(!b && br && r)
laserData.add(new LaserData(posX, posY, false, 1, 2));
else if(!b && br && !r)
laserData.add(new LaserData(posX, posY, true, 0, 0));
/*
* TOP RIGHT CORNER
*/
posX = Level.levelBounds.bounds.lowerLeft.x+x-1.5f;
posY = Level.levelBounds.bounds.lowerLeft.y+y-1.5f;
if(r && ur && u)
laserData.add(new LaserData(posX, posY, true, 0, 3));
else if(!r && ur && u)
laserData.add(new LaserData(posX, posY, false, 1, 3));
else if(!r && ur && !u)
laserData.add(new LaserData(posX, posY, true, 0, 1));
}
private static void optimiseLaserData() {
List<LaserData> optiLaserData = new ArrayList<LaserData>();
for(LaserData ld : laserData) {
if(ld.cornerPiece)
optiLaserData.add(ld);
else if(ld.dir == 0 || ld.dir == 2){
float x = ld.x;
float bottomY = ld.y;
float topY = ld.y;
float count = 1;
while (searchStraightLaserData(laserData, x, topY+1, ld.dir)) {
count++;
topY++;
}
while (searchStraightLaserData(laserData, x, bottomY-1, ld.dir)) {
count++;
bottomY--;
}
float centerY = bottomY + (topY-bottomY)/2;
if(!searchStraightLaserData(optiLaserData, x, centerY, ld.dir))
optiLaserData.add(new LaserData(x, centerY, false, count, ld.dir));
} else {
float y = ld.y;
float leftX = ld.x;
float rightX = ld.x;
float count = 1;
while (searchStraightLaserData(laserData, rightX+1, y, ld.dir)) {
count++;
rightX++;
}
while (searchStraightLaserData(laserData, leftX-1, y, ld.dir)) {
count++;
leftX--;
}
float centerX = leftX + (rightX-leftX)/2;
if(!searchStraightLaserData(optiLaserData, centerX, y, ld.dir))
optiLaserData.add(new LaserData(centerX, y, false, count, ld.dir));
}
}
laserData = optiLaserData;
}
private static boolean searchStraightLaserData(List<LaserData> data, float x, float y, int dir) {
for(LaserData ld : data)
if(ld.x == x && ld.y == y && ld.dir == dir && !ld.cornerPiece)
return true;
return false;
}
これらのメソッドは、最初にレベル エッジ境界のサイズであるブール グリッドを作成し、両側に 1 平方の余分なエッジを作成します。これは、安全な領域を表すために false に初期化され、余分なエッジは true に設定されているため、一種の中空ボックスができます。追加のエッジは、laserField の不適切なインデックスをチェックする必要をなくすことで、後で役立ちます。
レベルの範囲がグリッドにマップされた後、個々のセルは、レーザー ブロックで覆われている場所で true に変更されます。
ブール グリッドが完全にマッピングされると、各グリッド セルを反復処理し、偽のセルが見つかると、グリッド座標を次のメソッドに渡します。次のメソッドは、12 の異なる隣接パターンを調べて、このセルの周りにレーザーをレンダリングする必要があるかどうかを判断します。 . LaserData コンストラクターは次の引数を取ります (float x、float y、boolean cornerPiece、float length、int 方向)
最後のセクションでは、ブルート フォース検索を実行して、余分なスプライトのレンダリングを節約するために、隣接する直線部分を 1 つの長い直線部分に置き換えることができるかどうかを確認します。
その後、レンダラーは各フレームの laserData リストを読み取るだけで、正しいテクスチャ、その位置、長さなどをレンダリングするために必要なすべての情報を取得できます...
注: レベル境界の幅と高さは、境界外のプレイヤーの幅を考慮して、実際のプレイ エリアよりも 3 単位小さくなっています。それが levelBounds.lowerleft+5、+2、+ 1.5f などの由来です。少しハッキーなのはわかっていますが、古いコードであり、あえて触れませんxD