b2Body moves without stopping

Posted by SentineL on Game Development See other posts from Game Development or by SentineL
Published on 2012-02-29T10:52:07Z Indexed on 2012/04/05 11:44 UTC
Read the original article Hit count: 250

Filed under:
|

I got a quite strange bug. It is difficult to explain it in two words, but i'll try to do this in short.

  • My b2Body has restitution, friction, density, mass and collision group.
  • I controlling my b2Body via setting linear velocity to it (called on every iteration):

    (void)moveToDirection:(CGPoint)direction onlyHorizontal:(BOOL)horizontal { b2Vec2 velocity = [controlledObject getBody]->GetLinearVelocity();

        double horizontalSpeed = velocity.x + controlledObject.acceleration * direction.x;
    
        velocity.x = (float32) (abs((int) horizontalSpeed) < controlledObject.runSpeed
                ? horizontalSpeed
                : controlledObject.maxSpeed * direction.x);
    
        if (!horizontal)
        {
            velocity.y = velocity.y + controlledObject.runSpeed * direction.y;
        }
    
        [controlledObject getBody]->SetLinearVelocity(velocity);
    }
    
  • My floor is static b2Body, it has as restitution, friction, density, mass and same collision group

  • in some reason, I'm setting b2Body's friction of my Hero to zero when it is moving, and returning it to 1 when he stops.

  • When I'm pushing run button, hero runs. when i'm releasing it, he stops. All of this works perfect.

  • On jumping, I'm setting linear velocity to my Hero:

    (void)jump {
    b2Vec2 velocity = [controlledObject getBody]->GetLinearVelocity();
    velocity.y = velocity.y + [[AppDel cfg] getHeroJumpVlelocity];
    [controlledObject getBody]->SetLinearVelocity(velocity);
    

    }

  • If I'll run, jump, and release run button, while he is in air, all will work fine.

  • And here is my problem: If I'll run, jump, and continue running on landing (or when he goes from one static body to another: there is small fall, probably), Hero will start move, like he has no friction, but he has! I checked this via beakpoints: he has friction, but I can move left of right, and he will never stop, until i'll jump (or go from one static body to another), with unpressed running button.

    I allready tried:

  • Set friction to body on every iteration

  • double-check am I setting friction to right fixture.

  • set Linear Damping to Hero: his move slows down on gugged moveing.

A little more code:

I have a sensor and body fixtures in my hero:

 (void) addBodyFixture
{
    b2CircleShape dynamicBox;
    dynamicBox.m_radius = [[AppDel cfg] getHeroRadius];

    b2FixtureDef bodyFixtureDef;
    bodyFixtureDef.shape = &dynamicBox;
    bodyFixtureDef.density = 1.0f;
    bodyFixtureDef.friction = [[AppDel cfg] getHeroFriction];
    bodyFixtureDef.restitution = [[AppDel cfg] getHeroRestitution];
    bodyFixtureDef.filter.categoryBits = 0x0001;
    bodyFixtureDef.filter.maskBits = 0x0001;
    bodyFixtureDef.filter.groupIndex = 0;
    bodyFixtureDef.userData = [NSNumber numberWithInt:FIXTURE_BODY];

    [physicalBody addFixture:bodyFixtureDef];
}

 (void) addSensorFixture
{
    b2CircleShape sensorBox;
    sensorBox.m_radius = [[AppDel cfg] getHeroRadius] * 0.95;
    sensorBox.m_p.Set(0, -[[AppDel cfg] getHeroRadius] / 10);
    b2FixtureDef sensor;
    sensor.shape = &sensorBox;
    sensor.filter.categoryBits = 0x0001;
    sensor.filter.maskBits = 0x0001;
    sensor.filter.groupIndex = 0;
    sensor.isSensor = YES;
    sensor.userData = [NSNumber numberWithInt:FIXTURE_SENSOR];

    [physicalBody addFixture:sensor];
}

Here I'm tracking is hero in air:

void FixtureContactListener::BeginContact(b2Contact* contact)
{
    // We need to copy out the data because the b2Contact passed in
    // is reused.
    Squirrel *squirrel = (Squirrel *)contact->GetFixtureB()->GetBody()->GetUserData();
    if (squirrel)
    {
        [squirrel addContact];
    }
}

void FixtureContactListener::EndContact(b2Contact* contact) 
{
    Squirrel *squirrel = (Squirrel *)contact->GetFixtureB()->GetBody()->GetUserData();
    if (squirrel) 
    {
        [squirrel removeContact];
    }
}

here is Hero's logic on contacts:

- (void) addContact
{

    if (contactCount == 0)
        [self landing];
    contactCount++;
}
- (void) removeContact
{
    contactCount--;
    if (contactCount == 0)
        [self flying];
    if (contactCount <0)
        contactCount = 0;
}

- (void)landing
{
    inAir = NO;
    acceleration = [[AppDel cfg] getHeroRunAcceleration];
    [sprite stopAllActions];
    (running ? [sprite runAction:[self runAction]] : [sprite runAction:[self standAction]]);
}
- (void)flying
{
    inAir = YES;
    acceleration = [[AppDel cfg] getHeroAirAcceleration];
    [sprite stopAllActions];
    [self flyAction];
}

here is Hero's moving logic:

- (void)stop
{

    running = NO;
    if (!inAir)
    {
        [sprite stopAllActions];
        [sprite runAction:[self standAction]];
    }
}

- (void)left
{
    [physicalBody setFriction:0];
    if (!running && !inAir)
    {
        [sprite stopAllActions];
        [sprite runAction:[self runAction]];
    }
    running = YES;
    moveingDirection = NO;
    [bodyControls moveToDirection:CGPointMake(-1, 0) onlyHorizontal:YES];
}

- (void)right
{
    [physicalBody setFriction:0];
    if (!running && !inAir)
    {
        [sprite stopAllActions];
        [sprite runAction:[self runAction]];
    }
    running = YES;
    moveingDirection = YES;
    [bodyControls moveToDirection:CGPointMake(1, 0) onlyHorizontal:YES];
}
- (void)jump
{
    if (!inAir) 
    {
        [bodyControls jump];
    }
}

and here is my update method (called on every iteration):

 - (void)update:(NSMutableDictionary *)buttons
    {   
        if (!isDead)
        {
            [self updateWithButtonName:BUTTON_LEFT inButtons:buttons whenPressed:@selector(left) whenUnpressed:@selector(stop)];
            [self updateWithButtonName:BUTTON_RIGHT inButtons:buttons whenPressed:@selector(right) whenUnpressed:@selector(stop)];
            [self updateWithButtonName:BUTTON_UP inButtons:buttons whenPressed:@selector(jump) whenUnpressed:@selector(nothing)];
            [self updateWithButtonName:BUTTON_DOWN inButtons:buttons whenPressed:@selector(nothing) whenUnpressed:@selector(nothing)];
            [sprite setFlipX:(moveingDirection)];


        }

        [self checkPosition];
        if (!running)
            [physicalBody setFriction:[[AppDel cfg] getHeroFriction]];
        else
            [physicalBody setFriction:0];
    }

- (void)updateWithButtonName:(NSString *)buttonName inButtons:(NSDictionary *)buttons whenPressed:(SEL)pressedSelector whenUnpressed:(SEL)unpressedSelector
{
    NSNumber *buttonNumber = [buttons objectForKey:buttonName];
    if (buttonNumber  == nil)
        return;

    if ([buttonNumber boolValue])
        [self performSelector:pressedSelector];
    else
        [self performSelector:unpressedSelector];
}

- (void)checkPosition
{
    b2Body *body = [self getBody];
    b2Vec2 position = body->GetPosition();
    CGPoint inWorldPosition = [[AppDel cfg] worldMeterPointFromScreenPixel:CGPointMake(position.x * PTM_RATIO, position.y * PTM_RATIO)];
    if (inWorldPosition.x < 0 || 
        inWorldPosition.x > WORLD_WIDGH / PTM_RATIO ||
        inWorldPosition.y <= 0)
    {
        [self kill];
    }
}

© Game Development or respective owner

Related posts about box2d

Related posts about cocos2d-iphone