質問

I am building a game with libgdx. The game screen is a grid with Scene2D actors. Actors are displayed on the front. I would like to draw a background that looks like a checkerboard, coloring every 2 cells with one color and the other cells with another color.

It is easy to do but I was wondering if there are classes in libgdx that could optimize such a background, to make it as light and optimized as possible. For example, coloring each cell individually should work but doesn't seem like the best approach.

I have started to dig into the TiledMapTileLayer class but I'd have to fill each cell with a Tile object and that seems heavier than just a color.

Ideally, I would like to simply define 2 colors, set coordinates of the cells, and fill them with the colors without having to use objects or color the cells one by one.

What would be the best approach?

役に立ちましたか?

解決

I think the most simple way would be, that you define 2 Tiles black and white or what ever and create an TiledMap on runtime just with those two tiles. It's just filling the cells in 2 for loops(x,y) with the same tiles. Should be easy to manage. Put the texture of it inside of one texture so you minimize the rendertime. You than dont need to handle the rendering and stuff like that yourself. You just need to implement the creation of the board with the TiledMap system. There is no solution where you can just define 2 colors. You always need to iterate over the cells somehow i think.

Take a look at the example code of libgdx for creating a tiledmap on runtime.

You can nearly copy paste it and just change this line

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

Simply add the texture region for the back and white there depending on which cell you are currently are. something like this

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
}

this would now create black and white rows. I recomend to use a Atlas for the TextureRegions or define them yourself.

Play around with the x and y values and check which you need. Maybe change the if statement i wrote to the right you need.

If you really just want to define a color you need to create a Pixmap with the 32x32 filled with the color on runtime and create a texture out of it. You can than use this to create the Tilemap as shown above.

Here is how you can create the 32x32 tiles you need. You can even create just one texture with 32x64 for both tiles. Just create the TextureRegions of 0,0,32,32 and 32,0,32,32.

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

If you glue this together you should have your system you would like to have. Here you go:

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);
}

To render this you simply create an OrthogonalTiledMapRenderer and call the render() method.

In an minimum example this is the output:

cheststyle

already has some parameters for width and height and layercount. I think you wont need more than one layer Code:

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

In the end. i can't tell you if this is efficient! Maybe there are more efficient ways but this create your thing on runtime and if you dont do the creation over and over again it shouldn't be a problem since you just do it once you load the game for example. I think its efficient because the render is efficient and just draw the tiles that are visible on the screen. Moreover you just use 1 Texture for the background so its just one OpenGl bind for the whole background.

他のヒント

You could always just use ShapeRenderer to create a bunch of filled squares - http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/glutils/ShapeRenderer.html

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top