Run a function multiple times overtime

Godot Version



Hi fellows, I have a simple function to make my character jump when called. Like so:

func perform_jump(target):
    target.velocity.y = -500
    target.velocity.x = 200
    print("Jump ran")

Is it possible for me to run this function, let’s say, 2 times over a certain amount of time? If so, how can I implement this? Thanks

Jump twice over 4.2 seconds.

func perform_jump():
	target.velocity.y = -500
	target.velocity.x = 200
	await get_tree().create_timer(4.20).timeout
	target.velocity.y = -500
	target.velocity.x = 200

For full context, I’m trying to call the function based on how many times player presses a button.

I have this variable in my global game manager file: var jump_action_iteration: int = 0

And when player presses a UI button, I’m incrementing it like so:

func _on_button_pressed():
	GameManager.jump_action_iteration += 1

So, let’s say the player presses the button thrice, I want them to jump three times consecutively in response.

I’m doing this:

for i in range(GameManager.jump_action_iteration):

Even though it calls the function correspondingly to the amount of time the button was presssed, it only makes the player jump once.

What you’re doing is calling the function “perform_jump” i times, but all the calls occur on the same frame, so basically the velocity of the player is set to the defined values i times (this is the same as doing a=6; a=6; a=6;). Then, in the next frame, the physics simulation does its job on the player.

What you’re looking for is to perform the jump i times, but what does it mean? The player must jump after he finished the previous one and do this i times? Or he must do it i times, but after the first jump, he needs to jump after x seconds?

In the second case, you can use the snippet of code provided before (using a for loop) or using a timer.
The first case is more tricky because, again, when a jump is finished? Maybe we can assume that when the player is on the floor he can jump again. In that case in the player script you can check how many jumps he must still do and if it is on floor (assuming your character is a CharecterBody2D you can use the built-in function is_on_floor()): if true call the jump function.

Assuming you are calling the function inside _physics_process() or _process(), can you use delta to increase a counter, and check, after a certain amount of time, if the function can be called again? That’s the approach I am using to loop through animations, if the player press the same action in a short period of time, the animations are played in sequence. If the time between presses are too long, the index animation is reset.

oh ok, I think I understand what you’re trying to do better now. Basically air jumps right? You’ll need to adjust a few function names and such in code below, there’s a couple obvious placeholders. This code is untested, if you encounter problems with it let me know and I’ll actually test it out here.

# vv-- this part goes in the scripts global (top level) scope --vv

# maximum number of air jumps that can happen before the player must
# touch solid ground to reset
const MAX_DOUBLE_JUMPS: int = 4;

# this is the minimum timing between queued jumps.  If a new jump is 
# queued after this time has already occured since the last jump, the jump
# happens immediately.  If not, the jump is added to the pending jumps and
# happens after this much time has passed since the last jump activation.
const JUMP_COOLDOWN_TIME: float = 0.25;

var queued_jumps : int = 0;
var jump_cooldown:float = 0.0;
var jumps_since_last_touch_ground = 0;

# ^^-- end of global scope additions --^^

func _physics_process(_delta):
	# put this somewhere in the physics process
	jump_cooldown = max(0.0, jump_cooldown - _delta)
	if (_is_player_on_floor()):
		jumps_since_last_touch_ground = 0
		jump_cooldown = 0;  # if touching ground, reset cooldown immediately
	if (queued_jumps > 0 and jump_cooldown <= 0):
		queued_jumps -= 1

func _is_player_on_floor() -> bool:
	# however you'd like to do this.  maybe target.is_on_floor(), or 
	# whatever you like.
	return target.is_on_floor()

func _my_input_handling( ):
	# naturally you have some other, actual input handling, put this in 
	# there.  Make sure you're responding to the 'just_pressed' state, and 
	# not 'currently_down'.
	var jump_signal = however_you_check_for_jump_input()
	if (jump_signal ):
		if ( queued_jumps  +  jumps_since_last_touch_ground < MAX_DOUBLE_JUMPS ):
			if ( jump_cooldown <= 0.0 ):
				# either this is the first jump, or enough time has passed since last
				# jump to activate again, so activate immediately and don't add to 
				# the jump queue
				queued_jumps += 1
				# take no further action at this point because maybe they're already 
				# in mid cooldown (delay until next double jump)

func _jump_again():
	jump_cooldown = JUMP_COOLDOWN_TIME;
	jumps_since_last_touch_ground += 1;
	target.velocity.y = -500
	target.velocity.x = 200

Will try this and modify some parts of this. I will let you know if it works, thanks :+1:

1 Like