Проблемы с коллизией карты с использованием шестнадцатеричного изображения маски в Java - PullRequest
2 голосов
/ 29 мая 2020

Я делал игру, и мне пришла в голову идея использовать шестнадцатеричные цветовые коды для создания столкновений с объектами на карте, используя изображение png в качестве маски. Чтобы это сработало, код будет сканировать каждый пиксель этой маски, и, если пиксель имеет определенный цвет c, в его местоположении появится невидимый блок. Однако, поскольку изображение, которое я использую в качестве маски, довольно большое (1582 x 1146), код использует слишком большую мощность процессора (я думаю, что это процессор, не так уверен) для сканирования каждого пикселя, и игра запускается буквально со скоростью 1 кадр / с.

public class World {
    private Tile[] tiles;
    private static int WIDTH = 1582, HEIGHT = 1146;

    public World(String path) {
        try {
            BufferedImage map = ImageIO.read(getClass().getResource(path));
            int[] pixels = new int[map.getWidth() * map.getHeight()];
            tiles = new Tile[map.getWidth() * map.getHeight()];
            map.getRGB(0, 0, map.getWidth(), map.getHeight(), pixels, 0, map.getWidth());
            for (int xx = 0; xx < map.getWidth(); xx++) {
                for (int yy = 0; yy < map.getHeight(); yy++) {
                    int pixelAtual = pixels[xx + (yy * map.getWidth())];
                    if (pixelAtual == 0xfffcff00) //Pixel's hex verification
                    {
                        tiles[xx + (yy * WIDTH)] = new TileWall(xx, yy, Tile.TILE_WALL); //Invisible tile wall
                    }
                    /*else if (pixelAtual == )  Adding another tile
                        tiles[xx + (yy * WIDTH)] = new  TileWall(xx, yy, Tile.TILE_WALL);
                    } */
                    else {
                        tiles[xx + (yy * WIDTH)] = new TileFloor(xx, yy, Tile.TILE_FLOOR); //Invisible tile floor, just to complete the array
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void render(Graphics g) {
        for (int xx = 0; xx < WIDTH; xx++) {
            for (int yy = 0; yy < HEIGHT; yy++) {
                Tile tile = tiles[xx + (yy * WIDTH)];
                tile.render(g);
            }
        }
    }
}

Я думал, что этот метод шестнадцатеричного сканирования будет легко написать и практичным в использовании. Есть ли другой способ добавить в игру столкновения?

1 Ответ

2 голосов
/ 29 мая 2020

Незначительное примечание: есть https://gamedev.stackexchange.com/, который вы можете найти полезным ресурсом для этих типов вопросов.

Обнаружение столкновений может быть сложной задачей и действительно также сложный в вычислительном отношении topi c, потребляющий много времени выполнения и памяти. Однако это может быть довольно просто. Это зависит от ваших требований и дизайна игры. Часто бывает полезно изменить дизайн игры, чтобы упростить обнаружение столкновений, хотя это, конечно, зависит от того, какие интересные, забавные или прибыльные игры вы хотите делать.

То, как вы описываете звук, немного похоже на обнаружение столкновений на основе растра, где область, определяемая пикселями (если в 3D, это будет объем, определяемый вокселями), используется для обнаружения столкновений. Более распространенный подход состоит в том, чтобы вместо этого выполнять обнаружение столкновений с использованием подходов geometri c - прямоугольник, определенный по 4 точкам, круг по центру и радиусу, многоугольник и т. Д. c. Они часто могут давать хорошие результаты и быть достаточными для ваших нужд, и они обычно позволяют достаточно быстрое обнаружение столкновений, хотя их может быть немного сложнее реализовать. Тем не менее, есть статьи и учебные ресурсы, доступные в разных местах рег. такие алгоритмы, поэтому использование обнаружения столкновений на основе геометрических c форм по-прежнему должно быть достаточно доступным.

Обнаружение столкновений на основе прямоугольников очень легко реализовать. Создать по кругу все еще довольно просто. Метод на основе выпуклого многоугольника более сложен, но для него есть ресурсы, такие как ссылки в этом ответе: Обнаружение столкновений 2D-полигонов .

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

В качестве примечания: есть некоторые игровые движки и библиотеки, которые поддерживают растровые столкновения обнаружения, например GameMaker. Но поскольку он (как в вашем примере) может быть очень или очень медленным, с ним нужно быть осторожным.

Рег. l oop, имеет смысл, что он может быть медленным: в худшем случае, возможно, придется перебирать все пиксели. 1582 x 1146 дает в худшем случае 1812972. Предполагая, что вы не создаете объекты, а вместо этого просто позволяете ему быть представленным массивом с логическим или аналогичным значением, это может затем выполняться несколько раз (каждый раз, когда вы проверяете коллизии) в кадре, а затем кадр может выполняться несколько раз раз в секунду. Все это каждую секунду увеличивается до огромной нагрузки. Существуют различные способы оптимизации таких вещей, и для игры в реальном времени уменьшение времени, затрачиваемого на каждый кадр, может быть важным и сложной задачей. Хотя, опять же, изменение дизайна игры и требований на что-то менее интенсивное может быть полезным (что опять же является компромиссом).

В заключение, вы используете объекты для представления одного пикселя, если я понимаю ваш код правильно. Если вы новичок в объектно-ориентированном программировании, вас, возможно, заставили поверить в то, что объекты обычно хороши для непосредственного моделирования вашей предметной области. Это очень распространенное мнение новичков (также распространенное в различных учебных материалах), но в целом оно неверно. Для игр в реальном времени производительность часто имеет значение, и использование объектов по-разному, а не их прямое моделирование предметной области, может быть хорошей идеей, поскольку некоторые виды использования объектов могут иметь значительные накладные расходы времени выполнения. В других случаях могут возникнуть другие опасения. Например, вас могли научить, что класс можно использовать для описания типа Animal, а подтипы тогда могут быть Dog и Cat. Это очень прямое моделирование (и его легко обучить). Однако на практике описание всех видов животных с помощью одного класса данных может быть более подходящим, например, если вы хотите описать множество, множество и множество животных, и у них нет различных функций, только атрибуты. Если вы попытаетесь описать всех этих животных, используя подтипы, как можно предположить из некоторых учебных материалов, у вас может получиться очень большое количество подтипов с небольшими различиями между ними, причем очень многие классы стоят больше, чем приносят вам пользу. рег. развитие относительно просто наличия одного класса данных. Я надеюсь, что эта последняя часть ясна, хотя я не уверен, насколько ясно я ее изложил.

...