Нарисовать плитку из островов, которые находятся в пределах границ, используя и libGDX


Я новый человек в отношении и libGDX. Я написал ниже метод render. Я случайно поколений океанов (где есть острова в произвольном положении). В ниже код, focusedMapRectangle относится к сосредоточенным частью этой карте. Задача-нарисовать плитку из островов, которые находятся в пределах focusedMapRectangle.

Я хотел бы некоторую обратную связь в отношении:

  1. преобразование из моих собственных алгоритмов/кода для функций и libGDX (т. е. как я могу использовать существующие объекты и libGDX в отличие от делать расчеты сам напрямую).

  2. стиль кода / имена переменных (и могут ли другие являются предпочтительными)

  3. неэффективные вычисления, которые я могу сделать более эффективными способами (скорость)

@Override
public void render(float delta) {
    Gdx.gl.glClearColor(0.5f, 0.5f, 1, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    Gdx.gl.glClear(GL20.GL_ALPHA_BITS);
    getBatch().begin();

    Rectangle focusedMapRectangle = new Rectangle(
            getMatchMap().getBottomLeft().x,
            getMatchMap().getBottomLeft().y,
            Gdx.graphics.getWidth() / 16,
            Gdx.graphics.getHeight() / 16
    );

    getMatchMap().getIslands().forEach((island, point) -> {
        Rectangle islandRectangle = new Rectangle(
            point.x,
            point.y,
            island.getMaxWidth(),
            island.getMaxHeight()
        );

        // Signifies that the island is indeed present in the focused part of the map
        if (focusedMapRectangle.overlaps(islandRectangle)) {
            for (int islandTileX = 0; islandTileX < islandRectangle.getWidth(); islandTileX++) {
                for (int islandTileY = 0; islandTileY < islandRectangle.getHeight(); islandTileY++) {

                    // These refer to the absolute positions that each tile of the island has
                    // within the WHOLE map (not just focused)
                    int absoluteTileX = islandTileX + (int) point.x;
                    int absoluteTileY = islandTileY + (int) point.y;

                    // These refer to the position that each tile of the island has
                    // relative to the bottom left of the focused part of the map.
                    int relativeXToFocusPoint = absoluteTileX - (int) getMatchMap().getBottomLeft().x;
                    int relativeYToFocusPoint = absoluteTileY - (int) getMatchMap().getBottomLeft().y;

                    // Though we have verified that some part of the island is within the
                    // focused part of the map, it is is still possible that SOME of the island's tiles
                    // are NOT in focus.
                    boolean isXOutOfFocus = relativeXToFocusPoint < 0;
                    boolean isYOutOfFocus = relativeYToFocusPoint < 0;

                    // No need to render these said tiles of the island
                    if (isXOutOfFocus || isYOutOfFocus)
                        continue;

                    IslandTileType islandTileType = island.getRepr()[islandTileX][islandTileY];

                    // Do not go into statement if island tile type is water i.e null
                    if (islandTileType != null) {
                        Texture islandTexture = getIslandTextures().get(islandTileType);

                        int relativeCoordXToFocusPoint = relativeXToFocusPoint * 16;
                        int relativeCoordYToFocusPoint = relativeYToFocusPoint * 16;

                        getBatch().draw(islandTexture, relativeCoordXToFocusPoint, relativeCoordYToFocusPoint);
                    }
                }
            }
        }
    });

    getBatch().end();
}


146
5
задан 15 апреля 2018 в 05:04 Источник Поделиться
Комментарии
1 ответ

Уменьшить Ассигнования

Создание объектов во время игры не является оптимальным. Вы также создаете эти объекты внутри render метод, который будет вызываться много тысяч раз. Сборщик мусора-это хорошо, но вы будете по-прежнему видеть шипы производительность, когда она делает слишком много работы.

К счастью, вы можете устранить все эти деньги!

Одним из подходов, которые вы найдете полезно использовать PoolС. Это очень удобно при работе со многими классами и libGDX. Его установка занимает всего одну строку, где 100 ниже находится максимальное количество объектов, которые вам нужны на один раз:

private final Pool<Rectangle> recPool = Pools.get(Rectangle.class, 100);

Затем, когда вы хотите, чтобы объект "прямоугольник":

Rectangle focusedMapRectangle = recPool.obtain();

И когда вы закончите с использованием объекта:

recPool.free(focusedMapRectangle);

В Rectangle класс имеет ряд set методы для того, чтобы настроить его после получения объекта.

focusedMapRectangle.setX(getMatchMap().getBottomLeft().x);
focusedMapRectangle.setY(getMatchMap().getBottomLeft().y);
focusedMapRectangle.setWidth(Gdx.graphics.getWidth() / 16);
focusedMapRectangle.setHeight(Gdx.graphics.getHeight() / 16);

Я упоминаю Poolпотому что я думаю, что вы найдете его полезным в будущем, однако я думаю, что есть лучший подход в этом случае.

Нужен новый Rectangle в начале render метод, потому что это будет соответствовать текущему взгляд на мир. Однако, вместо того, чтобы создавать новый объект каждый раз, вы можете иметь один Rectangle и просто использовать set методы выше, чтобы установить его на соответствующие значения.

Это подводит меня к следующему нарушителю:

getMatchMap().getIslands().forEach((island, point) -> {
Rectangle islandRectangle = new Rectangle(
point.x,
point.y,
island.getMaxWidth(),
island.getMaxHeight()
);

Что getIslands() возвраты не является абсолютно ясным для меня, но я могу сказать, что каждый island есть point связанные с ним. Что point не представляется возможны изменения. Я тоже предполагаю, что maxWidth и maxHeight острова не подлежат изменению. Так почему заранее не просчитать Rectangle на остров при первом его создании? Затем вы можете просто сделать

if (focusedMapRectangle.overlaps(island.getRectangle())) { 

и совершенно не выделяет каких-либо новых объектов.

Остерегайтесь итераторы

Я не знаю, если вы используете и libGDX Array и Map классы, но вы должны рассмотреть это, если не. forEach само по себе это не проблема, но если вы используете обычное Java классы коллекций, перебор приведет к большим и большим количеством выделений. Коллекции и libGDX предназначены, чтобы избежать эти выделения при переборе.

Разделение

В настоящее время метод render делает две основные вещи. Он определяет, является ли остров находится в вид, и тогда он делает это. Однако, это делает обе эти вещи для каждого острова одновременно. Я думаю, что лучше было бы отделить сортировка от перевода. Сначала вы могли бы назвать sortIslands() метод, который бы поставил все острова, которые должны быть сделаны в массив. Затем метод render просто перебрать массив и сделать необходимые острова. Позже, если вы решите изменить способ островах сортируются, это будет намного проще. Он также будет более ясным и более нагляден, чтобы сделать сортировку вне метода render.

Стоит ли оно того?

Сортировка плиток, чтобы решить, что должно быть представлено, а что не будет (по моему опыту) в конечном итоге, используя больше ресурсов, чем стоит. Я рекомендую профилирования и без выбраковки для того, чтобы увидеть, если она обеспечивает прирост производительности для игр.

3
ответ дан 4 мая 2018 в 12:05 Источник Поделиться