我正在为圆形和正方形制作一个简单的 2D 物理引擎。我有一个主体类,我希望在创建时为其提供一个形状的 unique_ptr 实例。形状可以是圆形或盒子。身体是我想放入游戏循环以检查碰撞的对象。在检查碰撞时,我对与形状相关的数据感兴趣。一个非常原始的例子如下所示:
#include <iostream>
#include <memory>
struct Shape
{
virtual float calculateArea() const = 0;
};
struct Circle: public Shape
{
const float m_radius;
Circle(float radius) : m_radius(radius) {}
float calculateArea() const {return m_radius*m_radius*3.14;}
};
struct Square: public Shape
{
const float m_side_length;
Square(float side_length) : m_side_length(side_length) {}
float calculateArea() const {return m_side_length*m_side_length;}
};
struct Body
{
Body(std::unique_ptr<Shape>& shape): m_shape(std::move(shape)) {}
std::unique_ptr<Shape> m_shape;
};
int main()
{
std::unique_ptr<Shape> circ = std::make_unique<Circle>(5.0);
std::unique_ptr<Shape> square = std::make_unique<Square>(10.0);
std::shared_ptr<Body> body1 = std::make_shared<Body>(circ);
std::shared_ptr<Body> body2 = std::make_shared<Body>(square);
}
本质上,我想知道是否有办法访问形状的半径或形状的边长。我可以看到类似的东西
body1->shape->m_radius
或 body2->shape->m_side_length
不起作用,但我真的想找到一个解决方案,可以将我的形状分组为通用形状类,并且我仍然能够通过 body 类访问它们的独特功能。顺便说一句,这是为了碰撞检测。
我看到了一些相关的帖子,例如这里:通过基类指针C++访问派生类的成员,但总体问题与我的略有不同,而且问题相当老了。
感谢您的帮助 - 希望它有意义!
你说
我想知道是否有办法访问形状的半径或形状的边长。
是的,有多种方法可以获取派生类成员,但我不建议采用这种方法来解决您的编程问题。它很快就会长毛。
假设
shape
有 N 个子类。给定两个 shape
对象,如果碰撞检测逻辑取决于对象类型,则您将需要 NC2 函数来覆盖功能。
实现此目的的一种方法是拥有检测逻辑类/函数的注册表。您可以在程序启动时向注册表添加条目。您将需要添加代码来查找两个对象类型的类/函数的注册表,然后调用这些函数。在实现检测逻辑的类/函数中,使用
dynamic_cast
来获取特定对象类型并从特定对象类型中获取必要的数据是公平的。
这是其中的概述。
class CollisionDetector
{
virtual bool detectCollision(
shape const& shape1,
shape const& shape2) const;
};
class CollisionDetectorRegistry
{
using CollisionDectorBuilder = CollisionDetector*(void);
static void registerCollisionDetector(
std::string const& shapeType1,
std::string const& shapeType2,
CollisionDectorBuilder builder);
static CollisionDetector* getCollisionDetector(
shape const& shape1,
shape const& shape2);
};
class CircleCircleCollisionDetector : public CollisionDetector
{
virtual bool detectCollision(
shape const& shape1,
shape const& shape2) const;
static CollisionDetector* build();
}
class CircleSquareCollisionDetector : public CollisionDetector
{
virtual bool detectCollision(
shape const& shape1,
shape const& shape2) const;
static CollisionDetector* build();
}
// Add the following in some place that is executed at start up time.
CollisionDetectorRegistry::registerCollisionDetector(
"circle", "circle", CircleCircleCollisionDetector::build);
CollisionDetectorRegistry::registerCollisionDetector(
"circle", "square", CircleSquareCollisionDetector::build);
// Shape-independent function for detecting collision
bool detectCollision(
shape const& shape1,
shape const& shape2)
{
CollisionDetector* detector =
CollisionDetectorRegistry::getCollisionDetector(shape1, shape2);
if ( detector == nullptr )
{
// Throw an execption.
}
else
{
return detector->detectCollision(shape1, shape2);
}
}
我意识到你需要填补一些空白,但我假设你可以做到。