我正在尝试渲染一个平铺 map ,每次游戏运行时都会生成随机图 block 。
我有一个数组,应该保存图 block 的所有值,然后随机更改:
int[][] map = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
};
for (int x = 0; x < map.length; x++) {
for (int y = 0; y < map[x].length; y++) {
if(map[x][y] == 0){
switch(MathUtils.random(2)){
case 0:
map[x][y] = 0;
break;
case 1:
map[x][y] = 1;
break;
case 2:
map[x][y] = 2;
break;
}
}
}
}
然后我根据图 block 的内容渲染它们:
public void render(float delta) {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.gl.glClearColor(0f, 0f, 0f, 1f);
game.batch.begin();
for (int x = 0; x < map.length; x++) {
for (int y = 0; y < map[y].length; y++) {
if(map[x][y] == 1){
game.batch.draw(stone, x*120, y*120);
}
if(map[x][y] == 2){
game.batch.draw(grass, x*120, y*120);
}
if(map[x][y] == 0){
game.batch.draw(dirt, x*120, y*120);
}
}
}
问题:
- 所有渲染的图 block 都是污垢。
- 这确实会减慢一切。
最佳答案
2. It really slows everything down
这是由于您的 map 尺寸过大造成的:1920 x 1080 block 。如果每个图 block 均为 120 x 120 像素,则相当于 230,400 x 129,600 像素。渲染所有这些对于 OpenGL 来说不是问题,因为它会自动裁剪所有不可见的内容,并且 OpenGL 在确定可见性方面非常高效。但是在将其发送到批处理渲染器之前,您已经做了很多可以轻松避免的工作。
(以下代码片段可能不是正确的 Java。)
不要在内部绘图循环中使用
if
——甚至更好的switch
。创建索引查找数组:Texture textures[] = { dirt, stone, grass };
然后在循环内使用:
game.batch.draw(textures[map[x][y]], x*120, y*120);
不要绘制整个 map 。计算当前视口(viewport)(屏幕上显示的 map 部分)并仅绘制它。
维护一个坐标对mapx
,mapy
来保存屏幕上 map 的左上角坐标。移动该坐标对将使 map 在屏幕上移动。如果您希望“播放器”始终位于屏幕的正中央,可以像mapx = (player_x - screen_width/2)
一样简单。请注意检查是否有超出范围的值。map 上可见的部分开始于
int tile_xoffset = floor (mapx/120); int tile_yoffset = floor (mapy/120);
向下舍入,因为如果
mapx
为119
,您仍会看到map[0][y]
的一像素 strip 。 (小注意:floor
实际上是不必要的。当将浮点转换为整数时,Java会自动向下舍入。)120x120 map block 中可见部分的宽度(以及类似的高度)可以计算为
screen_width/120
但这只是可见的整个 map block 的数量。您还需要绘制仅部分可见的 block 的“边界”。
更准确的计算应该是这样的(警告:未经测试!):
int vis_width = (screen_width + (mapx % 120) + (120-(screen_width % 120)))/120;
一个好的通用原则是在内循环中进行尽可能少的计算。每个图 block 乘以
120
可以轻松地用加法代替。也没有必要对最内层循环内的x和y
都执行此操作。完成上述所有计算后,检查
tile_xoffset
是否不小于 0,并且tile_xoffset +visible_width
是否小于图 block map 的宽度;当然,y 部分也是如此。
将所有这些放在一起,您的 map 绘制代码应如下所示:
xp = (tile_xoffset*120) - mapx;
for (int x = 0; x < visible_width; x++)
{
yp = (tile_yoffset*120) - mapy;
for (int y = 0; y < visible_height; y++)
{
game.batch.draw(textures[map[x][y]], xp, yp);
yp += 120;
}
xp += 120;
}
<小时/>
要在此 map 上绘制字符,您可以将其坐标偏移-mapx,-mapy
。如果您有很多额外的字符,则可以通过首先测试它们是否在可见边界内来获得另一个加速。
关于java - 渲染图 block Java Libgdx,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25590777/