5

在 cocos2d 中,您可以在 CCSprites 中缓和并以各种方式移动它们。最重要的是 - 他们可以缓进/缓出。对于大多数游戏来说,这对于平滑移动等来说是可取的。

id action = [CCMoveTo actionWithDuration:dur position:pos];
move = [CCEaseInOut actionWithAction:action rate:2];
[self runAction: move];

移动 box2d 主体时,附加到它的精灵在 box2d step() 之后更新。移动精灵然后更新身体在这里不是一个选择,因为它完全违背了物理框架的目的。

因此,我已经成功实现的另一个选项是通过将精灵本身视为一个力学实体来计算精灵的位移、速度和加速度。每次我在 sprite 上调用我的 update() 以便角色可以决定移动的位置等时,我的超类也会存储之前的位置和速度。这些通过除以 PTM_RATIO 存储为符合 box2d 的值。

在 CCSprite 的子类中,称为 FMSprite:

-(CGPoint) displacement {
    return ccpSub(self.position, lastPos);
}

-(b2Vec2) getSpriteVelocity:(ccTime)dt {
    return b2Vec2(self.displacement.x / dt / PTM_RATIO,
                  self.displacement.y / dt / PTM_RATIO);
}

-(b2Vec2) getSpriteAccel:(ccTime)dt {
    b2Vec2 currVel = [self getSpriteVelocity:dt];
    if (dt == 0) {
        return b2Vec2(0,0);
    } else {    
        float accelX = (currVel.x - lastVel.x)/dt;
        float accelY = (currVel.y - lastVel.y)/dt;
        return b2Vec2(accelX, accelY);
    }
}

// This is called each update()
-(void) updateLast:(ccTime)dt {
    // MUST store lastVel before lastPos is updated since it uses displacement
    lastVel = [self getSpriteVelocity:dt];
    lastPos = ccp(self.X, self.Y);
}

// Leave this method untouched in subclasses
-(void) update:(ccTime)dt {
    [self updateObject:dt];

    // Store previous update values
    [self updateLast:dt];
}

// Override this method in subclasses for custom functionality
-(void) updateObject:(ccTime)dt {

}

然后,我将“FMSprite”子类化为“FMObject”,其中存储了 b2Body 等。

为了移动身体,我必须首先移动一个精灵并跟踪它的加速度,通过它我可以找到跟随精灵运动所需的力(使用质量)。由于我无法移动对象的精灵(与身体同步),我制作了另一个名为“信标”的精灵,将其作为子对象添加到对象中,然后移动它。然后我们需要做的就是使用我之前提到的力使 box2d 主体的位置与这个信标精灵同步。

-(void) followBeaconWithDelta:(ccTime)dt {
    float forceX = [beacon getSpriteAccel:dt].x * self.mass;
    float forceY = [beacon getSpriteAccel:dt].y * self.mass;
    [self addForce:b2Vec2(forceX, forceY)];
}

结果非常出色,b2body 的平滑缓动运动可以随心所欲地移动,无需使用任何自身的力,而是复制 CCSprite 的力并复制其运动。由于都是力,所以在与其他 b2Body 对象碰撞时不会引起抖动和失真。如果有人有任何其他方法可以做到这一点,请发布答案。谢谢!

4

1 回答 1

4

我所做的与您的不同,但也可以像 CCSprite 对象一样移动 Box2d 身体,甚至使用 CCAction。最重要的是创建一个包含 ccSprite 和 b2body 的对象。

@interface RigidBody : CCNode {
    b2Body *m_Body;
    CCSprite *m_Sprite;
}

然后,重写 setPosition 方法。

-(void)setPosition:(CGPoint)position
{
    CGPoint currentPosition = position_;
    b2Transform transform = self.body->GetTransform();
    b2Vec2 p = transform.p;
    float32 angle = self.body->GetAngle();
    p += [CCMethod toMeter:ccpSub(position, currentPosition)];
    self.body->SetTransform(p, angle);  
    position_ = position;
}

setPosition 方法计算位置变化量,并将其设置到 b2body。

我希望我能理解你的问题,答案对你有帮助......

于 2012-05-08T09:07:48.517 回答