I moved to a new URL! Check it out!

Platforming Ledge Forgiveness

Platforming Ledge Forgiveness
When it comes to making a cool platforming game there's all kinds of little tricks you can do to make your game shine above all the rest. I mentioned jump input buffering in a previous post and how silently helping the player out here and there can make a huge difference in the feel of your game. The topic of this post is very similar to that!

Image


Take a look at this typical platforming scenario. Our player is barreling toward a ledge at top speed, just holding right without a care in the world. They're going to want to jump when they get to the end of that ledge, and they're probably going to want to hit jump as late as possible so that they get the maximum distance out of their jump.

Image


Ideally they would hit the jump button right now. Their character is still on the ground, and in the most simple implementation of a platformer jump system then this would be fine. I assume that the code would be just something along the lines of if (onGround) { jump(); } and onGround would evaluate to true if our player collides with the ground at y + 1.

But what happens if the player just slightly overshoots the ledge?

Image


If our most basic platforming system is only looking at the player's y + 1 to detect the ground, then the player will not be able to jump in this case. At this point you might ask well doesn't that make sense? The player isn't on the ground, so they can't jump... that's how it would work in the real world!

Image


This isn't the real world though, this is video games! If you're playing a fast paced platformer running at 60 frames per second, it's incredibly easy to hit the jump button right after you run off a ledge, but to your feeble human eyes it looked like you hit the jump button while you were still on the ground. This can be incredibly frustrating, especially if you're trying to make jumps across some pretty wide gaps and you're trying to maximize your jump distance.

What I like to do for my games for this situation is to introduce a timer that keeps track of how long it has been since the player last touched the ground. I usually refer to it as a jump grace period.

The logic goes a little something like this: First I have a jumpGraceTimer and a jumpGraceTime. jumpGraceTime is a fixed value of how may frames I will allow the player to still have access to their jump after they leave the ground. Usually this is around 3 to 5 frames (at 60 frames per second) depending on the speed of the player and the game. The timer counts down from that value to 0 whenever the player is no longer touching the ground (no collision at y + 1) when they didn't jump. If they did jump, I assume that they are purposely leaving the ground and I don't need to help them, so I set the timer to 0. When the player is touching the ground, that timer is always set to jumpGraceTime, so that it's ready to count down when the ground collision is no longer happening.

Now when I check to see if my player can actually jump or not, I'm actually checking to see if they are on the ground (onGround) or if the jumpGraceTimer is greater than 0. If they indeed can jump, then I do the jump logic and set the jumpGraceTimer to 0 manually. I don't want the player to be able to jump multiple times if they happen to be really good at mashing.

if (jumpInput) {
if (onGround || graceTimer > 0) {
jump();
}
}

//somewhere else in the code:
public function jump():void {
//pretend theres more jumping logic here
graceTimer = 0;
}

You can implement this in any way you want really, but this is just my go to technique! (Edit: Actually I guess I could just check to see if the graceTimer is > 0... but there might be some reason why I'm still checking onGround || graceTimer > 0... I can't remember now, haha!)

So here we go again. Our player runs off the ledge and hits jump just 2 frames after they've left the ground...

Image


But thanks to our jumpGraceTime that allows the player to be off the ledge for 3 to 5 frames before their jump is taken away, they can jump!

Image


And all is right in the world. If you do this right then the player wont suspect a thing. A very popular platformer game that you've probably heard of before (Canabalt) makes use of this technique! If you really try to push the limit, you'll notice that your character can actually be totally off the ledge and still jump as if his feet were on solid ground, but just for a fraction of a second.

Just be careful with how much time you allow the player to have before they can no longer jump. I implemented this in Offspring Fling with a very small timing window and it works just fine. However, we implemented this technique in Snapshot as well, but the timing window might actually be too generous in this case. There are times where you can clearly see Pic falling before you push the jump button, and this can sometimes cause a weird disconnect, or reveal the "man behind the curtain" which can make the player feel a little disrespected.

Little tricks like this that help the player feel more in control can really help your platformer shine! But you don't want to go overboard and baby the player either. Let them roam free and hurt themselves sometimes and learn from their mistakes, but also make sure they don't get frustrated by tiny details like pushing a button too early or too late by fractions of a second (unless we're talking about Street Fighter.)

Comments

NounVerber
NounVerber
Super meat boy made it so that some characters get an additional air-jump if they walk off the edge.
Posted May 11th 2013 3:52 AM
Danik
Danik
Good post! I usually do this too for platforming movement. There are some other similar situations that you might want to help the player, for example when the player is jumping under a platform and collides with only one or two pixels, it can be a good idea to nudge him to the side of the platform, especially if it's a fast paced game.
The trick you describe works well in combination with this if the player should be able to jump from a low tunnel exiting out from a wall, without hitting the ceiling too easily, or running off the edge before jumping.
Posted May 11th 2013 6:03 AM
bluescrn
bluescrn
Great explanation of these techniques, they really do make a big difference, don't they! - we had jump input buffering in Little Acorns from the start, and actually added a couple of frames of ledge forgiveness for the recent 3DS version, as playing it on 'real controls' made it more obvious that we needed something.
Posted May 11th 2013 7:16 AM
Kyle
Kyle
Thanks!

Also forgive the " or whatever is happening in the post sometimes, got a php function that's acting up somewhere at the moment -_-
Posted May 11th 2013 12:49 PM
Cheshyr
Cheshyr
I was reading one of the latest xkcd What If's.. http://what-if.xkcd.com/44/ and this kinda clicked for me. The relevant section mentioned "...it takes about five milliseconds for the fastest nerve impulse to travel the length of the arm...". While we're supposed to be anticipating the ledge, there's a certain inherent delay in the execution of our actions in relation in input. Making your jumpGraceTime correspond some portion of 5ms could be a good way to adjust your desired difficulty?
Posted May 11th 2013 1:45 PM
Kyle
Kyle
5ms might be a little too tight, since you are probably not even updating your game that fast. At 60 frames per second, which most games will be capped at, you're refreshing at 16.7ms.
Posted May 12th 2013 11:25 AM
tonieprawda
tonieprawda
flashback iirc had this wonderful idea of jumping only after the character prepared for it, so you had to hit jump way before the character actually jumped. It was more realistic and more fun!
Posted May 12th 2013 12:39 PM
new comment!

Post your comment!

Name
Email
Comment