Increase the time of the character being at the peak of the jump

Godot Version

<4.2>

Question

<how can i increase the time until peak of the jump without changing jump height?
I would appreciate if you could teach me how to keep my character to stay in the air for a longer time while keeping the height constant.

the code for jump i use is:

@export var jumpmove_height : float
@export var jump_time_to_peak : float
@export var jump_time_to_descent : float

@onready var jump_velocity : float = ((2.0 * jumpmove_height) / jump_time_to_peak) * -1.0
@onready var jump_gravity : float = ((-2.0 * jumpmove_height) / (jump_time_to_peak * jump_time_to_peak)) * -1.0
@onready var fall_gravity : float = ((-2.0 * jumpmove_height) / (jump_time_to_descent * jump_time_to_descent)) * -1.0

player.velocity.y = -player.jumpmove_height

Here you can set how high you want to jump and how much time it should take with jump_time_to_peak and jump_height.
You can use the same calculation if you want separate jump_gravity and fall_gravity.

var jump_time_to_peak: float = 1.0
var jump_height: float = 1.0
var jump_velocity: float = (jump_height / jump_time_to_peak) * 2.0
var gravity: float = jump_velocity / jump_time_to_peak

func _physics_process(delta: float):
	if not is_on_floor():
		velocity.y -= gravity * delta

	if Input.is_action_just_pressed("jump"):
		velocity.y = jump_velocity

	move_and_slide()
1 Like

Thank you for your answer.
i am quiet not sure what you mean by " You can use the same calculation if you want separate jump_gravity and fall_gravity." Could you specify more about this please ?

Well, in your post you had separate jump_gravity and fall_gravity. You could calculate a separate fall gravity the same way, if you want the player to fall at a different speed:

var jump_time_to_descent: float = 1.0
var descent_velocity: float = (jump_height / jump_time_to_descent) * 2.0
var fall_gravity: float = descent_velocity / jump_time_to_descent

You would have to detect somehow when the player reached peak height and started falling to start applying the fall gravity instead of the jump gravity, don’t know if you have code for that already.

1 Like

i used this line of code for fall gravity

func get_gravity() -> float:
	#return jump_gravity if velocity.y < 0.0 else fall_gravity
1 Like

I somehow managed to make it work! Thank you very much for your kind help!!

1 Like

one more thing id like to ask. If i want to add air jump, what should the calculation be? because player cannot jump properly while falling.

You’re welcome :slight_smile: You could use the same calculation, no?

var air_jump_time_to_peak: float = 1.0
var air_jump_height: float = 1.0
var air_jump_velocity: float = (jump_height / jump_time_to_peak) * 2.0

Or just something like var air_jump_velocity = jump_velocity / 2 to make air jump half as high as normal jump for example. I’m not sure that’s what you mean.

character cannot jump high enough while falling maybe because of descent velocity? simply multiplying the jump velocity only for air jump does not solve the problem. this is what happens.
ezgif-4-acae511f06

if Input.is_action_just_pressed("jump"):
		velocity.y = jump_velocity

This should set velocity.y to jump_velocity no matter if the player is in the air or not, so the jump should be always the same. Is your jump code different? Make sure you’re using = and not +=. Other than that I don’t really know :confused:

I am using node base state machine which should not be the cause of the issue. and Im using -=.

inside player script:

var jump_time_to_peak: float = 0.4
var jump_height: float = 87.0
var jump_velocity: float = (jump_height / jump_time_to_peak) * 2.0
var jump_gravity: float = jump_velocity / jump_time_to_peak
var jump_time_to_descent: float = 0.3
var descent_velocity: float = (jump_height / jump_time_to_descent) * 2.0
var fall_gravity: float = descent_velocity / jump_time_to_descent

func get_gravity() -> float:
	return jump_gravity if velocity.y < 0.0 else fall_gravity

inside the jump state script:

func enter(msg := {}) -> void:
	print("state jump")
	player.velocity.y -= player.jump_velocity
	player.air_jump = true

func physics_update(delta: float) -> void:	
	
	player.velocity.y += player.get_gravity() * delta 
	player.move_and_slide()

Isn’t that the problem? The upwards jump velocity will be smaller while the player is falling.

well, i tried player.velocity.y = player.jump_velocity. and now player jump downward. I think it should be --= since gravity is positive.

Oh right, but then just make jump_velocity negative.

var jump_velocity: float = -(jump_height / jump_time_to_peak) * 2.0

Then you can use = to jump.

id like to stick with -= since var jump_velocity: float = -(jump_height / jump_time_to_peak) * 2.0 made player to jump super high even the value of jump height is small. maybe there is some problem in fall state? or maybe in airjump code?

my fall state code:

extends PlayerState

@export var _animation_player: NodePath
@onready var animation_player:AnimationPlayer = get_node(_animation_player)

func enter(_msg := {}) -> void:
	print("state fall")
	animation_player.play("PlayerFall") #Play Animation
	return

func physics_update(delta: float) -> void:
	player.sprite_flip()
	
	if not is_zero_approx(player.get_input_direction()): 
		player.velocity.x = lerpf(player.velocity.x, player.get_input_direction() * player.speed, player.acceleration * delta)
	else: 
		player.velocity.x = lerpf(player.velocity.x, 0, player.air_friction * delta)

	player.velocity.y += player.get_gravity() * delta 
	player.move_and_slide()

	if Input.is_action_just_pressed("jump") and player.air_jump:
		state_machine.transition_to("AirJump")
		player.air_jump = false

	if player.is_on_floor():
		if is_zero_approx(player.get_input_direction()): 
			state_machine.transition_to("Idle")
		else: 
			state_machine.transition_to("Run")

airjump:

extends PlayerState

@export var _animation_player: NodePath
@onready var animation_player:AnimationPlayer = get_node(_animation_player)

func enter(msg := {}) -> void:
	animation_player.play("PlayerJump") 
	print("state airjump")
	player.velocity.y -= player.jump_velocity

func physics_update(delta: float) -> void:
	player.sprite_flip()
	
	if not is_zero_approx(player.get_input_direction()): 
		player.velocity.x = lerpf(player.velocity.x, player.get_input_direction() * player.speed, player.acceleration * delta)
	else: 
		player.velocity.x = lerpf(player.velocity.x, 0, player.air_friction * delta)

	player.velocity.y += player.get_gravity() * delta 
	player.move_and_slide()

	if player.velocity.y > 0.0: 
		state_machine.transition_to("Fall")
		return
	
	if player.is_on_floor():
		if is_zero_approx(player.get_input_direction()): 
			state_machine.transition_to("Idle")
		else: 
			state_machine.transition_to("Run")