12
\$\begingroup\$

There's one thing that has been puzzling me, and that is how to implement a 'faux-impulsed' jump in a platformer. If you don't know what I'm talking about, then think of the jumps of Mario, Kirby, and Quote from Cave Story. What do they have in common? Well, the height of your jump is determined by how long you keep the jump button pressed.

Knowing that these character's 'impulses' are built not before their jump, as in actual physics, but rather while in mid-air - that is, you can very well lift your finger midway of the max height and it will stop, even if with desacceleration between it and the full stop; which is why you can simply tap for a hop and hold it for a long jump -, I am mesmerized by how they keep their trajetories as arcs.

My current implementation works as following:

enter image description here

While the jump button is pressed, gravity is turned off and the avatar's Y coordenate is decremented by the constant value of the gravity. For example, if things fall at Z units per tick, it will rise Z units per tick.

Once the button is released or the limit is reached, the avatar desaccelerates in an amount that would make it cover X units until its speed reaches 0; once it does, it accelerates up until its speed matches gravity - sticking to the example, I could say it accelerates from 0 to Z units/tick while still covering X units.

This implementation, however, makes jumps too diagonal, and unless the avatar's speed is faster than the gravity, which would make it way too fast in my current project (it moves at about 4 pixels per tick and gravity is 10 pixels per tick, at a framerate of 40FPS), it also makes it more vertical than horizontal. Those familiar with platformers would notice that the character's arc'd jump almost always allows them to jump further even if they aren't as fast as the game's gravity, and when it doesn't, if not played right, would prove itself to be very counter-intuitive. I know this because I could attest that my implementation is very annoying.

enter image description here

Has anyone ever attempted at similar mechanics, and maybe even succeeded? I'd like to know what's behind this kind of platformer jumping. If you haven't ever had any experience with this beforehand and want to give it a go, then please, don't try to correct or enhance my explained implementation, unless I was on the right way - try to make up your solution from scratch. I don't care if you use gravity, physics or whatnot, as long as it shows how these pseudo-impulses work, it does the job.

Also, I'd like its presentation to avoid a language-specific coding; like, sharing us a C++ example, or Delphi... As much as I'm using the XNA framework for my project and wouldn't mind C# stuff, I don't have much patience to read other's code, and I'm certain game developers of other languages would be interested in what we achieve here, so don't mind sticking to pseudo-code.

Thank you beforehand.

\$\endgroup\$
3
  • 3
    \$\begingroup\$ Did you have a look at the following question and its answer(s)? gamedev.stackexchange.com/questions/29617/… \$\endgroup\$
    – bummzack
    Commented Dec 17, 2012 at 16:24
  • \$\begingroup\$ @bummzack This is very clearing as well. \$\endgroup\$
    – Mutoh
    Commented Dec 17, 2012 at 19:48
  • 1
    \$\begingroup\$ possible duplicate of Jump handling and gravity While it doesn't have pretty pictures, it's the same question. \$\endgroup\$
    – House
    Commented Dec 17, 2012 at 22:12

3 Answers 3

8
\$\begingroup\$

I think your main problem lies here:

While the jump button is pressed, gravity is turned off and the avatar's Y coordenate is decremented by the constant value of the gravity. For example, if things fall at Z units per tick, it will rise Z units per tick.

Gravity doesn't work like that. Google "uniformly accelerated motion" for the details, but in simple terms, as another fellow member said, gravity is an acceleration, not a velocity.

To put it simply, while velocity is the constant rate of change of position over time, acceleration is the constant rate of change of velocity over time.

So your first order of business would be to change your falling algorithm to include acceleration, not just velocity. Instead of:

pos_y = pos_y + (velocity_y * time_difference)

you would have to do something like

pos_y = pos_y + (velocity_y * time_difference) + (gravity_y * (time_difference ^ 2) / 2)
velocity_y = velocity_y + (acceleration_y * time_difference)

That way everything will fall in a parabola, which is the physically correct motion.

Now, to implement simple jumping (we'll get to your exact question right after this), you simply set velocity_y to a desired value. As long as the sign for acceleration_y and your desired velocity_y are different, your object will jump correctly (In other terms, you don't "turn off gravity". You keep it on, and simply set the object's velocity to some predefined value).

You will notice that the greater velocity_y is when you start jumping, the higher the jump will be. So to implement your desired effect, you add some kind of acceleration to the jump (in physical terms, this means adding a force. Think of adding a small rocket to the object).

To do this, you do the same thing as before, but now the acceleration and velocity should have the same sign. You do this while the button is pressed:

pos_y = pos_y + (velocity_y * time_difference) + (force_y * (time_difference ^ 2) / 2)
velocity_y = velocity_y + (force_y * time_difference)
\$\endgroup\$
4
\$\begingroup\$

The solution is not to delay deceleration. When you throw a ball up in the air, it isn't moving at a constant speed until it reaches its maximum height, but decelerates from the moment of impulse.

Gravity is not a velocity, but an acceleration. So if a player has a speed upwards of 20 units, and gravity is -10 units, on the next tick, the speed upward would be 10 units, on the next, 0 units, etc.

The reason why your jumps are seeming so diagonal is because your player's speed up and down is constant. So if you literally draw a line following the path of the player, you will see a line with the slope, positive or negative, of your gravity value over the change in the x position.

For your player to control the height of your jump, your player should be given some initial velocity on impulse, gravity should be turned off, and a special gravity value (less than regular gravity) should be applied to the player's velocity. Once the jump button is released or the player velocity reaches 0, normal gravity should be applied.

This way, the player will see a nice curve during their jump, whether they are decelerating by regular gravity or not.

\$\endgroup\$
2
\$\begingroup\$

Short story is: you're going to have a non-parabolic section in your jump arc somewhere.

I tried a few approaches when implementing jumping:

  • Constant climb: This appears to be, in effect, what you were trying: having the positive vertical velocity fixed until the button is released, at which point normal gravity kicks in. The arc is diagonal on the ascent, but normal on the fall - this actually normally looks OK, and (more importantly) feels OK, as it's quite easy to judge the height of the jump well.

  • Arrested climb: This is where you start the character off ascending at the parabola of maximum height, applying an initial impulse. Then, when the button is released, you set the vertical velocity to zero (or a small upwards velocity). This means your biggest jumps are a guaranteed parabola, and smaller jumps feel more like you're doing a big jump then slowing down.

  • Variable initial impulse: This is the one I ended up opting for: pressing jump would apply an initial upward impulse sufficient for a hop, and then continue applying upward acceleration (much greater than gravity) over a short period - the jump window - until the button was released. Once the jump window closed, the motion would then be parabolic, and the period of variable initial impulse was short enough that it didn't look odd, but was long enough to give an experienced player enough scope to control jump height. The downside was it wasn't as easy to judge jump height, as the window was much smaller and didn't have the correspondence of release moment to height. As it happened most of the time you either wanted a tap or a full jump anyway, so that wasn't such an issue.

Try these and see which feels best.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .