Jumping in a video game is complicated.
If you’re a gamer and take to the controls, then mission accomplished for the developers.
You don’t care about mechanics if things feel right.
If you’re implementing a jump in a game, you have to make a lot of decisions and hope
those decisions do not frustrate the gamer.
And then after decisions have been made, implementation demands math.
What is your starting upward velocity, and what is gravity?
That should be enough to get things started and also send you back down to the ground.
But before you deal with allowing the player to land – one big question is: Does how
long you hold down the A button affect how high you jump?
If it does, starting upward velocity and gravity aren’t enough.
You have to compromise your physics during the middle of your jump.
Turtles compromises physics, and arguably…
does not do it very well.
One button is responsible for three types of jumps.
Let’s break down TMNT’s jump implementation.
We’re gonna get technical.
What is gravity?
In physics, it’s a fundamental force.
In game programming, it’s an opinion.
While perhaps the gravity on earth is a good starting point for implementing physics in
a video game, pure realism may compromise what is fun.
So with a bit of creative freedom at their side, what steps does a programmer take to
implement jumping along with gravity?
Standard acceleration due to gravity is close to 9.8 meters per second squared.
How does this go into a game?
Distance traveled can be implemented using a conversion to pixels – possibly based
on the height of the playable character, for some form of accuracy.
But what about time?
Meters “per second squared?”
Do we need to keep track of time in an NES game?
If only we could make time a constant – have the same amount of time pass between updates
to player, enemy, or item positions on the screen.
Wait… we already have that.
The framerate of video output to the television is more or less clockwork.
If the passage of time between updates is always the same – 1/60th of a second in
the case of the North American NES – we can just tie physics to the framerate and
make time a constant.
We don’t bog down the CPU with calculations just for acceleration due to gravity on every
frame - the programmer just adds a single, magic number each time.
So a simple jump example might be: 1: Player presses A button.
2: Game assigns starting vertical velocity to the player
3: A Gravity constant influences vertical velocity’s value each frame
4: And vertical velocity is applied to the player’s position each frame.
We examined this in the Ninja Gaiden episode of Behind the Code.
The game adds just over 20% of a pixel to the player’s Y position each frame to push
gravity’s influence.
And wouldn’t this value or other values close to it translate fairly well to other
NES games?
Sure.
So long as the game runs at 60 frames per second.
But…
how could it not?
Didn’t I just say that the video output framerate is 60 frames per second to the television?
I did, indeed.
But the framerate of the game doesn’t always match video output framerate of the console.
That’s up to the programmer and the efficiency of their code.
TMNT runs at 30 frames per second.
Each rendered frame is output twice to the TV.
Two questions – how and why?
We’ve talked about the CPU and PPU working side by side in previous episodes of Behind
the Code.
The CPU calculates positions, collision detection, and more to setup the next frame of video
as the PPU outputs the current frame of video.
So long as the CPU can complete the calculations to setup the next frame, game frame rate and
video output frame rate match at 60 fps.
But what if there isn’t enough time for the CPU to get the work done before the next
frame is drawn to the screen?
No updates are specified for the PPU to render a new frame, and the previous frame of video
output is repeated.
This is unintentional, and the gamer experiences “slowdown” as the CPU continues to have
too much work to perform inside a single frame’s time.
If this happens too often during testing and the programmer cannot tighten their code up
enough to maintain 60 fps, they may elect to design the game with a lower framerate.
In the case of a 30 fps game, the CPU can split the work across the time used for two
video output frames.
The PPU draws each new game frame to the screen twice in a row and then receives the next
game frame.
Since the necessary calculations for the next frame take place every 1/30th of a second
instead of 1/60th, numbers such as gravity that assume a constant passage of time should
be adjusted.
If the framerate of TMNT is half of a 60 fps game, then wouldn’t the gravity constant
designed for around 60fps need to be maybe doubled for 30fps?
Possibly… but again - the value of gravity IS still an opinion.
That said, Chip and Dale’s Rescue Rangers and Teenage Mutant Ninja Turtles have almost
the same value for their gravity constant.
If we look at jumping for the games side by side, these jumps are quite different in terms
of hang time.
It is obvious that Chip on the left returns to the ground a lot faster than Leonardo on
the right.
The difference?
Gravity is applied every 60th of a second for Rescue Rangers, and every 30th of a second
for TMNT.
Was this an intentional design decision for TMNT, or was the gravity constant unaltered
when the game was perhaps migrated from 60 fps to 30 fps during development?
The influence of gravity on your jump not only dictates how high you go but how fast
you get there.
You ascend quickly, and gravity takes longer to get you to the ground.
It feels floaty.
Gamers call this a “moon jump.”
TMNT has three jump heights - a short jump, and “normal” medium jump, and a high jump
- which is more accurately described as an automatic double jump.
More on that later.
The jump you make depends on how long you hold down the A button.
And now we have reached the crux of TMNT’s jumping problem, in my opinion.
The game requires you to make short jumps despite low gravity, and this requires holding
down the A button a very short amount of time with a quick tap despite being stressed about
the jump... potentially.
The nebulous physics do not include the human equation.
If anything, you are going to tense-up and hold down the A button longer than you want.
To make this short jump, you have to press and release the A button within 4 frames.
If you fail to do this by taking too long to release A, you hit your head and fall into
the water.
Let’s dive into the mechanics (not the water) of this.
I wrote a script to log our vertical velocity during a jump.
I’ll make a “normal” or “medium” jump to explain what you see here.
The three types of jumps are indicated here.
A 1, 2, or 3 will appear depending on the jump.
The normal jump is a 1.
That is our current jump.
Y is the current Y velocity.
Anim is the animation we see.
That will change when we hit jump 3.
Count is the frame counter for the jump.
Maximum value is 8 because the code only cares about how long the A button is held, and holding
it 8 frames puts your turtle into the final jump – the high spin jump.
No need to worry about anything after 8 frames.
The jump happens at 30 frames per second.
So 1/30 of a second has passed each time this number is incremented.
The velocity for each frame is listed in a box that appears at the bottom.
You can see our gravity constant of 84 over 256 is applied for each frame.
So in this case, I made a medium jump by releasing the A button between 4 frames and 8 frames.
OK.
What about a short jump?
To execute a short jump, we have to release A before the 4th frame.
So what happens when you do that?
Vertical velocity receives a new value.
It is hardcoded to -2.44 when the code detects you let go of the A button before jump frame
4.
This is how the jump is shortened.
Your speed changes mid-jump.
Physics start like any other jump as the game can’t predict what you want to do.
When it sees that you let go of the A button before jump frame 4, it slows down your ascent.
Gravity remains unchanged.
It continues to be applied as usual, but velocity is downshifted here.
The exact frame you let go of A doesn’t matter – Frame 4 is the “milestone”
check for a short jump or not.
All previous frames will have the same Y velocity regardless of jump height.
What about the high jump?
If you hold down A for 8 frames or more, velocity is reassigned later on.
This time, the same starting upward velocity from the ground is used at frame 8 - a value
of minus six.
That’s why I called this a double jump.
The game puts the turtle into a spin at this point.
This does two things - it reduces the hitbox of the turtle and serves to distract the gamer
from noticing they are in the air for so long.
We can disable the spin and get an idea of the hangtime of a high jump - it is pretty
long!
Since gravity is lower than your average NES game, the turtles move upward pretty fast.
This does not leave much of a time window to release the A button for a shorter jump
and perhaps passes a greater difficulty onto the player.
Alright.
Now let's look at the code.
This area increments the jump frame counter, checks to see if the A button is still held
down, and alters velocity when necessary.
This code is easier to explain since you’ve already seen what it does thanks to the script
we just used.
First thing we do is figure out if the A button is still held down.
Next up - if we are past Frame 8, we skip ahead.
No checks necessary after Frame 8.
Otherwise, the specific jump frame checks kick-in.
If we are on frame 4, we check for a short jump here by looking to see if the A button
is still held.
If it is, we skip ahead.
If it isn’t, this is a short jump!
These values are used to reassign jump velocity.
The code for the high jump?
Same thing.
Are we on Frame 8?
If so, check for a high jump.
If A button isn’t held, skip ahead.
If it is still held, this is a high jump.
You can attack during a high jump to cancel the spin, and that check is performed here.
Otherwise, the turtle spins.
Under that, the double jump value of -6 is reassigned to velocity.
The controller read, starting upward velocity, and gravity – the items that make the “heart”
of a jump – are performed elsewhere, but this is your breakdown of our code that loosens
up the physics.
The question now is – can we alter gravity and frame counting in such a way that jumping
does not require such precise timing for A button presses?
Here is the tug-of-war for jump design:
We could alter the code so the short jump allows the A button to be held more than just
four frames.
The problem with this is that the turtle is still moving up with the usual velocity before
the short jump activates and reduces that velocity.
That’s too fast a take-off speed to allow for more frames.
So…
now you have to compensate for this by increasing gravity for example.
Keep the turtle from moving upward at such a fast rate.
That… makes the jump landable, however the take-off distance from the ledge is tight
because of the jump arc.
So… maybe we should also reduce the assigned velocity value for a short jump to improve
the jump arc.
This is starting to make a difference.
There is more forgiveness in the jump window as the A button can now be released prior
to 6 frames instead of 4.
The gravity tweak along with an adjustment to short jump velocity provide a more forgiving
jump arc AND… gets the turtle down to the ground at a faster speed.
Control on the ground is going to be much more responsive versus hang time in the air.
The only other item that is perhaps worth tweaking is the high jump velocity.
Higher gravity means a minus 6 double jump velo on Frame 8 is not going to get the turtle
up as high as it did under default gravity.
Perhaps minus 8 is the way to go to regain that high jump.
Here are the ROM addresses along with their old and new values plus the Game Genie codes
to get us there.
I didn’t select these values using fancy math – I just did some trial and error until
control started to feel right.
You may wish to spend additional time making adjustments to gravity, velocities, and more
to dial-in some superior controls for jumping in TMNT.
These values were enough to make a point.
The medium jump has all but been eliminated.
Perhaps it would be even better to settle on a single type of jump and then implement
a double jump with a second press of A to reach those higher platforms.
So if we finish up by talking about modifying TMNT’s jump design… whatever jumping you
have in a platformer has to be compatible with level layout.
If you experiment with altering or even gutting and rewriting turtle jump code, I would recommend
finding some areas in the game in an emulator, creating a save state for each of them, and
loading them up as you make your changes.
This allows you to quickly test your changes and make sure the new jump logic feels compatible
with all platforming and combat.
These areas of code give you your addresses for creating Game Genie codes or ROM patches.
I’m interested in reading or even seeing any new jump logic some of you produce.
Personally, the shorter jump time – getting back to the ground faster than the original
design – made me that much more aware of how slow the attack speeds were.
Should each turtle have a shorter wind-up time for their attack and therefore less “input
lag" so to speak?
TMNT sure feels like a rabbit hole in terms of gameplay that could be tweaked to be better.
Please like and subscribe for more videos like this one.
I also have a Patreon available for those of you interested, and thanks for watching.