Обнаружение столкновений в C ++ - PullRequest
0 голосов
/ 15 марта 2020

Я работаю над 3D-лабиринтом, в котором сам лабиринт генерируется автоматически и случайным образом при каждом запуске программы. Так что в основном стены всегда где-то еще. Здесь мне нужна помощь, чтобы выяснить, как обнаружить столкновение, и, таким образом, игрок не может нажимать кнопки, чтобы двигаться, так как там стена. (3D на самом деле не имеет значения, так как он виден сверху, и теперь он работает как 2D-лабиринт)

Вот где я сейчас:

Мой персонаж - простой куб:

struct Cube {
    glm::vec3 position;
    glm::vec3 size;
};

Ниже вы можете найти, как я могу сделать моего персонажа подвижным. Я мог бы проверить, есть ли край лабиринта, чтобы вы не могли пройти через эти стены, но внутри лабиринта вы все еще можете. Стены всегда 0,25 ширины. Я хотел бы реализовать такую ​​функцию, как IsCollide, но я не знаю как. Когда я вызову функцию, std::vector<Cube> maze будет содержать данные, которые я покажу на картинке.

maze datas

        static void MoveCharacter(Cube &character, Keyboard keyboard, std::vector<Cube> maze)
        {
            if (keyboard.getKey(GLFW_KEY_UP))
            {

                if (character.position.x >= MazeHeight - 1.0f) || IsCollide(character, maze))
                {
                   character.position += glm::vec3(0,0,0);
                } else character.position += glm::vec3(0.05, 0, 0);
            }
            if (keyboard.getKey(GLFW_KEY_DOWN))
            {
                if (character.position.x <= 0.0f)
                {
                    character.position += glm::vec3(0, 0, 0);
                } else character.position -= glm::vec3(0.05, 0, 0);

            }
            if (keyboard.getKey(GLFW_KEY_RIGHT))
            {
                if (character.position.z >= MazeWidth - 1.0f)
                {
                    character.position += glm::vec3(0, 0, 0);
                } else character.position += glm::vec3(0, 0, 0.05);
            }
            //...
         }

Я пытался написать свою функцию как-то так, но я в значительной степени потерян в этом и не уверен, как go на ...

     static bool IsCollide(Cube character, std::vector<Cube> maze)
        {
        for (auto i : maze)
            if ( (character.position.x < (i.position.x + i.size.x)) && (character.position.x + character.size.x > i.position.x)) // && (//...) && (//...)
     // to implement!
            {
                return true;
            } return false;
        }

Я был бы ОЧЕНЬ рад каждому ответу и помощи!

Заранее большое спасибо!

1 Ответ

0 голосов
/ 15 марта 2020

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

Если вы действительно хотите попытаться запрограммировать это самостоятельно, тогда вы можете сделать следующее:

В программе, которую вы разместили, игрок перемещается на 0,05 единиц за раз, а стены имеют толщину 0,25 единиц. Следовательно, может быть достаточно осуществить тестирование на столкновение, просто проверив, находится ли новая позиция игрока внутри стены. Для быстро движущихся объектов (таких как пули, выпущенные из оружия), такое обнаружение столкновений может быть недостаточным, поскольку объект может пройти через стену за один шаг, даже не будучи внутри нее.

Для проверки новая позиция игрока находится внутри стены, вы можете сравнить позицию игрока с каждой отдельной стеной на карте. Однако, в зависимости от количества стен на карте, это может быть много работы. Следовательно, более эффективный алгоритм будет проверять только новую позицию игрока со стенами, которые находятся рядом.

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

Вместо использования фиксированной сетки, вы можете используйте более адаптивную структуру данных, такую ​​как R-дерево . Обычно такая структура данных работает лучше, если объекты расположены неравномерно, например, когда у вас много объектов в небольшой области, а большая часть остальной части карты пуста.

...