How to freeze/negate player's gravity for set time?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By soogy

I’m trying to make a dash mechanic, and my current code looks like this (for the player node):

 extends KinematicBody2D

onready var velocity = Vector2.ZERO
onready var run_spd
onready var gravity = 15
onready var jmp = 300
onready var dash_check = true
onready var double_dash = false
onready var timer = $Timer

func _physics_process(_delta):
	run_spd = (Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left"))*100
	velocity.x = lerp(velocity.x, run_spd, 0.2)
	velocity.x = clamp(velocity.x, -700, 700)
	if timer.time_left <= 0.02 or double_dash: # time_left <= 0 just didn't work..
		dash_check = true # dash recharge
	if Input.is_action_just_pressed("x") and dash_check and run_spd != 0:
		timer.start(0.8) # dash cooldown
		# lock velocity.y at current value, negate gravity??
		velocity.x *= 15 
		dash_check = false
		double_dash = false
	velocity.y += gravity
	if Input.is_action_just_pressed("ui_up") and (is_on_floor() or (is_on_wall() and Input.is_action_pressed("z"))):
		velocity.y -= jmp
	velocity.y = clamp(velocity.y, -300, 800)
	velocity = move_and_slide(velocity, Vector2.UP)
	if Input.is_action_pressed("ui_accept"):
		get_tree().change_scene("res://scene/game test.tscn")
	


func _on_double_dash_body_shape_entered(_body_rid, _body, _body_shape_index, _local_shape_index):
	double_dash = true


func _on_double_dash2_body_shape_entered(_body_rid, _body, _body_shape_index, _local_shape_index):
	double_dash = true


func _on_double_dash3_body_shape_entered(_body_rid, _body, _body_shape_index, _local_shape_index):
	double_dash = true


func _on_double_dash4_body_shape_entered(_body_rid, _body, _body_shape_index, _local_shape_index):
	double_dash = true
enter code here

My only idea I tried was this:

if Input.is_action_just_pressed("x") and dash_check and run_spd != 0:
		timer.start(0.8) # dash cooldown
		while timer.time_left >= 0.02:
			velocity.y = 0
		velocity.x *= 15 

However, I found out the hard way that Godot doesn’t like my while loops (it crashes, if anyone knows why please tell me). Any help would be appreciated, thanks in advance.

:bust_in_silhouette: Reply From: jgodfrey

First, the while loop is preventing the timer from counting down at all (since it runs on the same thread), so the exit condition will never be met - effectively hanging the game…

Really, you should be able to simply set the velocity.y to 0 in that section and start the timer. Then, in the timer’s timeout event, set the velocity.y value back to normal gravity.

You could also do this without a timer node at all, and instead simply subtract delta from your dash time (directly in _physics_process()) until you reach zero…

Thanks for the answer! It seems to work partially.
My code now looks like this:

if Input.is_action_just_pressed("x") and dash_check and run_spd != 0:
	velocity.y = 0
	timer.start(0.8) # dash cooldown
	if timer.time_left <= 0.02:
		velocity.y += gravity
	else:
		velocity.y = 0
	velocity.x *= 10

When the player is far in the air, the dash mechanic works as planned, however if the player jumps and then quickly dashes, gravity still acts on the player. Is there a problem with the code?

soogy | 2023-07-06 05:09

The new code looks like it’d have a few problems and isn’t really what I intended with my above input. A few comments / questions…

  • What action is the x input intended to trigger?
  • Why are you checking for time_left to be < 0.02?
  • Are you using the timer’s timeout event at all? If so, you don’t show it… If not, you need to be.

Rather than the if timer.time_left <= 0.02 (which isn’t likely to work as you expect because it’s inside action_just_pressed block of code), you should wire the timer’s timeout event and, when the call back fires, reset velocity.y to gravity.

So, something like:

if Input.is_action_just_pressed("x") and dash_check and run_spd != 0:
    velocity.y = 0
    timer.start(0.8) # dash cooldown

func _on_timer_timeout():
	pvelocity.y = gravity

jgodfrey | 2023-07-06 13:28