LibGdx PolygonSpriteBatch 未绘制所有多边形
LibGdx PolygonSpriteBatch not drawing all polygons
我正在尝试使用 libGdx 中的 PolygonSpriteBatch 渲染一个简单的 2D 景观轮廓,以在屏幕上绘制填充的多边形。我不知道为什么,但代码似乎只渲染了所有其他多边形,导致屏幕上出现条纹图案(请参见下面的屏幕截图 - 背景为红色,风景为绿色)。
我用来绘制风景的代码如下所示。这会遍历世界坐标中的一组相邻点(使用 landarray.getOnScreen() 检索),计算屏幕坐标,为每个线段创建一个 PolygonRegion 并绘制它们。我使用的纹理只是一个 100x100 像素的纯白色正方形。我没有使用任何相机或视图,只是将世界坐标即时转换为屏幕坐标并直接绘制到图形屏幕上。
请注意,我正在从一个使用 Slick2D 的工作版本重写这个游戏(因此在这个阶段不使用相机)并且下面的代码或多或少没有改变(除了翻转 y 轴高度计算)来自工作版本,它绘制了一个连续的风景。
public void drawPoly() {
System.out.println("Mountains - drawShape()");
// Calculate screen bottom-edge Y taking into account values = bHEIGHT
int scrBtmY = scrTopY - Gdx.graphics.getHeight();
if (FastMath.abs(scrBtmY) == bHEIGHT) { // Wrap-around bug at y == bHEIGHT
scrBtmY = 0;
}
// Draw the land masses on-screen that are in the results list
polyBatch.begin();
polyBatch.setColor(landColour);
ArrayList<Landmass> masses = landarray.getOnScreen(scrLeftX, scrTopY, scrBtmY);
for (Landmass lm : masses) {
/* Calculate the on-screen start and end x and y values taking into account
wrapping in 'buffer space'
Wrap around - low negative numbers (> -25) are 'just off screen' start or
end points, large ones are wrap-around points
*/
int sx = (int) lm.start.x - scrLeftX;
if (sx < -Settings.Physics.LANDSITEWIDTH) {
sx = sx + bWIDTH;
}
int sy = (int) lm.start.y - scrBtmY;
int ex = (int) lm.end.x - scrLeftX;
if (ex < -Settings.Physics.LANDSITEWIDTH) { // Wrap around
ex = ex + bWIDTH;
}
int ey = (int) lm.end.y - scrBtmY;
ex = ex - 1; // In case over-lapping regions is causing stripes
System.out.format("start (%d, %d)\t end (%d, %d)%n", sx, sy, ex, ey);
// Construct and draw the polygon
float[] vertices = new float[8];
vertices[0] = sx;
vertices[1] = 0;
vertices[2] = ex;
vertices[3] = 0;
vertices[4] = ex;
vertices[5] = ey;
vertices[6] = sx;
vertices[7] = sy;
short[] triangles = new short[] {0, 1, 2, 0, 2, 3};
PolygonRegion polyReg = new PolygonRegion(new TextureRegion(textureSolid), vertices, triangles);
polyBatch.draw(polyReg, sx, 0);
}
polyBatch.end();
}
我已经包含了一条调试线来打印出各个多边形(陆地段)的屏幕坐标,一次 drawPoly() 迭代的输出如下所示。这显示了应该在屏幕上绘制的每个段的开始 (x, y) 和结束 (x, y) 坐标。从输出来看,绘制的多边形看起来彼此相邻,因此它们之间不应有间隙。
Mountains - drawShape()
start (53, 265) end (77, 358)
start (78, 358) end (102, 376)
start (103, 376) end (127, 406)
start (128, 406) end (152, 371)
start (153, 371) end (177, 429)
start (178, 429) end (202, 447)
start (203, 447) end (227, 433)
start (228, 433) end (252, 415)
start (253, 415) end (277, 478)
start (278, 478) end (302, 490)
start (303, 490) end (327, 524)
start (328, 524) end (352, 519)
start (353, 519) end (377, 551)
start (378, 551) end (402, 556)
start (403, 556) end (427, 543)
start (428, 543) end (452, 470)
start (453, 470) end (477, 505)
start (478, 505) end (502, 482)
start (503, 482) end (527, 513)
start (528, 513) end (552, 476)
start (553, 476) end (577, 479)
start (578, 479) end (602, 460)
start (603, 460) end (627, 475)
start (628, 475) end (652, 426)
start (653, 426) end (677, 453)
start (-22, 449) end (2, 406)
start (3, 406) end (27, 357)
start (28, 357) end (52, 265)
我在这个网站上搜索了一系列 post,它们帮助我获得了上面的代码,但没有看到任何 post 有这个特定问题。
请注意,我 运行 这只是桌面版本,并为此启用了 Java 8。使用 libGdx 1.5.6 和 1.6.0 进行测试,结果相同。
我已经制作了一个独立版本的代码来复制这个问题,以防有人想在家里尝试这个。这使用 libGdx 1.6.0 和(我假设)Java 6 并显示上述问题(至少在我的电脑上)。可以在此处找到这些文件:java source, png image and whole project 压缩文件。
有谁知道为什么我在屏幕上出现条纹效果?
PolygonRegion 顶点坐标应该是相对于多边形的 TextureRegion 原点的偏移量,而不应该是绝对屏幕坐标,这就是我 认为 你正在做的输出(因为您正在使用未修改的坐标创建顶点)。
我建议你把你的顶点坐标修改成长度。
我遇到了完全相同的问题,这是 Google 上的唯一结果。我想我会分享我的解决方案。
编辑:
为了清楚起见,这是我自己的解决方案。
vertices = new float[] { 0, 0,
lTX-lBX, lTY-lBY,
rTX-lBX, rTY-lBY,
rBX-lBX, rBY-lBY};
撇开我糟糕的命名方案不谈,上面根据 UV 坐标定义了一个四边形多边形。 lBX(左基 x)和 lBY(左基 y)是我的多边形在屏幕坐标中的起始位置。它们直接位于 TextureRegion 的原点,因此偏移 0,0。 lTX(左上x)和lTY(左上y)是下一个位置。同样,我通过从 lBX 和 lBY 中减去两者来找到距原点的距离。我的其余坐标依此类推。
正如所承诺的,这是我使用 PolygonSpriteBatch 的工作测试程序:
/* PolygonSpriteBatch test using libgdx
Author: Twelve1110
Date: 6 June 2015
*/
package test;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.PolygonRegion;
import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
import java.util.ArrayList;
public class TestPolygonSpriteBatch extends ApplicationAdapter {
PolygonSpriteBatch polyBatch;
SpriteBatch batch;
Texture img;
ArrayList<Landmass> masses;
TextureRegion texRegion;
@Override
public void create() {
Gdx.graphics.setDisplayMode(600, 480, false);
polyBatch = new PolygonSpriteBatch();
masses = this.buildLandmass();
img = new Texture(Gdx.files.internal("land.png")); // 100 by 100 pixel plain white jpg
texRegion = new TextureRegion(img); // Create new texture region with base image
}
@Override
public void render() {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// Calculate screen left-edge X and bottom-edge Y (normally done in a game with moving screen)
int scrBtmY = 0;
int scrLeftX = 0;
// Draw the landscape on-screen
polyBatch.begin();
polyBatch.setColor(Color.GREEN);
for (Landmass lm : masses) {
// Calculate start and end x and y values taking into account wrapping in 'buffer space'
int sx = (int) lm.start.x - scrLeftX;
int sy = (int) lm.start.y - scrBtmY;
int ex = (int) lm.end.x - scrLeftX;
int ey = (int) lm.end.y - scrBtmY;
// Create polygon vertices
float[] vertices = new float[8]; // Create polygon with bottom-left corner = (0, 0)
vertices[0] = 0; // Bottom-left
vertices[1] = 0;
vertices[2] = (ex - sx) + 1; // Bottom-right; all points are lengths away from (0, 0);
vertices[3] = 0;
vertices[4] = (ex - sx) + 1; // Top-right
vertices[5] = ey;
vertices[6] = 0; // Top-left
vertices[7] = sy;
// Define how to divide polygon into trianlges, create region and draw...
short[] triangles = new short[]{0, 1, 2, 0, 2, 3}; // Define points of polygons to be used in triangles (could be done in 'create' method
PolygonRegion polyReg = new PolygonRegion(texRegion, vertices, triangles);
polyBatch.draw(polyReg, sx, 0); // Pass screen co-ordinates here to draw PolygonRegion in correct place on screen
}
polyBatch.end();
}
public ArrayList<Landmass> buildLandmass() {
ArrayList<Landmass> list = new ArrayList();
int[] coordinates = new int[]{ // Set of polygons to be drawn in screen co-ordinates
-22, 449, 2, 406, 3, 406, 27, 357,
28, 357, 52, 265, 53, 265, 77, 358,
78, 358, 102, 376, 103, 376, 127, 406,
128, 406, 152, 371, 153, 371, 177, 429,
178, 429, 202, 447, 203, 447, 227, 433,
228, 433, 252, 415, 253, 415, 277, 478,
278, 478, 302, 490, 303, 490, 327, 524,
328, 524, 352, 519, 353, 519, 377, 551,
378, 551, 402, 556, 403, 556, 427, 543,
428, 543, 452, 470, 453, 470, 477, 505,
478, 505, 502, 482, 503, 482, 527, 513,
528, 513, 552, 476, 553, 476, 577, 479,
578, 479, 602, 460, 603, 460, 627, 475,
628, 475, 652, 426, 653, 426, 677, 453};
for (int i = 0; i < 28; i++) { // Create landmass array of polygons
Landmass lm = new Landmass();
int pt = i * 4;
lm.start.x = coordinates[pt];
lm.start.y = coordinates[pt + 1];
lm.end.x = coordinates[pt + 2];
lm.end.y = coordinates[pt + 3];
list.add(lm);
}
return list;
}
public class Landmass {
public Vector2 start;
public Vector2 end;
Landmass() {
start = new Vector2();
end = new Vector2();
}
}
}
我正在尝试使用 libGdx 中的 PolygonSpriteBatch 渲染一个简单的 2D 景观轮廓,以在屏幕上绘制填充的多边形。我不知道为什么,但代码似乎只渲染了所有其他多边形,导致屏幕上出现条纹图案(请参见下面的屏幕截图 - 背景为红色,风景为绿色)。
我用来绘制风景的代码如下所示。这会遍历世界坐标中的一组相邻点(使用 landarray.getOnScreen() 检索),计算屏幕坐标,为每个线段创建一个 PolygonRegion 并绘制它们。我使用的纹理只是一个 100x100 像素的纯白色正方形。我没有使用任何相机或视图,只是将世界坐标即时转换为屏幕坐标并直接绘制到图形屏幕上。
请注意,我正在从一个使用 Slick2D 的工作版本重写这个游戏(因此在这个阶段不使用相机)并且下面的代码或多或少没有改变(除了翻转 y 轴高度计算)来自工作版本,它绘制了一个连续的风景。
public void drawPoly() {
System.out.println("Mountains - drawShape()");
// Calculate screen bottom-edge Y taking into account values = bHEIGHT
int scrBtmY = scrTopY - Gdx.graphics.getHeight();
if (FastMath.abs(scrBtmY) == bHEIGHT) { // Wrap-around bug at y == bHEIGHT
scrBtmY = 0;
}
// Draw the land masses on-screen that are in the results list
polyBatch.begin();
polyBatch.setColor(landColour);
ArrayList<Landmass> masses = landarray.getOnScreen(scrLeftX, scrTopY, scrBtmY);
for (Landmass lm : masses) {
/* Calculate the on-screen start and end x and y values taking into account
wrapping in 'buffer space'
Wrap around - low negative numbers (> -25) are 'just off screen' start or
end points, large ones are wrap-around points
*/
int sx = (int) lm.start.x - scrLeftX;
if (sx < -Settings.Physics.LANDSITEWIDTH) {
sx = sx + bWIDTH;
}
int sy = (int) lm.start.y - scrBtmY;
int ex = (int) lm.end.x - scrLeftX;
if (ex < -Settings.Physics.LANDSITEWIDTH) { // Wrap around
ex = ex + bWIDTH;
}
int ey = (int) lm.end.y - scrBtmY;
ex = ex - 1; // In case over-lapping regions is causing stripes
System.out.format("start (%d, %d)\t end (%d, %d)%n", sx, sy, ex, ey);
// Construct and draw the polygon
float[] vertices = new float[8];
vertices[0] = sx;
vertices[1] = 0;
vertices[2] = ex;
vertices[3] = 0;
vertices[4] = ex;
vertices[5] = ey;
vertices[6] = sx;
vertices[7] = sy;
short[] triangles = new short[] {0, 1, 2, 0, 2, 3};
PolygonRegion polyReg = new PolygonRegion(new TextureRegion(textureSolid), vertices, triangles);
polyBatch.draw(polyReg, sx, 0);
}
polyBatch.end();
}
我已经包含了一条调试线来打印出各个多边形(陆地段)的屏幕坐标,一次 drawPoly() 迭代的输出如下所示。这显示了应该在屏幕上绘制的每个段的开始 (x, y) 和结束 (x, y) 坐标。从输出来看,绘制的多边形看起来彼此相邻,因此它们之间不应有间隙。
Mountains - drawShape()
start (53, 265) end (77, 358)
start (78, 358) end (102, 376)
start (103, 376) end (127, 406)
start (128, 406) end (152, 371)
start (153, 371) end (177, 429)
start (178, 429) end (202, 447)
start (203, 447) end (227, 433)
start (228, 433) end (252, 415)
start (253, 415) end (277, 478)
start (278, 478) end (302, 490)
start (303, 490) end (327, 524)
start (328, 524) end (352, 519)
start (353, 519) end (377, 551)
start (378, 551) end (402, 556)
start (403, 556) end (427, 543)
start (428, 543) end (452, 470)
start (453, 470) end (477, 505)
start (478, 505) end (502, 482)
start (503, 482) end (527, 513)
start (528, 513) end (552, 476)
start (553, 476) end (577, 479)
start (578, 479) end (602, 460)
start (603, 460) end (627, 475)
start (628, 475) end (652, 426)
start (653, 426) end (677, 453)
start (-22, 449) end (2, 406)
start (3, 406) end (27, 357)
start (28, 357) end (52, 265)
我在这个网站上搜索了一系列 post,它们帮助我获得了上面的代码,但没有看到任何 post 有这个特定问题。
请注意,我 运行 这只是桌面版本,并为此启用了 Java 8。使用 libGdx 1.5.6 和 1.6.0 进行测试,结果相同。
我已经制作了一个独立版本的代码来复制这个问题,以防有人想在家里尝试这个。这使用 libGdx 1.6.0 和(我假设)Java 6 并显示上述问题(至少在我的电脑上)。可以在此处找到这些文件:java source, png image and whole project 压缩文件。
有谁知道为什么我在屏幕上出现条纹效果?
PolygonRegion 顶点坐标应该是相对于多边形的 TextureRegion 原点的偏移量,而不应该是绝对屏幕坐标,这就是我 认为 你正在做的输出(因为您正在使用未修改的坐标创建顶点)。
我建议你把你的顶点坐标修改成长度。
我遇到了完全相同的问题,这是 Google 上的唯一结果。我想我会分享我的解决方案。
编辑:
为了清楚起见,这是我自己的解决方案。
vertices = new float[] { 0, 0,
lTX-lBX, lTY-lBY,
rTX-lBX, rTY-lBY,
rBX-lBX, rBY-lBY};
撇开我糟糕的命名方案不谈,上面根据 UV 坐标定义了一个四边形多边形。 lBX(左基 x)和 lBY(左基 y)是我的多边形在屏幕坐标中的起始位置。它们直接位于 TextureRegion 的原点,因此偏移 0,0。 lTX(左上x)和lTY(左上y)是下一个位置。同样,我通过从 lBX 和 lBY 中减去两者来找到距原点的距离。我的其余坐标依此类推。
正如所承诺的,这是我使用 PolygonSpriteBatch 的工作测试程序:
/* PolygonSpriteBatch test using libgdx
Author: Twelve1110
Date: 6 June 2015
*/
package test;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.PolygonRegion;
import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
import java.util.ArrayList;
public class TestPolygonSpriteBatch extends ApplicationAdapter {
PolygonSpriteBatch polyBatch;
SpriteBatch batch;
Texture img;
ArrayList<Landmass> masses;
TextureRegion texRegion;
@Override
public void create() {
Gdx.graphics.setDisplayMode(600, 480, false);
polyBatch = new PolygonSpriteBatch();
masses = this.buildLandmass();
img = new Texture(Gdx.files.internal("land.png")); // 100 by 100 pixel plain white jpg
texRegion = new TextureRegion(img); // Create new texture region with base image
}
@Override
public void render() {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// Calculate screen left-edge X and bottom-edge Y (normally done in a game with moving screen)
int scrBtmY = 0;
int scrLeftX = 0;
// Draw the landscape on-screen
polyBatch.begin();
polyBatch.setColor(Color.GREEN);
for (Landmass lm : masses) {
// Calculate start and end x and y values taking into account wrapping in 'buffer space'
int sx = (int) lm.start.x - scrLeftX;
int sy = (int) lm.start.y - scrBtmY;
int ex = (int) lm.end.x - scrLeftX;
int ey = (int) lm.end.y - scrBtmY;
// Create polygon vertices
float[] vertices = new float[8]; // Create polygon with bottom-left corner = (0, 0)
vertices[0] = 0; // Bottom-left
vertices[1] = 0;
vertices[2] = (ex - sx) + 1; // Bottom-right; all points are lengths away from (0, 0);
vertices[3] = 0;
vertices[4] = (ex - sx) + 1; // Top-right
vertices[5] = ey;
vertices[6] = 0; // Top-left
vertices[7] = sy;
// Define how to divide polygon into trianlges, create region and draw...
short[] triangles = new short[]{0, 1, 2, 0, 2, 3}; // Define points of polygons to be used in triangles (could be done in 'create' method
PolygonRegion polyReg = new PolygonRegion(texRegion, vertices, triangles);
polyBatch.draw(polyReg, sx, 0); // Pass screen co-ordinates here to draw PolygonRegion in correct place on screen
}
polyBatch.end();
}
public ArrayList<Landmass> buildLandmass() {
ArrayList<Landmass> list = new ArrayList();
int[] coordinates = new int[]{ // Set of polygons to be drawn in screen co-ordinates
-22, 449, 2, 406, 3, 406, 27, 357,
28, 357, 52, 265, 53, 265, 77, 358,
78, 358, 102, 376, 103, 376, 127, 406,
128, 406, 152, 371, 153, 371, 177, 429,
178, 429, 202, 447, 203, 447, 227, 433,
228, 433, 252, 415, 253, 415, 277, 478,
278, 478, 302, 490, 303, 490, 327, 524,
328, 524, 352, 519, 353, 519, 377, 551,
378, 551, 402, 556, 403, 556, 427, 543,
428, 543, 452, 470, 453, 470, 477, 505,
478, 505, 502, 482, 503, 482, 527, 513,
528, 513, 552, 476, 553, 476, 577, 479,
578, 479, 602, 460, 603, 460, 627, 475,
628, 475, 652, 426, 653, 426, 677, 453};
for (int i = 0; i < 28; i++) { // Create landmass array of polygons
Landmass lm = new Landmass();
int pt = i * 4;
lm.start.x = coordinates[pt];
lm.start.y = coordinates[pt + 1];
lm.end.x = coordinates[pt + 2];
lm.end.y = coordinates[pt + 3];
list.add(lm);
}
return list;
}
public class Landmass {
public Vector2 start;
public Vector2 end;
Landmass() {
start = new Vector2();
end = new Vector2();
}
}
}