通常,您不希望您的精灵既由物理驱动又由直接操作驱动。您基本上是在与物理引擎争夺精灵的控制权。
您可能会考虑,而不是将物理应用到盒子上,只是定期更新帧以移动和旋转精灵,而不是尝试混合物理和动作。大多数物理引擎都有办法让物理对象像木偶一样四处移动,并且仍然可以正确触发碰撞,但不受物理引擎直接控制。研究一下,你可能会得到更好的结果。
编辑:
为了实现你想要的动作,我要做的就是直接使用 update() 函数(或任何 Cocos2D 等价物——我现在更熟悉 SpriteKit)来制作动画。(下面的未经测试的代码。)
您希望以点/秒为单位的恒定 x 速度开始,例如 100。在您的 update() 函数中,您获取自上次 update() 函数以来的增量(以秒为单位),并将其乘以该速度以获得x位置的变化:
float newX = oldX + delta * xVelocity;
要进行跳跃,您需要保留“isJumping”BOOL,如果是,则添加抛物线 Y 距离并旋转框。执行此操作的简单方法是从 0 到 1 跨越您希望跳跃的任何 X 距离,并将其映射到抛物线运动上。
float newY = 0; // zero is the ground plane
if (self.isJumping) {
self.jumpRamp += delta * xVelocity / jumpLength;
if (self.jumpRamp > 1.0) {
self.zRotation = self.jumpRamp * M_PI;
// Map the jump ramp onto (-1,1), and then square it to get parabolic motion
// Since the jump ramp goes from (0,1), we subtract .5 and multiply by 2
// to get a range from (-1, 1). Then we square that.
float parabolic = ((self.jumpRamp - .5) * 2) * (self.jumpRamp - .5) * 2));
// This yields (0,1), with the parabola pointing up. We need to
// invert it, scale it, and move it up so the end points are on the "floor".
newY = self.maxJumpHeight * (1.0 - parabolic);
} else {
self.isJumping = NO;
self.zRotation = 0;
self.jumpRamp = 0;
}
}
现在你有了你想要的动作。剩下的就是碰撞检测,您可以按照与以前完全相同的方式进行检测。只需断开盒子与物理驱动的连接(看起来,使用 Box2D,您将使用“运动”体而不是“动态”体)。您仍然会像以前一样收到碰撞消息,但您将直接控制盒子的行为,而不是依赖物理或动作。