Я пишу простой игровой движок и после большого переосмысления / рефакторинга я остановился на некой компонентно-ориентированной архитектуре (не только ECS, но и больше не основанной на наследовании). Так что все в моем мире - это сущность, и у каждой сущности есть куча компонентов. Каждая система / подсистема в моей игре сканирует сущность на наличие ряда интересующих ее компонентов и выполняет некоторые соответствующие вычисления.
Пока все хорошо. Базовую архитектуру движка можно увидеть здесь :
Теперь, у каждой сущности, с которой можно столкнуться, есть компонент столкновения (наряду с компонентами положения / движения / твердого тела), поэтому физическая система должна получить этот компонент и использовать его для подачи своих алгоритмов обнаружения столкновений, чтобы создать контакт данные, которые будут использоваться для разрешения столкновения.
Я застрял в следующей проблеме: алгоритмы обнаружения столкновений имеют дело с различными геометриями: ящиками, сферами, плоскостями и лучами (на данный момент), но я не хочу по крайней мере иметь компонент сферы столкновения и компонент столкновения коробки Я не хочу, чтобы они были не связаны, но я бы хотел, чтобы они имели общий базовый класс.
class Sphere
{
public:
Sphere(float radius);
~Sphere();
float GetRadius() { return mRadius; }
private:
float mRadius;
};
class Box : public BoundingVolume
{
public:
Box(const XMFLOAT3 &halfSize);
~Box();
XMFLOAT3 const &GetHalfSize() const { return mHalfSize; }
private:
XMFLOAT3 mHalfSize;
};
Очевидно, что каждый компонент имеет свой интерфейс (боксы имеют половинные размеры, сферы имеют радиус и т. Д.), И различные функции обнаружения столкновений работают с каждым из них очень по-разному (бокс-бокс, бокс-сфера, сфера-сфера). .).
void CollisionSystem::BoxAndBoxCollision(const Box &box1, const Box &box2)
{
// contact data
XMFLOAT3 contactPoint;
XMFLOAT3 contactNormal;
float minOverlap = 100.0f;
// get axes for SAT test
std::vector<XMFLOAT3> axes = GetSATAxes(box1, box2);
int axisIndex = 0;
int index = 0;
for (XMFLOAT3 axis : axes)
{
if (XMVectorGetX(XMVector3Length(XMLoadFloat3(&axis))) < 0.01f)
{
index++;
continue;
}
float overlap = PerformSAT(axis, box1, box2);
if (overlap < 0) // found separating axis - early out
return;
if (overlap < minOverlap)
{
minOverlap = overlap;
axisIndex = index;
}
index++;
}
// other collision detection/generation code.....
// store contact
mContacts.push_back(new Contact(box1->GetRigidBody(), box2->GetRigidBody(), contactPoint, contactNormal, minOverlap, coefficientOfRestitution));
}
Так, как я могу решить это изящным и надежным способом?