Kinematic Jump Formulas for 2D and 3D Games

Instead of tweaking jump speed and gravity values until they "feel right," you can use kinematic jump formulas to calculate the exact physics values you need. Just input design-friendly settings like how high you want your character to jump, how long it should take to reach the peak, and how far it should travel horizontally.

This approach gives you precise control over your character's jump height and how long they take. I'll show you a few simple functions you can copy and paste into any project and reuse for any jumping mechanic in your 2D and 3D games.

In M13 in Learn 2D Gamedev From Zero we use these formulas to finely control the jumps in our pixel art side-scroller

You can copy these formulas into any project to design jumps by their height, timing, and horizontal distance instead of guessing at physics values.

Why should I use these formulas instead of tweaking jump speed and gravity?

When you design jumps with speed and gravity, each property affects both height and timing. You end up tweaking both values repeatedly without knowing the exact jump height. It works, but it's not ideal.

With the kinematic jump formulas, you can input exact values like "I want my character to jump 50 pixels high and travel 100 pixels horizontally." The formulas calculate the exact speed and gravity values for you.

Also, knowing the exact height and length of jumps paves the way for more advanced systems like pathfinding with enemies that can jump over obstacles or chase the player across platforms.

Plus, it works the same in 2D and 3D games, so you can reuse these formulas in any project.

Formula 1: Initial jump speed

This formula calculates the upward velocity you need to reach a specific height in a specific time.

func calculate_jump_speed(height: float, time_to_peak: float) -> float:
	return (-2.0 * height) / time_to_peak

It has two parameters:

Use it like this:

@export var jump_height := 50.0
@export var jump_time_to_peak := 0.4

@onready var jump_speed := calculate_jump_speed(jump_height, jump_time_to_peak)

func _physics_process(delta: float) -> void:
	if Input.is_action_just_pressed("jump"):
		velocity.y = jump_speed
Why do you use the @onready annotation when calculating the jump speed?

The values you set in the Inspector for exported variables are not immediately available when a script loads. Waiting until the _ready() function runs (or using @onready) ensures that the exported variables have the expected values set before you use them.

Formula 2: Jump gravity (rising)

This formula calculates the gravity you need to reach a specific height in a specific time.

func calculate_jump_gravity(height: float, time_to_peak: float) -> float:
	return (2.0 * height) / pow(time_to_peak, 2.0)

It has two parameters:

This assumes you want an asymmetrical jump, where the character rises slower than they fall. This makes it easier for the player to control the jump height and landing (many games use this approach).

Use it like this:

@export var jump_height := 50.0
@export var jump_time_to_peak := 0.4

@onready var up_gravity := calculate_jump_gravity(jump_height, jump_time_to_peak)

func _physics_process(delta: float) -> void:
	if velocity.y <= 0.0:
		velocity.y += up_gravity * delta

Formula 3: Fall gravity (descending)

In many games, the jump has different gravity when going up vs. going down. This helps the player land precisely on platforms.

This formula is the same as for upward gravity, but it calculates gravity based on the time to return to ground level. I wrote a separate function for clarity, but feel free to reuse the calculate_jump_gravity() function if you prefer.

func calculate_fall_gravity(height: float, time_to_descent: float) -> float:
	return (2.0 * height) / pow(time_to_descent, 2.0)

The parameters and usage are the same as for the rising portion of the jump:

@export var jump_height := 50.0
@export var jump_time_to_descent := 0.25

@onready var fall_gravity := calculate_fall_gravity(jump_height, jump_time_to_descent)

func _physics_process(delta: float) -> void:
	if velocity.y <= 0.0:
		velocity.y += up_gravity * delta
	else:
		velocity.y += fall_gravity * delta

Formula 4: Horizontal jump speed

This formula calculates the horizontal speed needed to travel a specific distance during the complete jump. This assumes the jump is asymmetrical, meaning the time to reach the maximum height is different from the time to fall back down.

func calculate_jump_horizontal_speed(distance: float, time_to_peak: float, time_to_descent: float) -> float:
	return distance / (time_to_peak + time_to_descent)

Use it like this:

@export var jump_distance := 100.0
@export var jump_time_to_peak := 0.4
@export var jump_time_to_descent := 0.25

@onready var horizontal_speed = calculate_jump_horizontal_speed(jump_distance, jump_time_to_peak, jump_time_to_descent)

func _physics_process(delta: float) -> void:
	if Input.is_action_just_pressed("jump"):
		velocity.x = sign(input_direction) * horizontal_speed
What if my jump is symmetrical?

If your jump has the same time to rise and fall, you can simplify the formula to:

func calculate_jump_horizontal_speed(distance: float, time_to_ground: float) -> float:
	return distance / time_to_ground

These formulas work the same in 2D and 3D! Just change your height and use the correct values (pixels in 2D and meters in 3D) and apply the calculated values to the correct velocity components.

Nathan

Founder and teacher at GDQuest

Updates / Code patches

Become an Indie Gamedev with GDQuest!

Don't stop here. Step-by-step tutorials are fun but they only take you so far.

Try one of our proven study programs to become an independent Gamedev truly capable of realizing the games you’ve always wanted to make.

Nathan

Founder and teacher at GDQuest
  • Starter Kit
  • Learn Gamedev from Zero
Check out GDSchool

You're welcome in our little community

Get help from peers and pros on GDQuest's Discord server!

20,000 membersJoin Server

Contribute to GDQuest's Free Library

There are multiple ways you can join our effort to create free and open source gamedev resources that are accessible to everyone!