Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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'm 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 already 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];
    }
}
share|improve this question
    
Don't set the linear velocity apply a force to the body. Box2d cant apply friction (etc...) if you keep overriding the changes by setting the velocity. –  ClassicThunder Feb 29 '12 at 11:24
    
tnx for response, I thought about that, but I'm porting this from flash (with box2d), and there this work. may be we use dofferent versions? Or, I must set friction in another part of code? but where? I cant clearly understand this stuff. Can you advice something more specific? –  SentineL Feb 29 '12 at 12:02
add comment

1 Answer 1

up vote 2 down vote accepted

I needed only reset friction on presolve:

void FixtureContactListener::PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
{
    contact->ResetFriction();

}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.