物理引擎的继承/接口决策

Bin*_*ngo 6 c++ inheritance game-physics

这适用于在MinGW/Windows上使用SDL的小型游戏项目.

我正在研究一个物理引擎,我的想法是拥有一个Physics::Object所有物理对象应该从中得到的东西,并且它用全局Physics::System类(它是一个单独的模式)注册自己,这样用户就不需要跟踪哪些对象了包含在物理计算中,只需要调用一个函数Physics::System::PerformTimestepCalculation(double dt).

这工作正常,我甚至使用单个派生类实现它Physics::Circle,这是一个2d圈.我对预测性碰撞检测非常满意,即使我仍然需要优化它.

无论如何,当我开始添加其他原语以包含在计算中时,我遇到了麻烦,例如line.将Physics::System::PerformTimestepCalculation(double dt)成为与将呼叫散落Object::GetID()或类似的功能(5办法避免的dynamic_cast <>),但我觉得脏.

我做了一些阅读并意识到我的层次结构中的元素不可替代(即两个圆之间的碰撞在两条线的碰撞之间非常不同).

我喜欢我Physics::ObjectsSystem课堂上"自我注册"的方式,所以它们会自动包含在计算中,我真的不想失去这个.

必须有一些其他合理的设计路径.我怎样才能更好地重新设计东西,以便不可替代的对象不会妨碍?

编辑FYI: 最后,我已经打破了实体和形状属性,类似于在接受的答案中描述的方式,类似于实体 - 组件 - 系统模型.这意味着我仍然有yuk逻辑"这是一个圆圈还是一条线,是一条线还是一条圆?",但我不再假装多态在这里帮助我.这也意味着我使用某种工厂,可以同时发生多个计算世界!

Dan*_*n O 5

最成功的公共物理引擎对"模式"或"面向对象设计"并不十分重视.

这是一个支持我的,无可否认的大胆断言的纲要:

花栗鼠 - 写在C,足够说.

Box2d - 用C++编写,这里有一些多态.有一些形状的层次结构(基类b2Shape)和一些虚函数.尽管如此,抽象漏洞就像一个筛子一样泄漏,你会在整个源代码中找到很多关于叶子类的强制转换.还有一个"联系人"的层次结构,这证明更成功,虽然使用单个虚函数,在没有多态的情况下重写它是很简单的(我相信,花栗鼠使用函数指针).b2Body是用于表示刚体的类,它是非虚拟的.

Bullet - 用C++编写,用于大量游戏.大量的功能,大量的代码(相对于其他两个).实际上有一个基类,刚体和软体表示扩展,但只有一小部分代码可以使用它.大多数基类的虚函数与序列化(保存/加载引擎状态)有关,剩下的两个虚函数软体无法实现一个TODO通知我们需要清理一些hack.在物理引擎中并不完全是对多态性的认可.

这是很多的话,我甚至没有真正开始回答你的问题.我想要回家的是,多态性不是在现有物理引擎中有效应用的东西.这可能不是因为作者没有"得到"OO.

所以无论如何,我的建议是:你的实体类沟通多态.你不会最终得到100种不可能在以后重构的不同类型,你的物理引擎的形状数据将是相当同质的(凸多边形,盒子,球体等),你的实体数据很可能是甚至更均匀(可能只是开始的刚体).

我觉得你做的另一个错误只是支持一个Physics :: System.能够独立于彼此模拟身体(例如,对于双人游戏)具有实用性,并且最简单的方法是支持多个Physics :: Systems.

考虑到这一点,最简洁的"模式"将是工厂模式.当用户想要创建一个刚体时,他们需要告诉Physics :: System(充当工厂)为他们做这件事,所以在你的Physics :: System中:

// returning a smart pointer would not be unreasonable, but I'm returning a raw pointer for simplicity:
rigid_body_t* AddBody( body_params_t const& body_params );
Run Code Online (Sandbox Code Playgroud)

并在客户端代码中:

circle_params_t circle(1.f /*radius*/);
body_params_t b( 1.f /*mass*/, &circle /*shape params*/, xform /*system transform*/ );
rigid_body_t* body = physics_system.AddBody( b );
Run Code Online (Sandbox Code Playgroud)

Anyhoo,有种咆哮.希望这是有帮助的.至少我想指向box2d.它是用一种非常简单的C++方言编写的,其中应用的模式将与您的引擎相关,无论是3D还是2D.