Sticking the Landing: The Parabolic Jump Physics of Endless Runners
A mathematical exploration of kinematic jump curves, Euler integration, asymmetrical gravity designs, and bounding box collision detection in HTML5 games.
Introduction: The Geometry of the Leap
In side-scrolling endless runner games, such as our browser-based Endless Runner Pixel, the player has minimal controls. Usually, you can only perform one active action: **Jumping**. Because the entire gameplay loop revolves around timing this single leap over gaps, barriers, and enemies, the physical feel of the jump must be perfect.
If a jump is too slow to rise or lingers too long at the peak, players describe it as "floaty" or unresponsive. If it drops too quickly, the jump feels heavy and frustrating. Finding the sweet spot is not just a matter of trial and error; it is a question of classical physics and calculus. This article breaks down the mathematical equations that model a perfect jump, analyzes how computers calculate these curves in real-time, and shares the secrets game designers use to make jumping feel incredibly responsive.
The Classical Physics of a Jump: Parabolic Trajectories
In classical mechanics, a jump is a standard example of projectile motion. When a character leaves the ground, their horizontal velocity remains constant, while their vertical velocity is acted upon by a constant downward acceleration: **Gravity** ($g$).
According to Newton's equations of motion, the vertical position ($y$) of the character at any given time ($t$) after leaving the ground is calculated using this quadratic formula:
y(t) = y_0 + v_{y0} * t - \frac{1}{2} * g * t^2
Where y_0 is the starting vertical position, v_{y0} is the initial upward velocity, g is the gravitational acceleration constant, and t is the elapsed time.
Because the vertical position is a quadratic function of time, plotting the character's coordinates yields a perfect mathematical **Parabola**. The peak of this parabola represents the maximum height of the jump ($h_{\text{max}}$), which occurs when the vertical velocity decelerates to exactly zero. The time it takes to reach this peak is modeled by:
t_{peak} = v_{y0} / g
Discrete Euler Integration in Game Engines
While the mathematical physics equation is elegant, computer game engines rarely use analytical calculus to calculate positions frame-by-frame. Instead, engines calculate motion using a step-by-step approximation called Euler Integration.
On every frame of the game loop, the engine updates the character's state using three discrete calculations:
- Apply Gravity to Velocity:
velocity.y += gravity * dt;
- Apply Velocity to Position:
position.y += velocity.y * dt;
- Resolve Collisions: Check if the character has touched a platform and halt downward velocity if necessary.
While Euler integration is incredibly simple and fast, it has a significant flaw: **framerate dependency**. If your delta time ($\Delta t$) fluctuates due to system lag or varies between 60Hz and 120Hz displays, the step-by-step integration will overshoot or undershoot the theoretical parabola. To prevent this, developers must clamp delta time values and implement high-precision physics sub-stepping.
The Secret of Game Feel: Asymmetrical Gravity
If you build a game using pure Newtonian physics where gravity is constant, the jump will feel bad. Real-world gravity decelerates your ascent and accelerates your descent at the exact same rate. In a fast-paced game, this symmetry makes the jump feel sluggish at the peak and floaty overall. Players want to feel in control.
To fix this, game designers use a technique called Asymmetrical Gravity:
Instead of using a single gravity constant, developers apply different gravity values based on the character's vertical movement:
- Ascending Gravity ($g_{\text{up}}$): When the character is moving upward (
velocity.y < 0), apply a lower gravity value. This allows the player to reach their peak height quickly and smoothly, providing a sense of weightless lift. - Descending Gravity ($g_{\text{down}}$): The instant the character reaches the peak and begins to fall (
velocity.y > 0), switch to a significantly higher gravity value (often 1.5x to 2x higher). This pulls the character back to the ground quickly, giving the landing a satisfying, snappy weight.
Variable Jump Heights: Player Agency
To give players fine-grained control, modern platformers also support variable jump heights. If a player merely taps the jump key, they perform a short hop. If they hold the key down, they jump much higher. Developers achieve this by checking the input state during the ascent:
- If the player releases the jump key while the character is still rising (
velocity.y < 0), the engine instantly scales down the upward velocity or applies a massive gravitational penalty for the remainder of the frame. This cuts the jump short, allowing players to adjust their landing trajectory mid-air.
| Jump Physics Type | Ascent Rate | Descent Snappiness | Player Responsiveness | Best Gaming Application |
|---|---|---|---|---|
| Newtonian Physics (Symmetrical) | Constant Linear Deceleration | Constant Linear Acceleration | Low. Feels floaty and slow to land. | Realistic simulators and space physics. |
| Asymmetrical Snappy Gravity | Extended high-velocity lift | Aggressive, heavy fall pull | High. Ascent is fast, landing is instant. | Retro arcade, high-speed runners, platformers. |
| Variable Height (Sustained Lift) | Determined by button-hold length | Snappy fall pull upon release | Excellent. High control over landing points. | Competitive speedrunners, precise platformers. |
Collision Detection and the Tunnelling Problem
Jumping is only half the battle; the character must also land safely on platforms. The standard method for checking collisions is Axis-Aligned Bounding Box (AABB) collision detection. AABB checks if two non-rotated rectangular boxes overlap along both the X and Y axes.
However, when a character falls rapidly due to aggressive descending gravity, their vertical velocity might reach 20 pixels per frame. If a platform is only 10 pixels thick, the character's position on frame 1 is above the platform, but by frame 2, they have jumped entirely past the platform's boundaries.
This phenomenon is known as Tunnelling. To prevent characters from falling through solid ground, high-performance engines use **Sweep Testing** or **Sub-Frame Stepping**. Instead of checking for collisions only at the final position, the engine divides the frameβs movement vector into smaller, 2-pixel steps, checking for collisions at each step to catch any intersections.
function updatePlayerPhysics(player, dt) {
// Select gravity based on movement direction
let gravity = PHYSICS.GRAVITY_NORMAL;
if (player.velocity.y > 0) {
gravity = PHYSICS.GRAVITY_FALL; // Heavier pull when falling
} else if (player.velocity.y < 0 && !player.isHoldingJump) {
gravity = PHYSICS.GRAVITY_LOW_HOLD; // Apply penalty if released early
}
// Euler Integration step
player.velocity.y += gravity * dt;
player.y += player.velocity.y * dt;
// Floor boundary resolution
if (player.y >= PHYSICS.FLOOR_LEVEL) {
player.y = PHYSICS.FLOOR_LEVEL;
player.velocity.y = 0;
player.isGrounded = true;
}
}
Conclusion: Crafting the Perfect Jump
Creating a satisfying jump is a delicate balance of physical science and game design. By applying asymmetrical gravity and variable height multipliers, developers turn simple equations of motion into a responsive, snappy game mechanic. The next time you timing a leap over a pixel obstacle, remember the math and coding working in the background to ensure you stick the landing. Ready to test these physics yourself? Put your reflexes to the test in our touch-responsive Endless Runner Pixel or challenge your spatial planning in our classic Sliding Puzzle for the ultimate test of control.