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.

This question already has an answer here:

I have a very simple 2D game, similar to old-school Mario or Metroid. I'm having a lot of trouble figuring out the proper way to handle player jumping. I've tried several different methods. The first method being that as soon as the player presses the space bar, his position on the Y-Axis is automatically updated so that he is now 50 pixels higher. This didn't work, because his player model immediately jumped up instead of going for that smooth up/down look. The second method I tried was using a Timer. With this, once the player pressed the space bar, his position on the Y-Axis would be incremented every x milliseconds. This also didn't work, for the exact same reason that the first way didn't work. It shot straight up without looking smooth. The last method I tried was a resemblance of my movement on the X-Axis. Instead of waiting for player input, the Y-Axis is constantly being added, but when the player isn't jumping, the yVelocity = 0. When input does come in, an amount is added yVelocity and the player jumps up. I didn't expect this to work, obviously, but it looked better.

So how do you apply jumping correctly? This is something that I've been struggling with for a while, and I just want to get it right. Please don't confuse this question like this question, as they're both different. I need an efficient way to handle jumping so that he looks smooth (as in one motion) going up and down. I can make his falling look good, just not the going up part. Can anybody explain to me how they make jumping look good?

Note: I wrote this question without code because I want a general description of how one might do it. If you do need code or extra details, or anything to understand the question, I'll be happy to add any extra details that you might need.

share|improve this question

marked as duplicate by Sean Middleditch, Byte56 Jul 31 '13 at 14:33

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

    
This really has nothing to do with rendering. The motion of the character and how you draw him are separate things. –  Sean Middleditch Jul 31 '13 at 4:11
3  
The usual link on everything you need to know before writing a 2D platformer: higherorderfun.com/blog/2012/05/20/… –  Sean Middleditch Jul 31 '13 at 4:16
    
@SeanMiddleditch Thanks, I appreciate the link. I never found anything like this before, but the jumping portion of it doesn't really explain how I should implement jumping so that it looks correctly. All in all, however, I appreciate the link. –  hasherr Jul 31 '13 at 4:27
1  
2  
I'm a complete jerk in real life, if that helps even things out. :) –  Sean Middleditch Jul 31 '13 at 5:03
show 8 more comments

4 Answers 4

You must use Y vector applied to coordinate.

Every timer tick Y vector decreases by gravitation, so as higher player jumps as slower it will happens.

i.e. You set vector to 100px/s. This mean that in 1 second player must up to 100px. BUT, gravitation will reduce this height every timer tick. For example it will reduce 100px vector in 1 second. This mean that our vector will be fully decreased in 1 second.

If you have 30 timer ticks for this 1 second, so gravitation will reduce vector by 100/30 every tick.

You must update coordinates every tick by it's vector*time. Time in my example = 1/30s

Trajectory will like parabola in this case. It will be smooth enough.

share|improve this answer
    
This solution work only if the frame frequency is constant. If for any reason a frame take more than others, the trayectory is strange and not correct. –  Adrian Maire Jul 31 '13 at 7:57
    
Not exactly. This will work for any framerate if you will take into count delta time bethween frames and will multiply all constants by it. –  Darthman Jul 31 '13 at 9:29
    
Not, because your equation is a lineal aproximation for a quadratic ecuation: For example with g=1, fps=1 and start speed=5, you will get: 5 9 12 14 15 15 14.., but for fps=2 you get: 10 16 18.. The result trayectory depend of your framerate.That is not so bad, but if the framerate is not constant, you get strange behavior: imagine fps=1 1 20, so your y values will be 5 9 69, that is, a jump of 69 instead of 15. –  Adrian Maire Jul 31 '13 at 10:00
    
In this kind of games you must code your game very bad for getting 1fps :D I mean that it will not give you any difference at 60 or 90 fps. No, really there will be no visible difference. But if there is need to calculate it for 1fps then you must calculate all middle points in one timer iteration. But this is stupid to play that game with 1 fps. I mean nobody will do it. –  Darthman Jul 31 '13 at 10:35
    
You are right. The problem is when the game load some texture or perform any other operation that produce a lag in the fps, that is, the game run at (eg) 25 fps and in a instant one frame take 1second. In this case your algoritm push the character up like a rocket. –  Adrian Maire Jul 31 '13 at 11:07
show 2 more comments

Consider next values:

Vectors

  • pos0: The position of the character when he begin to jump.
  • speed0: The speed of the character when he begin to jump.

  • pos: current position

  • speed: current speed

Values:

  • g: gravity.
  • t0: time when the character begin to jump.
  • t: time elapsed in the current jump.
  • speedJump: The momentum added by jumping (vertical) (constant)
  • isJumping: if your character is currently jumping

When the player press the space key, your hold the t0 and pos0, and compute speed0:

if (!isJumping) // Only jump if it is not yet currently jumping
{
    t0=currentTime();
    pos0=pos;
    speed0 = speed;
    speed0.y += speedJump;
    isJumping = true;
}

Every frame, you may compute the new position of the character with:

if (isJumping)
{
    t = currentTime()-t0;
    pos.y = pos0.y + speed0.y*t - g*t*t;
    pos.x = pos0.x + speed0.x*t;

    // And test that the character is not on the ground again.
    if (pos.y < groundHeight(pos.x))
    {
        pos.y=groundHeight(pos.x);
        isJumping = false;
    }
}
share|improve this answer
add comment

You should Maintain 3 vectors: Position, Velocity and Acceleration

Initially set acceleration -ve in y-axis to simulate gravity

And Update these vectors at every frame like this

Position += Velocity
Velocity += Acceleration

(But if you are on ground, don't update the y component of velocity and position)

Now when you need to jump, simply set the Y component of Velocity to some +ve value. And you will automatically observe a smooth jump.

What actually happens here, when you set the velocity's Y to positive value, the player starts to rise up in space but since there is also some -ve acceleration, the velocity will also decrease, and at a particular height, velocity will become 0 and starts to drop down. The best part of this approach is that, it gives you a great feel of realistic gravity.

Note: (I am taking down left as (0,0) coordinate)

share|improve this answer
add comment

For this problem, I usually have a preset value for GRAVITY that pulls you down.

public void updatePosition() {
  if (onGround) {
    velocity_y = 0;   //If standing on ground surface, velocity in y-axis is stable.

  } else {
    velocity_y--;
    //Otherwise velocity in y-axis always goes downward, 
    //Depending on which platform you're working on, it could be velocity_y++;

    if (velocity_y < GRAVITY) velocity_y = GRAVITY; 
    // Have a threshold for velocity_y
  }
  // Update the actual position with the velocity calculated.
  x += velocity_x;
  y += velocity_y;
}

The above function is called at every frame

public void jump() {
  velocity_y = 20;
}

And jumping occurs when an event like key press happens.

share|improve this answer
    
This is how I had my X movement working, in which I already tried. –  hasherr Jul 31 '13 at 19:52
add comment

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