1
votes

I'm creating a runner game, here is a screenshot : screenshot1

I divided my world in chunks, and i'm experiencing a collision issue. As you can see (in very small) on the bottom left, I have multiple grounds and they're moving to the left. Sometimes (by sometimes, I mean randomly) the runner bumps between two chunks and follows the ground to the left... screenshot2 (on the screenshot I placed the runner on the middle so I could take the screenshot)

I wrote a little fix to this but I find it very very [...] very dirty :

public void fixWeirdCollisionBug() {
    body.setTransform(body.getPosition().x, body.getPosition().y + transformToScreen(0.0002f), body.getAngle());
}

I move the ground up (just a little) where is the runner to avoid this bug between two grounds. Actually I'm looking for a better way to do this...

I also have another problem. I want my runner to be able to jump with a positive x velocity so he will go forward on the ground. My ground is a kinematic body and my player is a dynamic body. I set the friction on the player to 0 so he stays on his initial state and doesn't 'follow' the ground. The thing is that I want the runner to go ahead and come back slowly to its initial state when he jumps.

I tried the following but it doesn't work, the runner keep sliding on the ground :

public void jump() {
    if(!jumping) {
        System.out.println("Jump !");
        body.getFixtureList().get(0).setFriction(0.1f);
        body.applyLinearImpulse(getUserData().getJumpingLinearImpulse(), body.getWorldCenter(), true);
        jumping = true;
    }
}

and when the runner is at its initial state :

if(body.getFixtureList().get(0).getFriction() != 0 && body.getPosition().x < Constants.RUNNER_X_DEFAULT) {
        System.out.println("reset friction");
        body.getFixtureList().get(0).setFriction(0);
        body.setTransform(Constants.RUNNER_X_DEFAULT, body.getPosition().y, body.getAngle());
        body.setLinearVelocity(0, 0); //also try to reset velocity to remove the sliding effect, but doesn't work
}

(this is in the act() method of the runner)

I hope that someone will find out what's wrong with my code because it's starting to give me a headache... Thank you very much

EDIT : I tried to use an HorizontalGroup to solve the random bumps : doesn't work

1

1 Answers

1
votes

Regarding the first problem...

Sounds like you're encountering the "getting stuck" problem. Someone else also encountered this problem and asked about it here and I suspect many other people have also run into this same problem.

A write-up of this problem and how it can be worked-around was done by iforce2d at their website. I like iforce2d's write-up and recommend reading it.

I've also done an explanation of this problem and how it can be worked-around which you can find here. If you like my write-up, please up-vote it.

TL;DR... use the chain shape for the ground (which uses the optional adjacent vertices of the edge shape).

As to the second problem...

Based on what you've written, the comments you've added, and some reviewing of the Box2D sources I've been doing for this, I believe the problem you're running up against is that changing the friction of fixtures isn't designed to update the friction of existing contacts.

Here's the declaration for b2Fixture::SetFriction in the 2.3.2 sources related to this:

/// Set the coefficient of friction. This will _not_ change the friction of
/// existing contacts.
void SetFriction(float32 friction);

Inspecting the call hierarchy for b2MixFriction confirms the above comment. The mix friction function only gets called on construction of the contact and on calls to the contact's ResetFriction method. So when your code calls setFriction and you're not seeing the result you're expecting, I'll bet there's a contact already constructed for that fixture contacting the ground.

To solve this, algorithmically speaking, right after changing the fixture's friction, search for any contacts to this fixture and call those contacts' reset-friction methods to get those contacts to recognize the new mixed friction value. I believe in this context you could use the fixture body's get-contact-list method to get the list of contacts to check. Then iterate over all the contact edges while inspecting the edges' contacts to see if either of the contact's fixtures are the fixture you've just set a new friction for. For all the contacts whose fixture-A or fixture-B are the fixture in question, call their reset-friction method.