## the cc0 assets used for the sprite are from https://kenney.nl/assets/new-platformer-pack @icon("res://_icons/icon_hero.png") class_name Hero extends CharacterBody2D #local vars - all with @export for easier debugging purposes @export var move_speed: float = 600.0 #find a value that fits best for you @export var jump_velocity: float = -2000.0 #going up in 2D means decreasing the y value in coordinates @export var jump_buffer: bool = false #check if jump buffer is available @export var was_on_floor: bool = false #little helper variable for the jump buffer @export var coyote_time: bool = false #check if coyote time is available @export var double_jump: bool = false #check if a second jump is available @export var direction: float = 0.0 #>0 means right, <0 means left #nodes @onready var sprite: AnimatedSprite2D = $Sprite #reference to the visible sprite @onready var timer_jump_height: Timer = Timer.new() #create a timer for variable jump height @onready var timer_jump_buffer: Timer = Timer.new() #create a timer for jump input buffer @onready var timer_coyote_time: Timer = Timer.new() #create a coyote time timer #functions func _ready() -> void: #configure variable jump height timer timer_jump_height.name = "TimerJumpHeight" #easier to find it while debugging timer_jump_height.wait_time = 0.2 #find a value that fits best for you timer_jump_height.one_shot = true timer_jump_height.timeout.connect(_variable_jump_height) #connect function with timeout signal add_child(timer_jump_height) #configure jump buffer timer timer_jump_buffer.name = "TimerJumpBuffer" timer_jump_buffer.wait_time = 0.3 #find a value that fits best for you timer_jump_buffer.one_shot = true timer_jump_buffer.timeout.connect(_stop_jump_buffer) add_child(timer_jump_buffer) #configure coyote time timer timer_coyote_time.name = "TimerCoyoteTime" #easier to find it while debugging timer_coyote_time.wait_time = 0.2 #find a value that fits best for you timer_coyote_time.one_shot = true timer_coyote_time.timeout.connect(_stop_coyote_time) #connect function with timeout signal add_child(timer_coyote_time) func _physics_process(delta: float) -> void: _controls(delta) was_on_floor = is_on_floor() move_and_slide() #start falling if was_on_floor and not is_on_floor() and velocity.y >= 0: coyote_time = true timer_coyote_time.start() #touching ground if not was_on_floor and is_on_floor(): double_jump = true if jump_buffer: jump_buffer = false _jump() print_rich("[color=Gold]Buffered jump[/color]") _update_animation(direction) ##the _controls functions will handle user input and manipulate the node's position through CharacterBody2D class' velocity func _controls(delta: float) -> void: #apply gravity if not is_on_floor() and not coyote_time: velocity += get_gravity() * delta * 5.0 #jump if Input.is_action_just_pressed("jump"): timer_jump_height.start() _jump() #move in direction direction = Input.get_axis("walk_left", "walk_right") if direction: velocity.x = direction * move_speed else: velocity.x = move_toward(velocity.x, 0, move_speed) ##ascend the hero in the air func _jump() -> void: if is_on_floor() or coyote_time: velocity.y = jump_velocity if coyote_time: coyote_time = false print_rich("[color=Chartreuse]Coyote jump[/color]") elif Input.is_action_just_pressed("jump") and double_jump: double_jump = false velocity.y = jump_velocity print_rich("[color=Purple]Double jump[/color]") elif not jump_buffer: jump_buffer = true timer_jump_buffer.start() ##this function will make the hero stop ascending in the y position making the jump shorter func _variable_jump_height() -> void: #is connected with timer_jump_height.timeout signal if not Input.is_action_pressed("jump"): print_rich("[color=Hot_Pink]Short jump[/color]") if velocity.y < 0: velocity.y = 0 #let gravity handle it else: print_rich("[color=Plum]High jump[/color]") func _stop_jump_buffer() -> void: #is connected with timer_jump_buffer.timeout signal jump_buffer = false func _stop_coyote_time() -> void: #is connected with timer_coyote_time.timeout signal coyote_time = false func _update_animation(dir) -> void: if dir > 0: #right direction sprite.flip_h = false elif dir < 0: #left direction sprite.flip_h = true if is_on_floor(): if dir == 0: sprite.play("idle") else: sprite.play("walk") else: if velocity.y < 0: sprite.play("jump") elif velocity.y > 0: sprite.play("fall")
or share this direct link: