Рекомендации по структуре классов в системе обнаружения столкновений

0

C++ - это первый язык, который я использовал во всем экстенсивно, который использует объектную ориентацию, поэтому я все еще немного новичок в этой идее. Я пытаюсь портировать библиотеку игр, с которой я работал, от Go (который использует интерфейсы вместо истинной системы OOP) до C++.

У меня есть система столкновений, которая использует четыре типа: точку, ограничительную, линию и многоугольник. То, что я хотел бы сделать, состоит в том, чтобы все они были абстрактно-способными в класс "Коллайдер" и имели функцию, которая способна принимать два объекта коллайдера и проверять наличие столкновения. Это будет выглядеть примерно так:

bool Collides(Collider obj1, Collider obj2);

Первоначально я думал, что у меня могут быть методы для каждого типа столкновения, которые будут проверять наличие столкновения с другим типом (то есть методы OnPoint, OnBounding, OnLine и OnPolygon), а затем иметь "Коллайдер" как виртуальный класс, который требует всех этих методов, но то я понял, что это невозможно в C++, потому что он будет заставлять классы зависеть друг от друга для компиляции (правильно?).

Я немного растерялся о том, что еще я могу сделать. Является ли моя идея дизайна мечтой?

  • 0
    Почему вы думаете, что занятия будут зависеть друг от друга? Если все они являются дочерними классами абстрактного класса Collider и все они просто переопределяют методы, определенные в этом классе, тогда ваш метод Collides не должен беспокоиться о конкретных типах аргументов.
  • 0
    Не делайте объекты на вашей сцене ответственными за обнаружение столкновений. Либо иметь объект сцены, обнаруживающий их, и / или иметь автономные функции, такие как bool collision(const Circle&, const% Rectangle&)
Показать ещё 3 комментария
Теги:
oop
visitor-pattern
double-dispatch

1 ответ

1
Лучший ответ

То, что вы хотите, - это функция, которая отправляет не только по первому аргументу, но и по второму, т.е. двойную отправку. Это не поддерживается в C++, но может быть эмулировано.

class Collider {
public:
    virtual bool Collides(Collider const& x) const = 0;

private:
    virtual bool Collides(Point const& p) const = 0;
    virtual bool Collides(Line const& l) const = 0;
};

class Point: public Collider {
public:
    virtual bool Collides(Collider const& x) const {
        // here, the type of this is now Point
        // now, find out what x is and call the overload on this type
        x.Collides(*this);
    }

private:
    virtual bool Collides(Point const& p) const {
        // we now know that we are a point and checking vs. another point
    }

    virtual bool Collides(Line const& l) const {
        // we now know that we are a point and checking vs. a line
    }
};

class Line: public Collider {
public:
    virtual bool Collides(Collider const& x) const {
        // here, the type of this is now Line 
        x.Collides(*this);
    }

private:
    virtual bool Collides(Point const& p) const {
        // we now know that we are a line and checking vs. a point
    }

    virtual bool Collides(Line const& l) const {
        // we now know that we are a line and checking vs. another line
    }
};

Теперь, проверка двух объектов будет выполнять две рассылки:

Collider* p = new Point();
Collider* l = new Line();

p.Collides(l)
// first dynamically dispatches on p to call Point::Collides
// in Collides, this (which is p) now has the static Point. 
// now do the second dispatch on l and use *this as the parametet
// to find the overload.

Это, например, используется в шаблоне проектирования Visitor. Если ваш набор объектов исправлен, но вы ожидаете, что сделанные на них операции будут изменены или расширены, Visitor - хороший выбор.

  • 0
    Очень интересное решение! Спасибо!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню