我猜我已经问了几个相似的问题之前,我打周围的灌木丛中。我认为这是真正的问题,我不能躺着休息。

我处理一个 第三方图书馆, 有一个对象,不可能创建自己, b2Body.的 b2World化它.我不喜欢这个设计图案很多;我认为的 b2Body 应该能够独立存在的世界,然后被添加到全世界,当需要。无论如何,我的包裹 b2Body 与我自己的类类 Body, 因为我需要添加一些额外的东西给它无论如何。同样,我有一个 World 包装。现在我想我有3个选择:

  1. Body's需要构造一个指向 World 所以它可以完全实例(电话 b2World::CreateBody 里面的某个地方)--即有一个构造像 Body *b = new Body(world_ptr)
  2. Body 到一些 World::CreateBody 方喜欢怎样的图书馆已经不--即 Body *b = world.CreateBody(params);
  3. 重复的所有数据 b2Body 这样就可以使用它,但是你想要的,然后添加到全世界,它将开了'使用 b2Body 数据--即 Body b 和之后 world.addBody(b).

(1)和(2)的意思是,你不能有一个 Body 没有一个 World, 我可能不需要,但它可能是不错的选择[这样,我可以使用它作为模板,用于其他目的而这样的].不知道什么其他的优点和缺点。(3)似乎更好,但这是一个更多的工作来实现,这意味着我必须重复的大多数数据已经包含在 b2Body.

你有什么想法?我 CW 这只所以没有一个苦恼。


我仍然不能躺在这休息。这是什么每个选择会是这样的:

备选案文1: (什么我更喜欢)

World w;
Body b;
Fixture f;
b.addFixture(f);
w.addBody(b);

备选2: (在中间的某个地方)

World w;
Body b(w);
Fixture f(b);

备选案文3: (怎么Box2D它不会)

World *w = new World;
Body *b = w->CreateBody(args);
Fixture *f = b->CreateFixture(args);

备选方案2和3不是那么不同,但是它改变谁拥有控制创造的对象。

我将如何实际执行备选办法3有关系吗? World::CreateBody() 已经呼叫 b2World::CreateBody(args) 这电话 b2Body::b2Body() 和返回 b2Body 但从来不打电话 Body::Body(args) 这是一个问题。的 b2Body 会得到充分的初始化,但我的包皮已经没有地方做的事情...更具体地说,我怎么会写 World::CreateBody(const BodyDef &bd)?假设BodyDef继承b2BodyDef、身体从b2Body,世界从b2World,等等。

有帮助吗?

解决方案

我想,如果你要用一个第三方图书馆,你应该只争取它的设计如果你有一个更好的原因 哦,我不喜欢这个设计图太多.你的图书馆拥有一种方式做事的—很显然,通过使用工厂的目的和战斗将会增加你的代码复杂性,可能大大。

其他提示

听起来像b2World对象是工厂b2Body,因此提交人已经决定,一个b2Body已经没有意义没有它的世界。

我的第一反应会是这个接口,这样的生活。有你的世界,象是一个工厂于你的身体。所以这是接近的方法(1)除了你没有一个公共构造,世界对象具有makeBody()方法。

你认为尸体没有世界意义?如果是这样,也许你的发现是,一些集体方法可能是有用的,没有一个世界,我不清楚你如何实现它们-他们显然不能够实施通过b2Body,因为他不可能存在没有一个b2World.这样一种可能性是,你有一套配置的信息

 class Body {
        int howBig;
        String name;
        Flavour flavour;
        // and getter/setters
 } 

现在这些(或在东bgetters)清楚可能是有意义的有或没有的世界。

考虑到这一点,我想你可能会发现你的真正有两个"国家"的身体,一个当它是不相关联的世界,一个时就是如此。和实际的能力 不同的.因此,你实际上有两个接口。

因此,有一个IndependentBody类和一体类。世界工厂的方法可能有一个签名

World {

    Body makeBody(IndependentBody);

}

以下你的链接时,我看到 createBody 不返回b2Body,但一个 指针 一:

 b2Body* b2World::CreateBody  ( const b2BodyDef*  def );     

这可能是因为b2World

  1. 管理b2Body生(, 删除和存储它使用当B2World超出范围/本身就是删除),或

  2. 因为B2Wsorld需要保持针对b2Bodies, 例如 迭代过他们为完成某些B2World的功能。

我还注意到所有的需要(其他比 b2World)创建一个 b2Body 是指向 b2BodyDef.

所以如果你想要一个b2Body,没有连接到一个b2World,但可以在后来的一些被附加于一个,你为什么不能通过围绕b2BodyDefs,或针对他们?

可能会 创建一个薄包装为一个b2BodyDef, 例如,:

 class b2BodyDefWrapper {
   public const b2BodyDef& b2bodyDef;
   public b2BodyDefWrapper( const b2BodyDef& bodydef ) : b2bodyDef(bodydef) {}
   public const b2Body* reifyOn( b2World& world) const { 
     return world.CreateBody( b2bodyDef ) ;
   }
 }

注意,我可以将这种b2BodyDefWrapper多的世界,或以同样的世界上超过一次。

现在它可能是你可以做的事情到b2Body你不能做到一b2BodyDef,以便通过周围(可能包裹的)b2BodyDefs不会满足您的目的。在这种情况下,我可能使用该指令模式"附加"一个列表中的职能 b2BodyDefWrapper, 那将是"重播"在每个抛b2Body:

 class b2BodyDefWrapper {
   private std::vector<Command&> commandStack;
   public const b2BodyDef& b2bodyDef;
   public b2BodyDefWrapper( const b2BodyDef& bodydef ) : b2bodyDef(bodydef) {}
   public const b2Body* reify( b2World& world) const { 
     b2body* ret = world.CreateBody( &b2bodyDef ) ;
     for (int i=0; i< commandStack.size(); i++) {
        v[i].applyTo( ret ) ;
     }
     return ret;
   }

   public void addCommand( const Command& command ) {
      commandStack.push_back( command );
   }
 }

哪里 Command 是一个抽象的基类函,像这样:

  class Command {
     virtual ~Command() {}
     virtual void applyTo( b2Body* body ) = 0 ;
  }

与具体的子类:

 class ApplyForce : public Command {
   private const b2Vec2& force;
   private const b2Vec2& point;
   ApplyForce(const b2Vec2& f, const b2Vec2& p) : force(f), point(p) {}
   virtual void applyTo( b2Body* body ) {
      body->ApplyForce( force, point ) ;
   }
 }

然后我可以用我的包装这样的:

extern b2BodyDef& makeb2BodyDef();
b2BodyDefWrapper w( makeb2BodyDef()  ) ; 
ApplyForce a( ..., ... );
w.addCommand( a ) ;
...
b2World myworld;
b2World hisWorld;
w.reifyOn( myWorld ) ;
w.reifyOn( hisWorld) ;

注意,我已经离开了一些细节,主要是关于物体的所有权和存储管理,并要求删除关于CommandStacks;我也没有遵循规则的三个在我的草图的课程。你可以填补这些你喜欢的。

我也有留出任何规定调用,从命令,b2Body功能返回的其他无效和回这些价值观;你或许可以涵盖这种(如果您需要)通过具有ApplyTo返回联盟的某种。

更根本的是,我没有涵盖如何一个具体的命令可以提供其返回值(如果有)到另一个具体的命令。一个完整的解决方案将有不一矢量的命令,但一个 n元树他们,那里的儿童的命令,首先应用,以及他们的返回值(如果有的话)是提供给他们的父的命令。无论你 需要 这种复杂性是一个问题,我显然不能回答。(我已经给出一个相当详细的回答,认为我是既没有得到支付这个,我也不是越来越声誉点,由于你的社会Wiki就这个问题。)

我同意,你不该战斗的设计的一个第3方图书馆,你使用。走这样的路径可能会导致大量的未来的问题。

通过寻找"下面"和创造包装,你可能被锁定的行为的第3党库的方式在当前实施的行为。

会发生什么,如果一个未来的版本的API保持不变,但基本义改变?

突然,一切都是打破从一点看你的包装。

只是我的0.02.

其中一个原因,box2D使用bodyDef对象建造b2Body目的是使得可以重新使用的清晰度,以创建多个机构。代码,如:

b2BodyDef myDef;
// fill out def

for (int i=0; i < 100; ++i) {
   for (int j=0; j < 100; ++j) {
      myDef.x = i;
      myDef.y = j
      b2Body* body = world.CreateBody(myDef)
   }
}

是一个非常有效和紧凑的方式创建多的对象,用相同的特性。它不必在同样的循环,你可以保持清周围的物体作为元数据,并创建机构从它们的需要。

不要打它,因为它是有原因的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top