2


I am having trouble in getting precise jump heights using move_and_slide() on Godot 4.
I am trying to create a simple but reliable jump for my 2D platformer. Creating the jump parameters comes from this GDC talk.
The code I use is the following (simplified to focus on jump) :

extends CharacterBody2D

# Parameters to fix
var JUMP_HEIGHT : float = 100.0;   # In pixels
var JUMP_WIDTH : float = 64.0;    # In pixels
var MAX_SPEED : float = 500.0;
# Deduced parameters from GDC talk
var jump_speed : float = 2 * JUMP_HEIGHT * MAX_SPEED / JUMP_WIDTH;
var gravity : float = 2 * JUMP_HEIGHT * pow(MAX_SPEED, 2) / pow(JUMP_WIDTH,2);


func _physics_process(delta):
    
    # Add gravity
    velocity.y += gravity * delta
    
    # Jump
    if Input.is_action_just_pressed("jump") and is_on_floor():
        velocity.y = -jump_speed;
    
    # Move
    move_and_slide()

Doing this I can get a jump height of 112 px, not the desired 100 px.

Now I know the code works since if I slow down the process ( either by changing the time scale to 0.1, or by increasing JUMP_WIDTH to get a slower jump ) then the jump height goes to the desired 100 px.
This leads me to think that the problem comes from the move_and_slide() not being able to be precise given the speed of the jump.

The question then is : is there a way to increase the precision without slowing down the jump ?

Rafael
  • 1,281
  • 2
  • 10
  • 35
GD Clone
  • 83
  • 6

1 Answers1

0

I haven't tried this in Godot because it is awkward to work around move_and_slide...

But the idea would be to apply half the gravity before the motion, and half the gravity after.

    # Add half gravity
    velocity.y += gravity * delta * 0.5
    
    # Jump
    if Input.is_action_just_pressed("jump") and is_on_floor():
        velocity.y = -jump_speed;
    
    # Move
    move_and_slide()

    # Add half gravity
    velocity.y += gravity * delta * 0.5

This is based on Velocity Verlet. It is not quite the same form you will often find it, because move_and_slide is a black box, but I believe it should work...

This is te logic behind it: you are trying to compute the velocity and position at discrete chunks of the time. Which is approximating the integration of the acceleration, but using summation of rectangles... If you set the height of the rectangle to the curve at the start of the interval, you will undershoot the total. If you set the height of the rectangle to the curve at the end of the interval, you will overshoot the total. The middle is a better approximation.

Theraot
  • 31,890
  • 5
  • 57
  • 86