在cocos2d中,您可以轻松使用CCSprites并以各种方式移动它们。最重要的是 - 他们可以缓入/缓出。对于大多数游戏来说,这对于平滑移动等是可取的。
id action = [CCMoveTo actionWithDuration:dur position:pos];
move = [CCEaseInOut actionWithAction:action rate:2];
[self runAction: move];
当移动 box2d 主体时,附加到它的精灵会在 box2d 步骤()之后更新。移动精灵然后更新身体在这里不是一个选择,因为它完全违背了物理框架的目的。
因此,我已经成功实现的另一个选项是通过将精灵本身视为力学实体来计算精灵的位移、速度和加速度。每次我在精灵上调用 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物体碰撞时不会造成抖动和扭曲。如果有人有任何其他方法可以做到这一点,请发布答案。谢谢!