【问题标题】:LibGdx: most efficient way to draw a checkerboard in backgroundLibGdx:在背景中绘制棋盘的最有效方法
【发布时间】:2014-04-13 12:48:31
【问题描述】:

我正在使用 libgdx 构建游戏。 游戏屏幕是一个带有 Scene2D 演员的网格。演员显示在前面。 我想绘制一个看起来像棋盘的背景,每 2 个单元格用一种颜色着色,其他单元格用另一种颜色着色。

这很容易做到,但我想知道 libgdx 中是否有类可以优化这样的背景,使其尽可能轻巧和优化。例如,单独为每个单元格着色应该可行,但似乎不是最好的方法。

我已经开始深入研究 TiledMapTileLayer 类,但我必须用 Tile 对象填充每个单元格,这似乎比颜色更重。

理想情况下,我想简单地定义 2 种颜色,设置单元格的坐标,并用颜色填充它们,而不必使用对象或为单元格逐个着色。

最好的方法是什么?

【问题讨论】:

    标签: grid libgdx draw scene2d


    【解决方案1】:

    我认为最简单的方法是,您定义 2 个黑色和白色的 Tiles 或其他任何东西,并在运行时仅使用这两个 Tile 创建一个 TiledMap。它只是用相同的瓷砖填充 2 for loops(x,y) 中的单元格。应该很容易管理。将它的纹理放在一个纹理中,以便最大限度地减少渲染时间。你不需要自己处理渲染和类似的东西。您只需要使用 TiledMap 系统来实现看板的创建。没有可以只定义 2 种颜色的解决方案。我认为你总是需要以某种方式迭代单元格。

    看看example code of libgdx for creating a tiledmap on runtime

    您几乎可以复制粘贴它并更改此行

    cell.setTile(new StaticTiledMapTile(splitTiles[ty][tx]));
    

    只需根据您当前所在的单元格添加背面和白色的纹理区域即可。像这样的

    if(y % 2 !=0){
        cell.setTile(new StaticTiledMapTile(blackTextureRegion)); //or what color you need
    }else{
        cell.setTile(new StaticTiledMapTile(whiteTextureRegion)); //or what color you need
    }
    

    现在这将创建黑白行。我建议为 TextureRegions 使用 Atlas 或自己定义它们。

    玩转 x 和 y 值并检查您需要的值。也许将我写的 if 语句更改为您需要的权利。

    如果您真的只想定义一种颜色,您需要创建一个 32x32 的像素图,并在运行时填充该颜色并从中创建纹理。您可以使用它来创建如上所示的 Tilemap。

    以下是创建所需 32x32 瓷砖的方法。您甚至可以只为两个图块创建一个 32x64 的纹理。只需创建0,0,32,3232,0,32,32 的TextureRegions。

    Pixmap pixmap = new Pixmap(64, 32, Format.RGBA8888);
    pixmap.setColor(Color.BLUE); // add your 1 color here
    pixmap.fillRectangle(0, 0, 32, 32);
    
    pixmap.setColor(Color.RED); // add your 2 color here
    pixmap.fillRectangle(32, 0, 32, 32);
    // the outcome is an texture with an blue left square and an red right square
    Texture t = new Texture(pixmap);
    TextureRegion reg1 = new TextureRegion(t, 0, 0, 32, 32);
    TextureRegion reg2 = new TextureRegion(t, 32, 0, 32, 32);
    //now use this to create the StaticTiledMapTile
    

    如果您将它们粘合在一起,您应该拥有您想要的系统。 给你:

    Pixmap pixmap = new Pixmap(64, 32, Format.RGBA8888);
    pixmap.setColor(Color.BLUE); // add your 1 color here
    pixmap.fillRectangle(0, 0, 32, 32);
    
    pixmap.setColor(Color.RED); // add your 2 color here
    pixmap.fillRectangle(32, 0, 32, 32);
    // the outcome is an texture with an blue left square and an red right
    // square
    Texture t = new Texture(pixmap);
    TextureRegion reg1 = new TextureRegion(t, 0, 0, 32, 32);
    TextureRegion reg2 = new TextureRegion(t, 32, 0, 32, 32);
    
    TiledMap map = new TiledMap();
    MapLayers layers = map.getLayers();
    for (int l = 0; l < 20; l++) {
        TiledMapTileLayer layer = new TiledMapTileLayer(150, 100, 32, 32);
        for (int x = 0; x < 150; x++) {
            for (int y = 0; y < 100; 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);
    }
    

    要渲染它,您只需创建一个OrthogonalTiledMapRenderer 并调用render() 方法。

    在一个最小的例子中,这是输出:

    已经有一些宽度和高度以及层数的参数。我认为您不需要超过一层 代码:

    public class MainClass implements ApplicationListener {
        private OrthographicCamera camera;
        private OrthogonalTiledMapRenderer render;
        private final static int width = 150, height = 100, layercount = 1;
        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(64, 32, Format.RGBA8888);
            pixmap.setColor(Color.BLUE); // add your 1 color here
            pixmap.fillRectangle(0, 0, 32, 32);
    
            pixmap.setColor(Color.RED); // add your 2 color here
            pixmap.fillRectangle(32, 0, 32, 32);
            // the outcome is an texture with an blue left square and an red right
            // square
            Texture t = new Texture(pixmap);
            TextureRegion reg1 = new TextureRegion(t, 0, 0, 32, 32);
            TextureRegion reg2 = new TextureRegion(t, 32, 0, 32, 32);
    
            map = new TiledMap();
            MapLayers layers = map.getLayers();
            for (int l = 0; l < layercount; l++) {
                TiledMapTileLayer layer = new TiledMapTileLayer(width, height, 32,
                        32);
                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(GL10.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 个纹理,因此整个背景只需一个 OpenGL 绑定。

    【讨论】:

    • 感谢您抽出宝贵的时间写出如此出色的答案。但是有一个问题:有什么要处理的吗?你的 dispose 方法是空的,我只是想仔细检查一下它是不是故意的。再次感谢您的帮助
    • 是的,您应该处理渲染和地图。刚刚添加了帖子。注意你首先处理渲染而不是地图。由于渲染器仍然使用地图。
    【解决方案2】:

    您总是可以只使用 ShapeRenderer 创建一堆填充的正方形 - http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/glutils/ShapeRenderer.html

    【讨论】:

      猜你喜欢
      • 2011-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多