LibGdx棋盘绘制问题求助:缺失两行棋盘格,附代码求解决方案
LibGdx绘制棋盘缺失两行问题排查与解决方案
我尝试在LibGdx中绘制棋盘,但遇到棋盘缺失两行的问题。以下是我的代码,希望找出问题所在,若无法修复也可接受其他解决方案。
package com.mygdx.game; import com.badlogic.gdx.ApplicationAdapter; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Pixmap.Format; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.maps.MapLayers; import com.badlogic.gdx.maps.tiled.TiledMap; import com.badlogic.gdx.maps.tiled.TiledMapTileLayer; import com.badlogic.gdx.maps.tiled.TiledMapTileLayer.Cell; import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer; import com.badlogic.gdx.maps.tiled.tiles.StaticTiledMapTile; import com.badlogic.gdx.utils.ScreenUtils; import com.badlogic.gdx.utils.viewport.Viewport; public class MyGdxGame extends ApplicationAdapter { SpriteBatch batch; Texture img; private OrthographicCamera camera; private OrthogonalTiledMapRenderer render; private final static int width = 100, height = 80, layercount = 8; private TiledMap map; @Override public void create() { float w = Gdx.graphics.getWidth(); float h = Gdx.graphics.getHeight(); camera = new OrthographicCamera(w, h); Pixmap pixmap = new Pixmap(100, 80, Format.RGBA8888); pixmap.setColor(Color.WHITE); pixmap.fillRectangle(0, 0, 80, 80); pixmap.setColor(Color.BLACK); pixmap.fillRectangle(0, 0, 80, 80); // 预期是左侧白色方块、右侧黑色方块,但实际被覆盖 Texture t = new Texture(pixmap); TextureRegion reg1 = new TextureRegion(t, 0, 0, 80, 80); TextureRegion reg2 = new TextureRegion(t, 80, 0, 80, 80); TiledMap map = new TiledMap(); MapLayers layers = map.getLayers(); for (int l = 0; l < layercount; l++) { TiledMapTileLayer layer = new TiledMapTileLayer(width, height, 80, 80); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { Cell cell = new Cell(); if (y % 2 != 0) { if (x % 2 != 0) { cell.setTile(new StaticTiledMapTile(reg1)); } else { cell.setTile(new StaticTiledMapTile(reg2)); } } else { if (x % 2 != 0) { cell.setTile(new StaticTiledMapTile(reg2)); } else { cell.setTile(new StaticTiledMapTile(reg1)); } } layer.setCell(x, y, cell); } } layers.add(layer); } render = new OrthogonalTiledMapRenderer(map); render.setView(camera); camera.translate(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2); } @Override public void dispose() { render.dispose(); map.dispose(); } private static final float movmentspeed = 5f; @Override public void render() { Gdx.gl.glClearColor(1, 1, 1, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); camera.update(); render.setView(camera); render.render(); if (Gdx.input.isKeyPressed(Keys.LEFT)) { camera.translate(-movmentspeed, 0); } else if (Gdx.input.isKeyPressed(Keys.RIGHT)) { camera.translate(movmentspeed, 0); } else if (Gdx.input.isKeyPressed(Keys.UP)) { camera.translate(0, movmentspeed); } else if (Gdx.input.isKeyPressed(Keys.DOWN)) { camera.translate(0, -movmentspeed); } } @Override public void resize(int width, int height) {} @Override public void pause() {} @Override public void resume() {} }
问题排查
- Pixmap尺寸与绘制错误
- 创建的Pixmap宽度仅100,但要截取80x80的第二个区域(x=80),超出Pixmap范围,导致
reg2是无效区域 - 两次
fillRectangle都从(0,0)开始,黑色完全覆盖白色,两个TextureRegion实际颜色一致,棋盘区分失效
- 创建的Pixmap宽度仅100,但要截取80x80的第二个区域(x=80),超出Pixmap范围,导致
- 变量遮蔽
create方法内重新定义TiledMap map = new TiledMap(),导致全局map变量未初始化,dispose时会抛出空指针异常
- 相机未更新
camera.translate后未调用camera.update(),初始相机位置未生效,可能导致部分棋盘区域不在可视范围内
- 冗余图层
- 创建8层完全相同的棋盘图层,完全没必要,浪费渲染性能
修复后的代码
package com.mygdx.game; import com.badlogic.gdx.ApplicationAdapter; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Pixmap.Format; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.maps.MapLayers; import com.badlogic.gdx.maps.tiled.TiledMap; import com.badlogic.gdx.maps.tiled.TiledMapTileLayer; import com.badlogic.gdx.maps.tiled.TiledMapTileLayer.Cell; import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer; import com.badlogic.gdx.maps.tiled.tiles.StaticTiledMapTile; public class MyGdxGame extends ApplicationAdapter { private OrthographicCamera camera; private OrthogonalTiledMapRenderer render; private final static int TILE_COUNT_WIDTH = 100, TILE_COUNT_HEIGHT = 80; private final static int TILE_SIZE = 80; private TiledMap map; private static final float MOVEMENT_SPEED = 5f; @Override public void create() { float screenWidth = Gdx.graphics.getWidth(); float screenHeight = Gdx.graphics.getHeight(); camera = new OrthographicCamera(screenWidth, screenHeight); // 相机居中并更新 camera.position.set(screenWidth / 2, screenHeight / 2, 0); camera.update(); // 创建能容纳两个80x80方块的Pixmap Pixmap pixmap = new Pixmap(TILE_SIZE * 2, TILE_SIZE, Format.RGBA8888); // 绘制白色方块 pixmap.setColor(Color.WHITE); pixmap.fillRectangle(0, 0, TILE_SIZE, TILE_SIZE); // 绘制黑色方块(x偏移80) pixmap.setColor(Color.BLACK); pixmap.fillRectangle(TILE_SIZE, 0, TILE_SIZE, TILE_SIZE); Texture tileTexture = new Texture(pixmap); pixmap.dispose(); // 用完Pixmap及时释放资源 TextureRegion whiteTile = new TextureRegion(tileTexture, 0, 0, TILE_SIZE, TILE_SIZE); TextureRegion blackTile = new TextureRegion(tileTexture, TILE_SIZE, 0, TILE_SIZE, TILE_SIZE); // 使用全局map变量,避免遮蔽 map = new TiledMap(); MapLayers layers = map.getLayers(); // 只创建一层棋盘即可 TiledMapTileLayer chessboardLayer = new TiledMapTileLayer(TILE_COUNT_WIDTH, TILE_COUNT_HEIGHT, TILE_SIZE, TILE_SIZE); for (int x = 0; x < TILE_COUNT_WIDTH; x++) { for (int y = 0; y < TILE_COUNT_HEIGHT; y++) { Cell cell = new Cell(); // 棋盘颜色逻辑:(x+y)为偶数时白色,奇数时黑色 boolean isWhite = (x + y) % 2 == 0; cell.setTile(new StaticTiledMapTile(isWhite ? whiteTile : blackTile)); chessboardLayer.setCell(x, y, cell); } } layers.add(chessboardLayer); render = new OrthogonalTiledMapRenderer(map); render.setView(camera); } @Override public void dispose() { render.dispose(); map.dispose(); } @Override public void render() { Gdx.gl.glClearColor(1, 1, 1, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); camera.update(); render.setView(camera); render.render(); // 相机移动逻辑 if (Gdx.input.isKeyPressed(Keys.LEFT)) { camera.translate(-MOVEMENT_SPEED, 0); } if (Gdx.input.isKeyPressed(Keys.RIGHT)) { camera.translate(MOVEMENT_SPEED, 0); } if (Gdx.input.isKeyPressed(Keys.UP)) { camera.translate(0, MOVEMENT_SPEED); } if (Gdx.input.isKeyPressed(Keys.DOWN)) { camera.translate(0, -MOVEMENT_SPEED); } } @Override public void resize(int width, int height) { // 适配窗口大小 camera.setToOrtho(false, width, height); camera.update(); } @Override public void pause() {} @Override public void resume() {} }
简化方案:直接用SpriteBatch绘制棋盘
如果不需要TiledMap,用SpriteBatch直接绘制会更简单高效:
package com.mygdx.game; import com.badlogic.gdx.ApplicationAdapter; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.SpriteBatch; public class MyGdxGame extends ApplicationAdapter { private OrthographicCamera camera; private SpriteBatch batch; private Texture whiteTile, blackTile; private final static int TILE_COUNT_WIDTH = 100, TILE_COUNT_HEIGHT = 80; private final static int TILE_SIZE = 80; private static final float MOVEMENT_SPEED = 5f; @Override public void create() { float screenWidth = Gdx.graphics.getWidth(); float screenHeight = Gdx.graphics.getHeight(); camera = new OrthographicCamera(screenWidth, screenHeight); camera.position.set(screenWidth / 2, screenHeight / 2, 0); camera.update(); batch = new SpriteBatch(); // 创建单色纹理 Pixmap pixmap = new Pixmap(TILE_SIZE, TILE_SIZE, Pixmap.Format.RGBA8888); pixmap.setColor(Color.WHITE); pixmap.fill(); whiteTile = new Texture(pixmap); pixmap.setColor(Color.BLACK); pixmap.fill(); blackTile = new Texture(pixmap); pixmap.dispose(); } @Override public void dispose() { batch.dispose(); whiteTile.dispose(); blackTile.dispose(); } @Override public void render() { Gdx.gl.glClearColor(1, 1, 1, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); camera.update(); batch.setProjectionMatrix(camera.combined); batch.begin(); // 绘制棋盘 for (int x = 0; x < TILE_COUNT_WIDTH; x++) { for (int y = 0; y < TILE_COUNT_HEIGHT; y++) { float tileX = x * TILE_SIZE; float tileY = y * TILE_SIZE; Texture tile = (x + y) % 2 == 0 ? whiteTile : blackTile; batch.draw(tile, tileX, tileY); } } batch.end(); // 相机移动 if (Gdx.input.isKeyPressed(Keys.LEFT)) camera.translate(-MOVEMENT_SPEED, 0); if (Gdx.input.isKeyPressed(Keys.RIGHT)) camera.translate(MOVEMENT_SPEED, 0); if (Gdx.input.isKeyPressed(Keys.UP)) camera.translate(0, MOVEMENT_SPEED); if (Gdx.input.isKeyPressed(Keys.DOWN)) camera.translate(0, -MOVEMENT_SPEED); } @Override public void resize(int width, int height) { camera.setToOrtho(false, width, height); camera.update(); } }
内容的提问来源于stack exchange,提问作者alexandra zamfir
相关产品推荐
相关产品推荐

