在Box2d / Cocos2d中为iPhone应用漩涡/漩涡效果

时间:2012-05-20 05:21:27

标签: objective-c math cocos2d-iphone box2d

我使用Nick Vellios' tutorial用Box2D对象创建径向引力。我在SO上知道Make a Vortex,但我无法弄清楚如何在我的项目中实现它。

我制作了一个涡旋物体,它是一个Box2D circleShape传感器,以一致的角速度旋转。当其他Box2D物体接触到这个涡旋物体时,我希望它们以与涡旋相同的角速度旋转,逐渐靠近涡旋的中心。此刻物体被吸引到涡旋的中心,但是它将直接朝向涡旋的中心,而不是像我想要的那样慢慢地旋转它。它也会以与涡旋相反的方向以及涡旋的旋转方向行进。

给定一个漩涡和一个box2D体,如何设置box2d体随着它被“吸入”而随着旋涡旋转。

当我像这样创建漩涡时,我设置旋涡的旋转:

b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.angle = 2.0f;
bodyDef.angularVelocity = 2.0f;

根据Nick Vellios' sample code,我正在应用径向引力。

-(void)applyVortexForcesOnSprite:(CCSpriteSubclass*)sprite spriteBody:(b2Body*)spriteBody withVortex:(Vortex*)vortex VortexBody:(b2Body*)vortexBody vortexCircleShape:(b2CircleShape*)vortexCircleShape{

    //From RadialGravity.xcodeproj
    b2Body* ground = vortexBody;
    b2CircleShape* circle = vortexCircleShape;
    // Get position of our "Planet" - Nick
    b2Vec2 center = ground->GetWorldPoint(circle->m_p);
    // Get position of our current body in the iteration - Nick
    b2Vec2 position = spriteBody->GetPosition();
    // Get the distance between the two objects. - Nick
    b2Vec2 d = center - position;
    // The further away the objects are, the weaker the gravitational force is - Nick
    float force = 1 / d.LengthSquared(); // 150 can be changed to adjust the amount of force - Nick
    d.Normalize();
    b2Vec2 F = force * d;
    // Finally apply a force on the body in the direction of the "Planet" - Nick
    spriteBody->ApplyForce(F, position);
    //end radialGravity.xcodeproj


}

更新我认为iForce2d已经给了我足够的信息以便我继续前行,现在它只是在调整。除了上面的代码之外,这就是我现在正在做的事情。发生的事情是身体获得足够的速度来很好地退出涡旋的重力 - 在某个地方我需要检查速度是否低于这个数字。我有点担心我现在没有考虑物体的质量。

b2Vec2 vortexVelocity = vortexBody->GetLinearVelocityFromWorldPoint(spriteBody->GetPosition() );

b2Vec2 vortexVelNormal = vortexVelocity;
vortexVelNormal.Normalize();
b2Vec2 bodyVelocity = b2Dot( vortexVelNormal, spriteBody->GetLinearVelocity() ) * vortexVelNormal;

//Using a force
b2Vec2 vel = bodyVelocity;
float forceCircleX =    .6 * bodyVelocity.x;
float forceCircleY =    .6 * bodyVelocity.y;

spriteBody->ApplyForce( b2Vec2(forceCircleX,forceCircleY), spriteBody->GetWorldCenter() );

2 个答案:

答案 0 :(得分:2)

听起来你只需要根据身体当前点的漩涡方向施加另一种力。您可以使用b2Body :: GetLinearVelocityFromWorldPoint来查找世界任何位置的涡旋速度。来自Box2D来源:

/// Get the world linear velocity of a world point attached to this body.
/// @param a point in world coordinates.
/// @return the world velocity of a point.
b2Vec2 GetLinearVelocityFromWorldPoint(const b2Vec2& worldPoint) const;

那就是:

b2Vec2 vortexVelocity = vortexBody->GetLinearVelocityFromWorldPoint( suckedInBody->GetPosition() );

一旦知道了目标速度,就可以计算从当前速度到所需速度需要多大的力。这可能会有所帮助:http://www.iforce2d.net/b2dtut/constant-speed

该链接中的主题仅讨论一维情况。对于你的情况,如果你将吸入体的当前速度投影到vortexVelocity矢量上,它也基本上是1维的:

b2Vec2 vortexVelNormal = vortexVelocity;
vortexVelNormal.Normalize();
b2Vec2 bodyVelocity = b2Dot( vortexVelNormal, suckedInBody->GetLinearVelocity() ) * vortexVelNormal;

现在bodyVelocity和vortexVelocity将处于同一方向,您可以计算要应用的力量。然而,如果你只是施加足够的力来完全匹配涡流速度,那么被吸入的体内可能会围绕涡旋进入轨道并且实际上从未被吸入。我想你会想要使力量相当于此,并且我也会根据重力强度将其缩小,否则一旦它接触到涡流的外边缘,被吸入的体就会被侧向抛弃。可能需要进行大量调整才能获得您想要的效果。

编辑:

你应用的力应该基于当前速度(bodyVelocity)和所需速度(vortexVelocity)之间的差值,即。如果身体已经随着涡旋移动,那么你不需要施加任何力。看一下上面给出的链接中标题为“使用力”的子节中的最后一个代码块。如果用bodyVelocity和vortexVelocity向量的大小替换'vel'和'desiredVel',那么最后三行几乎可以满足你的需要:

float desiredVel = vortexVelocity.Length();
float currentVel = bodyVelocity.Length();
float velChange = desiredVel - currentVel;
float force = body->GetMass() * velChange / (1/60.0); //for a 1/60 sec timestep
body->ApplyForce( b2Vec2(force,0), body->GetWorldCenter() );

但是请记住,这可能会将身体放入轨道,因此在某个地方您可能希望减小所施加力的大小,例如。将'desiredVel'减少一定百分比,将'力'减少一定百分比等。如果你也可以缩小力,使其在涡旋的外缘处为零,那么看起来可能会更好。

答案 1 :(得分:0)

我有一个项目,我的小行星围绕一个中心点旋转(有些东西在它们之间跳跃......这是另一个点)。

  • 他们通过b2DistanceJoints连接到“中心”身体。
  • 您可以控制关​​节长度,使它们向内(或向外)缓慢旋转。这使您可以找到谷物控制而不是平衡力控制,这可能很困难。
  • 您还应用切向力使它们绕中心旋转。
  • 通过应用不同(或随机变化)的切向力,你可以制作 撞到对方等等。

我发布了一个更完整的答案here