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
_jump_again()
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
_jump_again()
else:
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