LibGdx: наиболее эффективный способ рисования шахматной доски в фоновом режиме

Я создаю игру с помощью libgdx. Экран игры представляет собой сетку с актерами Scene2D. На переднем плане изображены актеры. Я хотел бы нарисовать фон, похожий на шахматную доску, окрашивая каждые 2 ячейки одним цветом, а остальные ячейки другим цветом.

Это легко сделать, но мне было интересно, есть ли классы в libgdx, которые могли бы оптимизировать такой фон, чтобы сделать его максимально легким и оптимизированным. Например, раскрашивание каждой ячейки по отдельности должно работать, но не кажется лучшим подходом.

Я начал копаться в классе TiledMapTileLayer, но мне пришлось бы заполнять каждую ячейку объектом Tile, и это кажется более тяжелым, чем просто цвет.

В идеале я хотел бы просто определить 2 цвета, установить координаты ячеек и заполнить их цветами без необходимости использовать объекты или раскрашивать ячейки одну за другой.

Что было бы лучшим подходом?


person Don    schedule 10.03.2014    source источник


Ответы (2)


Я думаю, что самым простым способом было бы определить 2 тайла, черный и белый или что-то еще, и создать TiledMap во время выполнения только с этими двумя тайлами. Это просто заполнение ячеек в 2 циклах (x, y) одинаковыми плитками. Должно быть легко управлять. Поместите его текстуру внутрь одной текстуры, чтобы минимизировать время рендеринга. Вам не нужно заниматься рендерингом и тому подобными вещами самостоятельно. Вам просто нужно реализовать создание платы с помощью системы TiledMap. Нет решения, в котором вы можете просто определить 2 цвета. Я думаю, вам всегда нужно как-то перебирать ячейки.

Взгляните на пример кода libgdx для создания тайловой карты во время выполнения.

Вы можете почти скопировать его и просто изменить эту строку

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
}

теперь это создаст черные и белые строки. Я рекомендую использовать Atlas для TextureRegions или определить их самостоятельно.

Поэкспериментируйте со значениями x и y и проверьте, что вам нужно. Возможно, измените оператор if, который я написал, на нужный вам.

Если вы действительно просто хотите определить цвет, вам нужно создать растровое изображение с размером 32x32, заполненным цветом во время выполнения, и создать из него текстуру. Вы можете использовать это для создания Tilemap, как показано выше.

Вот как вы можете создать нужные плитки размером 32x32. Вы даже можете создать только одну текстуру размером 32x64 для обоих тайлов. Просто создайте TextureRegions 0,0,32,32 и 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

Если вы склеите это вместе, у вас должна быть ваша система, которую вы хотели бы иметь. Ну вот:

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 для всего фона.

person BennX    schedule 10.03.2014
comment
Спасибо, что нашли время написать такой отличный ответ. Но один вопрос: есть ли что-нибудь, что можно было бы утилизировать? ваш метод dispose пуст, и я просто хотел дважды проверить, что это было сделано специально. В очередной раз благодарим за помощь - person Don; 11.03.2014
comment
Да, вы должны удалить рендер и карту. Просто добавил пост к этому. позаботьтесь о том, чтобы сначала удалить рендеринг, а не карту. Так как рендер все еще может использовать карту. - person BennX; 11.03.2014

Вы всегда можете просто использовать ShapeRenderer для создания набора заполненных квадратов - http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/glutils/ShapeRenderer.html

person Chase    schedule 10.03.2014