Хороший объектно-ориентированный дизайн класса для обнаружения столкновений в разработке игр

Я хочу узнать, как создать хорошую объектно-ориентированную (OO) конструкторскую практику для столкновения между ситуацией двух объектов в разработке игр.

Скажем, у меня есть класс SpaceShip и класс Meteor. Когда Meteor столкнется с SpaceShip, SpaceShip будет уничтожен.

Вопрос: В каком классе следует поместить метод для проверки наличия столкновений между метеором и космическим кораблем, а также метода разрешения конфликтов (уничтожить космический корабль)? Это класс SpaceShip или класс Meteor? Или, может быть, я должен поместить в другой класс, т.е. Класс GameArea или GameController?

Примечание: для простоты предположим, что Meteor и SpaceShip находятся в виде ресурса изображения. Я привык использовать язык Java, но на другом языке тоже хорошо.

Ответы

Ответ 1

Более естественно думать, что обнаружение столкновений является ответственностью, которая не относится к классам Spaceship или Meteor. Особенно, когда это осложняется множественными возможностями столкновения в разных направлениях. Если вы поместите эту логику в оба этих класса, им нужно будет иметь ссылки на множество других объектов, которые вокруг них, которые не подходят.

У вас может быть это на отдельном классе, например CollisionDetector, который отслеживает координаты всех объектов в игровом пространстве и обнаруживает столкновения. По-видимому, предотвращение столкновений является отдельной ответственностью, которая, по моему мнению, должна быть в другом классе. Для этого у вас может быть отдельный класс CollisionResolver. В зависимости от требований CollisionDetector может разговаривать с CollisionResolver.

CollisionResolver может потребоваться поговорить с Spaceships для целей, таких как консультирование по изменению направления или командование стрельбой ракетами в направлении Метеор.

CollisionDetector и CollisionResolver могут находиться в GameSpace/* GameController *. и т.д..

Это способствовало бы принципу единой ответственности, чтобы каждый компонент выполнял только одну сосредоточенную задачу.

Ответ 2

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

Другое дело, что в играх обычно объект состоит из нескольких слоев (компонентов): Graphics Layer, Physical Layer, Logic Layer. Таким образом, физический менеджер управляет только физическим компонентом данных объектов.

class GameObject 
{
    RenderComponent  m_renderComponent;
    LogicComponent   m_aiComponent;
    PhysicsComponent m_physicsComponent;
};

Ответ 3

Ну, я обычно создаю (иногда общий) GameObject класс или интерфейс, который имеет метод collides. Например:

template< typename T = int > class GameObject
{
public:
    bool collides(const GameObject& obj);
};

// usage
GameObject<int> my_obj, your_obj;
if(my_obj.collides(your_obj)) { ... };

Другая вещь, которую я иногда (но редко) делаю, - создать отдельный класс GamePhysics:

template< typename T > class GamePhysics
{
public:
    /* you may make this static or the class a singleton */
    void detect_collision(const T& obj, const T& obj2);
};

Ответ 4

В Java (или любом другом языке OO) я бы разместил CollisionDetected callback/event в общем классе предков всех движущихся объектов в вашей игре.

Это упрощенное описание игры:

  • В игре обычно существует игровой цикл. Цикл игры похож на цикл while (true), который работает непрерывно (вроде как основной поток пользовательского интерфейса приложения) и на каждом шаге проверяет, что изменилось с объектами, что нужно обновлять и какие события следует вызывать ( и многое другое...).

  • Для реагирования этот цикл должен цикл много раз в секунду.

  • Внутри этого цикла объект Физический двигатель должен постоянно обновлять его статус. Это будет экземпляр объекта независимого класса. Этот движок должен обнаруживать столкновения между объектами и вызывать событие CollisionDetected для всех объектов, которые столкнулись.

Это идея, а не окончательное решение...