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:
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.
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.
Answer
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)
No comments:
Post a Comment