Игра Столкновение-Обработка - PullRequest
9 голосов
/ 05 декабря 2010

The code given is for example purposes, not copypasta from my codebase

Я пишу примитивную, кроссплатформенную игру Snake на C ++ с Boost и SDL, и мне интересно, каков наилучший способ реализации обработки столкновений (не collision-обнаружения).До сих пор я использовал идею единой диспетчеризации с уродливым кодом спагетти, например:

void Snake::CollisionHandler(const WorldObject& obj)
{
    // collided with self
    if(obj.GetObjectType() == snake)
        Die();
    ...
    ...
}

Кроме того, у меня есть «глобальный» обработчик коллизий, который делает вещи, вовлеченные в коллизию,которые не зависят от каждого объекта, например:


void GameWorld::CollisionHandler(WorldObject& obj1, WorldObject& obj2)
{
    if(obj1.GetObjectType() == snake && obj2.GetObjectType() == snake)
        PlayDeathSound();
    ...
    ...
}

Чтобы избежать таких вещей, как звуки, воспроизводимые дважды при столкновениях.

Я также рассмотрел двойную диспетчеризацию, например:

<code>
void Snake::CollisionHandler(WorldObject& obj) const
{
    // invoke obj's collision handler with a const Snake& parameter
    obj.CollisionHandler(*this);
}
// collided with self
void Snake::CollisionHandler(const Snake& obj)
{
    Die();
}

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

Тогда есть подход only с глобальным обработчиком коллизий (который является функцией другако всем игровым объектам), вот так:


void GameWorld::CollisionHandler(WorldObject& obj1, WorldObject& obj2)
{
    // snake collided with self
    if(obj1.GetObjectType() == snake && obj2.GetObjectType() == snake)
    {
        obj1.Die();
        obj2.Die();
        PlayDeathSound();
    }
    ...
    ...
}

Какие стратегии мне не хватает?Что из этого оказывается самым хорошим?Кажется, что все они имеют какой-то некрасивый код, а одно- и двухдиспетчерские - полиморфизм, от которого я лично стараюсь уклоняться.

Ответы [ 2 ]

5 голосов
/ 05 декабря 2010

Обработка столкновений - это область, где ориентация объектов в стиле C ++ / Java (с одной диспетчеризацией) недостаточно гибкая. Результат столкновения зависит от типов обоих сталкивающихся объектов, поэтому для его обработки требуется многократная диспетчеризация. (Не случайно, что мотивирующий пример статьи многократная рассылка в Википедии - обработка коллизий!)

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

1 голос
/ 05 декабря 2010

ИМО. Последний подход, позволяющий игровому классу полностью обрабатывать столкновения и другие глобальные события, - это самый мудрый и, возможно, самый «правильный» способ сделать это.
Например, взять шахматную программу.Совершенно очевидно, что класс игры должен обрабатывать случай выигрыша или проигрыша одного из игроков, а не класса игрока.
Это также более эффективно практически.Вспомните случай, когда вы хотите добавить больше классов (например, другого типа змей), вместо дублирования кода или переопределения CollisionHandler, вы можете просто позволить классу игры справиться с этим с гораздо меньшими усилиями., если ваша единственная цель - простая игра-змейка, вероятно, не так важно, как вы решите ее реализовать.

...