You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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() {}
}

问题排查

  1. Pixmap尺寸与绘制错误
    • 创建的Pixmap宽度仅100,但要截取80x80的第二个区域(x=80),超出Pixmap范围,导致reg2是无效区域
    • 两次fillRectangle都从(0,0)开始,黑色完全覆盖白色,两个TextureRegion实际颜色一致,棋盘区分失效
  2. 变量遮蔽
    • create方法内重新定义TiledMap map = new TiledMap(),导致全局map变量未初始化,dispose时会抛出空指针异常
  3. 相机未更新
    • camera.translate后未调用camera.update(),初始相机位置未生效,可能导致部分棋盘区域不在可视范围内
  4. 冗余图层
    • 创建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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 06:55:22