在cocos2d中,您可以轻松使用CCSprites并以各种方式移动它们。最重要的是 - 他们可以放松身心。对于大多数游戏来说,这对于平稳运动等是理想的。
id action = [CCMoveTo actionWithDuration:dur position:pos];
move = [CCEaseInOut actionWithAction:action rate:2];
[self runAction: move];
当移动box2d体时,附加到它的精灵会在box2d step()之后更新。移动精灵然后更新正文不是一个选项,因为它完全违背了物理框架的目的。
所以我成功实现的另一个选项是通过将精灵本身视为一个力学实体来计算精灵的位移,速度和加速度。每次我在精灵上调用我的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)];
}
结果是辉煌的,b2体的平滑缓和运动移动到你想要它的地方,而不是用它自己的任何力量,而是复制CCSprite的那个并复制它的运动。由于它是所有力,因此在与其他b2Body物体碰撞时不会引起抖动和扭曲。如果有人有任何其他方法可以做到这一点,请发一个答案。谢谢!
答案 0 :(得分: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。
我希望我理解你的问题,答案对你有帮助......