我正在使用工厂为物理引擎创建Shape
个实例。每个形状的大小在构建时间之前是未知的,因此使用工厂代替堆栈存储器+克隆。然后将Shape
提供给物理Scene
以创建Body
:
// Sphere derives from Shape
Sphere *s = Scene.CreateSphere( radius );
// Construct a rigid body with a certain shape
Body *b = Scene.CreateBody( s );
问题:我希望每个Shape
在任何给定时间只与一个Body
相关联。我需要禁止用户这样做:
Body *b1 = scene.CreateBody( );
Body *b2 = scene.CreateBody( );
Shape *s = scene.CreateBox( 1.0f, 1.0f, 1.0f );
b1->AddShape( s );
b2->AddShape( s ); // bad
其他信息:最好避免对指针唯一性进行昂贵的性能检查,因为这里的性能非常重要。但是,在调试模式下,可以接受错误检查的性能命中。
能够与创建实体分开构造形状非常重要,因为多个形状可以是聚合刚体的一部分:
Body *b = Scene.CreateBody( );
b->AddShape( shapePtr1 );
b->AddShape( shapePtr2 );
Shape
个实例也应该能够在运行时从一个Body
转移到另一个;
Body *b1, b2; // initialized elsewhere
Shape *s; // initialized elsewhere, is attached to b1
b1->RemoveShape( s );
b2->AddShape( s );
也许我应该采用不同的api设计?也许克隆可以某种方式使用?
答案 0 :(得分:1)
首先,让所有Create*()
函数都采用Body
参数,作为依赖性反转的形式。
然后,您只能为单个Shape
创建Body
。如果您尝试在已有形状的Shape
上创建Body
,也可以断言或以其他方式输出错误。
您可以通过简单要求目标Shape
尚未附加Body
来支持移动Shape
个对象。没有DetachShape
,这将允许“悬空”形状,而只是MoveShapeTo
和ReleaseShape
。或者,只需使用某种多样的智能指针,以确保正确清理“悬垂”形状,如果这是您的主要担心。
答案 1 :(得分:1)
将Body::AddShape(...)
设为私有,并删除带有Shape*
参数的ctor。
void Body::AddSphere(float radius)
{
AddShape(Scene.CreateSphere(radius));
}
void Body::transferShape(Shape *s, Body &B2)
{
RemoveShape( s );
B2.AddShape( s );
}
// Construct a rigid body with no Shapes (yet)
Body *b = Scene.CreateBody();
// Give it a Sphere
b->AddSphere(radius);
// Transfer it to another body:
Body *b2 = Scene.CreateBody();
Shape *s = b->GetShapePointerSomehow();
b->transferShape(s, *b2);
请注意,如果不将其从Shape
移除,则无法将Body
添加到Body
。没有外部代码可以导致两个Bodies包含相同的Shape
。