1
votes

Until lately I've been just changing the x coordinate of my sprite on each update and I was happy with it. But yesterday when being in the debugDraw mode, I found out that after certain speed physics body wouldn't align correctly with the sprite ,like this: enter image description here Later I got told that, (by Birkemose in cocos2d forum) the preferred way to move a physics body from A to B is to apply impulse to it. But I have no idea how to achieve constant speed this way. This is the code I used to move it without applying any impulse:

-(void)update:(CCTime)delta{
    rollingHero.position=ccp(rollingHero.position.x+scrollSpeed*delta,    
                         rollingHero.position.y);
    physicsNode.position=ccp(physicsNode.position.x-scrollSpeed*delta,
                         physicsNode.position.y);
}

So to create a feeling of moving I scroll the physics node and the hero in opposite directions with the same scrolling speed. I tried lots of different variants of applying impulse, but I never got it moving with constant speed. The speed accelerates and the hero gets offscreen. I would appreciate it very much if someone would post a sample code.

1

1 Answers

5
votes

The reason impulse isn't working to keep your character at a constant speed is because impulse translates directly into a change in momentum (and thus a change in velocity). So if you were to try to maintain a constant velocity through impulse, you would have to check your sprite's velocity first, and although you could get pretty close to a constant velocity, it wouldn't be truly constant.

static const float kRollingHeroMoveSpeed     = 10.f;
static const float kRollingHeroAccelConstant = 10.f;

-(void)update:(CCTime)delta {

    // check velocity of sprite
    if(_rollingHero.physicsBody.velocity.x < kRollingHeroMoveSpeed) {

        // if velocity is under limit, push character
        [_rollingHero.physicsBody applyImpulse:ccp(kRollingHeroAccelConstant, 0)];
    }
}

The better way to do this is to step into the C level of the Chipmunk2D physics engine that powers Cocos2D physics.

-(void)onEnter {
    [super onEnter];

    // tell physics engine to use our C function to update physics body
    _rollingHero.physicsBody.body.body->velocity_func = playerUpdateVelocity;
}

static void playerUpdateVelocity(cpBody *body, 
                                 cpVect gravity, 
                                 cpFloat damping, 
                                 cpFloat dt) {

    // check validity of cpBody
    cpAssertSoft(body->m > 0.0f && body->i > 0.0f, "Body's mass and moment must be positive to simulate. (Mass: %f Moment: %f)", body->m, body->i);

    // update velocity and angular velocity
    body->v = cpvadd(cpvmult(body->v, damping), cpvmult(cpvadd(gravity, cpvmult(body->f, body->m_inv)), dt));
    body->w = body->w*damping + body->t*body->i_inv*dt;

    // reset force vector
    body->f = cpvzero;
    // reset torque
    body->t = 0.0f;

    // set body's velocity to desired velocity
    body->v.x = kRollingHeroMoveSpeed;
}

Here's cpBody.h on Github.