Хороший объектно-ориентированный дизайн класса для обнаружения столкновений в разработке игр
Я хочу узнать, как создать хорошую объектно-ориентированную (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 для всех объектов, которые столкнулись.
Это идея, а не окончательное решение...