Problem with character jumping

Aug 24, 2010 at 8:36 AM

Hey guys, currently I'm trying to implement the character jumping and everything looks fine but there is one problem which make me headache.

If the ground doesn't have any friction, when I moving to the right/left and press Jump, it will jump with a same distance and height no matter how many times I tried.

But if I set some friction on ground, when I moving to the right/left, sometimes I will get lower jump compared to the one without friction.

Anyone know what happens? You might be thinking that friction reduced the velocity but the problem is sometimes I still can get the same height, distance with the one without friction.

My character is a circle shape body, if I didnt set any friction on floor, when the character moving, the body doesn't roll at all but once I have set some friction on the ground, the circle body will move by rolling itself.

Hope someone can help me out on this, thanks.

Aug 24, 2010 at 2:19 PM

Are you using Farseer 2.1 or Farseer3.0?

In Farseer 2.1, the circles are not real circles, are approximations, so probably if you have friction set on the grouind, you character wil bump a little when moving. Because of these small bumps probably are the cause that your jump height varies when you apply an impulse to your character.

Aug 24, 2010 at 2:36 PM

Yea I'm using Farseer 2.1...

So is there anyway I can overcome this problem while using Farseer 2.1? 

Because I found out that the translation from Farseer2.x to Farseer3.0 required me to do quite alot of changes and I don't have enough of time for it :(

Aug 24, 2010 at 2:43 PM

You can do a little trick, is like cheating the physics engine though.

Before applying the impulse, check your Y value of your character's LinearVelocity, then substract that value to the applied impulse. For example if you make your character jump with this code:

body.ApplyLinearImpulse(new Vector2(Xvalue, Yvalue));

You can do instead:

body.ApplyLinearImpulse(new Vector2(Xvalue, Yvalue - body.LinearVelocity.Y));
Or something like that. Hope this helps :)

Aug 24, 2010 at 2:58 PM

It doesn't work :(

OMG :(

Aug 24, 2010 at 3:01 PM

What happens? Your character jumps more, less?

Aug 24, 2010 at 3:10 PM
Edited Aug 24, 2010 at 3:21 PM

Nothing change, sometimes it will still jump higher and sometimes it jumps lower.. :( 

BTW, I think I will post the solution and you can download it and have a look.

After you compile and run the program, you can use AD to move, W to jump, F1 to turn on Farseer DebugView.

I'll repeat my problem again:

you can try to walk left/right then jump and observe the jumping height, you will notice that sometimes it will jump higher and sometimes it will jump lower. 

If I turn off the friction for ground and circle, it will always jump higher. This is why I suspect the friction has make it jump lower but weird is, sometimes it still can jump higher :(

I'm really blur about this.


Aug 24, 2010 at 3:28 PM

OK, I think I know where your problem is. Is the code you use for detecting if the character is touching the floor or not.

Everytime the Oncollision is called, you set the isJumping value to false. But sometimes, your character will not be touching the floor even if you haven't pressed the W key (because of the small bumps I explained before). In other cases when you press the W key, you apply a vertical impulse and set isJumping to true, but at the next update, it is possible that the character will still touching the floor, hence calling the onCollision and then updating the isJumping back to false, then it applies again the vertical impulse as the W key is still pressed.

You could do a couple of things to solve this:

- Implement a InputHelper that records when a key is pressed for the first time (somthing like NewPress) instead of checking if it is pressed. There are plenty of inputhelper examples on the Internet.

- Implement a better "touching floor" detection. What I do is that in the OnCollision I record the current gametime in a variable, let's call it lastTimeTouchingFloor. Then in the Update method I check if the lastTimeTouchingFloor is less than 50 ms than the current time, this means that my character has been 50ms without touching the floor, then I set isJumping to true.

Good luck :)

Aug 24, 2010 at 3:33 PM

Alright, I'll try to fix it like what you said, thanks alot for your helps :D

Aug 24, 2010 at 3:36 PM

O ya, 1 more thing, is there anyway to prevent the upper rectangle body to bounce down?

Because I noticed that the rectangle will slightly move down whenever I jump from the top.

Aug 24, 2010 at 3:39 PM

Make the circle heavier (or the rectangle lighter), and maybe the rectangle will bounce less. I guess...

Aug 24, 2010 at 3:41 PM

I tried before by making the circle heavier or rectangle lighter but make no difference :(


Aug 25, 2010 at 2:53 AM

Forgive my noobiness. I try to implement the second way which you have suggested to me but I still don't get it right :(

I don't understand what's your second way mean.

Can u help me out or maybe explain in more details?

Aug 25, 2010 at 6:38 AM

No problem :)

The idea is to check when was the last time your character was touching the floor, and then check that if it hasn't been touching the floor for a small amount of time (this small amount of time is just in case the character hasn't bumped instead of jumping). In your character class you declare (this is an example, I'm not sure if it would work as it is):

double lastTimeOnFloor;
double currentTime;
bool isJumping = false;

Then in your circle's OnCollision method:

private bool OnCollision(Geom g1, Geom g2, ContactList contactList)
    lastTimeOnFloor = currentTime;
    isJumping = false;

And in your character's Update method:

public void Update(GameTime gameTime)
    // We give a threshold of 50ms
    if(lastTimeOnFloor + 50 < currentTime)
        isJumping = true;

    currentTime = gameTime.CurrentTimeInMs;
I guess this should do it. Cheers.


Aug 25, 2010 at 6:59 AM
Edited Aug 25, 2010 at 8:02 AM

Hey, it is working now !!!! Although sometimes it still will jump lower but the lower is much more higher

Thanks alot :D

But I still don't really understand the concept? why there is some bumped on the ground? the friction will create the invincible bump?


Aug 25, 2010 at 8:09 AM

I'm not sure about the friction effect, but the case is that the circle below is not a "real" circle, is an approximation. Think about a square spinning, you will see that it bumps when spinning on the ground because of its edges, now if instead a square you use a pentagon, the bumping will be lower, and so on, the more the edges you have, lower will be the bumping effect. So in Farseer 2.1, the circles are polygons with many edges, they are not "perfect" circles, that's why you could see a small bumping. Probably the lack of friction minimizes this effect, I'm not sure.

Remember to still substract the Y Linear Velocity while applying the jumping impulse, just in case. And make the jumping button work when is pressed for the first time.


Aug 25, 2010 at 8:16 AM

I see, too bad I wish to switch to Farseer 3.0 but there are something which I still don't understand :(

Because now they are using the real world unit (meter).

The usual way I used to create a geom/body is passing the texture.Width and texture.Height as the body width and height.

But if I do the same thing in Farseer3.0 it's gonna create hundred of meter for an object.

I heard they said need to scale down then zoom in the camera, that's make me very headache and confusing.

I'm looking forward for Farseer 3.0 documentation and hope they have a clearer explanation on it :(

Aug 25, 2010 at 8:18 AM
Edited Aug 25, 2010 at 8:19 AM

I also got headaches with the unit conversion. This post should help you:

The last message has a pretty good solution for converting pixels to meters and viceversa.

Aug 25, 2010 at 8:22 AM

Wow, that's cool but I guess it takes some times for me to "digest" it...

BTW, another thing is RayHelper class. Do you know where does it goes to in Farseer 3.0 ?