Godot Version
Godot 4.6 Beta-2 (32-bit)
Question
Jump caused by jump_buffer_timer is not a variable jump.
Hello! I hope that you are doing well!
I am pretty new to Godot and game dev, so correct my silly mistakes (if any, of course).
I have created a 2D platformer from a video of brackeys (How to make a game), I added a nice amount of things, two of them were jump buffering and variable jump.
As the question says, whenever I jump normally, when on the floor, it’s a variable jump, but when the jump is triggered by the jump buffer, it’s a full jump, which I don’t want.
player.gd (I think only the physics_process function is important):
extends CharacterBody2D
class_name Player
signal health_changed
signal hit
signal died
const SPEED: float = 130.0
const JUMP_VELOCITY: float = -300.0
const JUMP_BUFFER_TIME: float = 0.12
const MAX_HEALTH: int = 3
@export var health: int = 3:
set(desired_value):
health = clamp(desired_value, 0, MAX_HEALTH)
health_changed.emit()
var direction: float
var jump_available: bool = true
var jump_requested: bool = false
var knockback: Vector2 = Vector2.ZERO # Direction and speed of knockback.
var knockback_timer: float = 0.0
var _jump_buffer_timer: float = 0.0
#region @onready var
@onready var state_machine: Node = $StateMachine
@onready var collision_shape_2d: CollisionShape2D = $CollisionShape2D
@onready var death_timer: Timer = $Timers/DeathTimer
@onready var hit_timer: Timer = $Timers/HitTimer
@onready var _animated_sprite_2d: AnimatedSprite2D = $AnimatedSprite2D
@onready var _jump_sound: AudioStreamPlayer = $Sounds/JumpSound
@onready var _hurt_sound: AudioStreamPlayer = $Sounds/HurtSound
@onready var _coyote_timer: Timer = $Timers/CoyoteTimer
#endregion
func _ready() -> void: # Testing purposes ONLY.
Engine.time_scale = 0.4
func _physics_process(delta: float) -> void:
#region if dead or hit
# Avoid running movement when player is dead.
if state_machine.current_state is PlayerDeath:
if not is_on_floor():
velocity += get_gravity() * delta
move_and_slide()
return
elif state_machine.current_state is PlayerHit:
if not is_on_floor():
velocity += get_gravity() * delta
if knockback_timer > 0.0: # Turn on knockback and tick down timer.
velocity = knockback
knockback_timer -= delta
if knockback_timer <= 0.0: # Turn off knock back.
knockback = Vector2.ZERO
if _jump_buffer_timer > 0.0:
_jump_buffer_timer = 0.0
move_and_slide()
return
#endregion
# Implement jump_buffer.
if _jump_buffer_timer > 0.0:
_jump_buffer_timer -= delta # Reduce by delta if _jump_buffer_timer > 0.0.
else:
jump_requested = false
# Add the gravity.
if not is_on_floor():
velocity += get_gravity() * delta
if _coyote_timer.is_stopped():
_coyote_timer.start()
else: # Do when on floor.
if not jump_available:
_coyote_timer.stop()
jump_available = true
# Handle jump.
if jump_available and jump_requested and _jump_buffer_timer > 0.0:
velocity.y = JUMP_VELOCITY
_jump_buffer_timer = 0.0
elif velocity.y < 0.0:
if Input.is_action_just_released("jump"):
velocity.y *= 0.5
# Find direction: -1, 0, 1
direction = Input.get_axis("move_left", "move_right")
# Flip the AnimatedSprite2D horizontally accordingly.
if direction > 0:
_animated_sprite_2d.flip_h = false
elif direction < 0:
_animated_sprite_2d.flip_h = true
# Apply movement logic.
if direction:
velocity.x = direction * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
move_and_slide()
func _input(event: InputEvent) -> void:
if event.is_action_pressed("jump"):
jump_requested = true
_jump_buffer_timer = JUMP_BUFFER_TIME
func _on_coyote_timer_timeout() -> void:
jump_available = false
func _on_death_timer_timeout() -> void:
Engine.time_scale = 1.0
get_tree().reload_current_scene()
func apply_knockback(knockback_direction: Vector2, force: float, knockback_duration: float) -> void:
knockback = knockback_direction * force
knockback_timer = knockback_duration
func hurt() -> void:
health -= 1
if health == 0:
die()
return
hit.emit()
func die() -> void:
died.emit()
func play_animation(animation_name: String) -> void:
_animated_sprite_2d.play(animation_name.to_lower())
func play_sound(sound_name: String) -> void:
match sound_name.to_lower():
"jump":
_jump_sound.play()
"hurt":
_hurt_sound.play()
_:
print("WARNING: Sound named '" + sound_name + "' not found.")
player_idle.gd:
extends State
class_name PlayerIdle
var player: Player
func physics_update(_delta: float) -> void:
if player.jump_available and player.jump_requested:
Transitioned.emit(self, "Jump")
return
if player.is_on_floor():
if player.direction == 0:
player.play_animation("idle")
else:
player.play_animation("run")
Thanks a lot for your precious time!
LL