Trung Tran
Trung Tran

Reputation: 229

Rotate while jumping - iOS game

I am making an iOS game that a box will rotate while jumping (like this: http://www.lessmilk.com/games/3/). I have tried many ways and one of them seems acceptable:

When touch began, I run this code:

[_box.physicsBody applyImpulse:ccp(0, 5000)];

CCActionRotateBy *r2 = [CCActionRotateBy actionWithDuration:0.9f angle:360.f];
CCActionSequence *moveSequence = [CCActionSequence actionWithArray:@[r2]];
[_box runAction:moveSequence];

This is quite good but I later figured out there was performance problem. For unknown reason, while the box is in the air and it is rotating, the frame seems decreased (or I feel so because the animation is not smooth).

Does anyone know what the problem is or have better idea to implement this? Thank you,

Upvotes: 0

Views: 148

Answers (2)

cc.
cc.

Reputation: 3051

Typically, you don't want to both have your sprites being driven by physics AND by direct manipulation. You're basically fighting with the physics engine over control of the sprite.

You might consider, instead of applying physics to the box, just doing regular frame updates to move and rotate the sprite instead of trying to mix physics and actions. Most physics engines have a way to have physics objects that are moved around like puppets and which still trigger collisions properly, but which aren't directly controlled by the physics engine. Look into that, and you might have better results.

EDIT:

To achieve the motion you want, what I'd do is just animate directly using the update() function (or whatever the Cocos2D equivalent is - I'm more familiar with SpriteKit at the moment). (Untested code below.)

You'd want to start with a constant x velocity in points/second, say, 100. In your update() function, you take the delta since the last update() function, in seconds, and multiply it by that velocity to get the change in x position:

float newX = oldX + delta * xVelocity;

To do the jumping, you'd want to keep an "isJumping" BOOL, and if it's YES, add a parabolic Y distance and rotate the box. The easy way to do this is to just ramp from 0 to 1 across whatever X distance you want the jump to be, and map that onto the parabolic motion.

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;
    }
}

Now you have the motion you want. All that's left is collision detection, which you can do in exactly the same way as you did before. Just disconnect the box from being driven by the physics (it looks like, using Box2D, that you would use a "kinematic" body instead of a "dynamic" body). You'll still get your collision messages as before, but you'll control the behavior of the box directly instead of relying on physics or actions.

Upvotes: 2

Rajeev
Rajeev

Reputation: 585

Since your sprite is associated with physics and you are applying Linear impulse for sprite movement.So, instead of using animation for rotating the sprite, you can try to rotate the sprite using physics as well. Try applying angular velocity to the sprite as:

_box.physicsBody.angularVelocity = someConstantValue;

I hope you will get better performance as well as smoothness.

Upvotes: 3

Related Questions