How to implement jump buffer in finte state machine

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

Hi everyone :slight_smile:

I am making a platformer game in the godot engine.Some days ago I implemented finite state machines in my player’s code because I thought it was convenient.A while ago I also implemented coyote time. I took me some time because the tutorials I watched didn’t have finite state machines but got it working after some time. But now I wanted to add jumpbuffer to my game.I watched tutorials but they they didn’t have finite state machine or their state machines were not similar to mine.Can someone give me an idea on how to do it.

Note:I am using a finite state machine that uses match statement

Could you upload your code so we can see what the issue might be?

Gluon | 2022-05-03 22:32

  extends KinematicBody2D
var speed : int = 100
var acc : int = 25
var jumpforce : int = 37
var gravity : int = 70
var direction : int = -1
var is_dashing : bool = false
var is_dashing_upward : bool = false
var candash : bool = true
var is_paused : bool = false
var high : bool = false
var jumpwaspressed : bool = false
var state = STATES.AIR
var shake_amount : float = 1.8
var jump_time_to_peak : float = 0.22
var jump_time_to_descent : float = 0.20

onready var jump_velocity : float = ((2.0 * jumpforce) / jump_time_to_peak) * -1.0
onready var jump_gravity : float = ((-2.0 * jumpforce) / (jump_time_to_peak * jump_time_to_peak)) * -1.0
onready var fall_gravity : float = ((-2.0 * jumpforce) / (jump_time_to_descent * jump_time_to_descent)) * -1.0

enum STATES {FLOOR = 1, AIR, DOUBLEJUMP, WALL, LANDED, COYOTETIME, JUMPBUFFER}

var velocity : Vector2 = Vector2.ZERO

func _ready():
	pass
	
func landed_particles():
	var lan_particles = preload("res://Landed.tscn").instance()
	get_parent().add_child(lan_particles)
	lan_particles.position = $Position2D.global_position
	
func jump_particles():
	var jump_particle = preload("res://Jumped.tscn").instance()
	get_parent().add_child(jump_particle)
	jump_particle.position = $Position2D.global_position
		

func dash():
	if candash == true:
		if is_on_floor():
			if velocity.x > 99 or velocity.x < -99:
				gravity = 0
				$Particles2D.emitting = true
				is_dashing = true
				speed *= 3
				$Timer.start()
				candash = false		
		elif not is_on_floor() and (velocity.x > 90 or velocity.x < -90):
			if Input.is_action_pressed("jump"):
				gravity = 0
				$Particles2D.emitting = true
				is_dashing_upward = true
				speed *= 2.9
				velocity = Vector2(velocity.x, -250)
				$Timer.start()
				candash = false
			else:
				gravity = 0
				$Particles2D.emitting = true
				is_dashing = true
				speed *= 3.3 
				$Timer.start()
				candash = false
							

func set_direction():
	direction = 1 if not $AnimatedSprite.flip_h else -1
	$WallChecker.rotation_degrees = 0 if not $AnimatedSprite.flip_h else -180	
					
func _process(delta):
	if is_dashing == true or is_dashing_upward == true:
		$Camera2D.set_offset(Vector2( \
			rand_range(-1.5, 1.5) * shake_amount, \
			rand_range(-1.5, 1.5) * shake_amount \
		))
	else:
		$Camera2D.set_offset(Vector2.ZERO)					
func _physics_process(delta):
	apply_gravity(false)
	
	if state == 6:
		print("oof")
	
	velocity.y += get_gravity() * delta
	
	if velocity.y >= 350:
		velocity.y = 350

	if $Ground.is_colliding() and velocity.y >= 300:
		high = true
	
	if Input.is_action_just_pressed("ui_cancel"):
		get_tree().quit()
	elif Input.is_action_just_pressed("fullscreeen"):
		OS.window_fullscreen = !OS.window_fullscreen
		
	velocity = move_and_slide(velocity, Vector2.UP)	

	match state:
		STATES.FLOOR:
			if not is_on_floor():
				$CoyoteTimer.start()
				state = STATES.COYOTETIME
				continue
		
			if Input.is_action_pressed("right"):
				$AnimatedSprite.play("running")
				$AnimatedSprite.flip_h = false
				velocity.x = min(velocity.x + acc, speed)
			elif Input.is_action_pressed("left"):
				$AnimatedSprite.play("running")
				$AnimatedSprite.flip_h = true
				velocity.x = max(velocity.x + -acc, -speed)
			else:
				$AnimatedSprite.play("idle")
				velocity.x = lerp(velocity.x, 0, 0.3)
				
			if Input.is_action_just_pressed("jump"):
				jump_particles()
				velocity.y = jump_velocity
				state = STATES.AIR
				continue
				
			set_direction()

		STATES.AIR:
			if is_on_floor() and high == false:
				state = STATES.FLOOR
				continue
			elif is_on_floor() and high == true:
				state = STATES.LANDED
				continue	
			elif $WallChecker.is_colliding() and velocity.y > 0:
				if Input.is_action_pressed("left") and direction == -1:
					state = STATES.WALL
					continue
				elif Input.is_action_pressed("right") and direction == 1:
					state = STATES.WALL
					continue		
			
			if Input.is_action_pressed("right"):
				$AnimatedSprite.flip_h = false	
				velocity.x = speed
			elif Input.is_action_pressed("left"):
				$AnimatedSprite.flip_h = true
				velocity.x = -speed
			else:
				velocity.x = lerp(velocity.x, 0, 0.2)
			
			set_direction()	

		STATES.DOUBLEJUMP:
			if is_on_floor() and high == false:
				state = STATES.FLOOR
				continue
			elif is_on_floor() and high == true:
				state = STATES.LANDED
				continue
				
			elif $WallChecker.is_colliding() and velocity.y > 0:
				if Input.is_action_pressed("left") and direction == -1:
					state = STATES.WALL
					continue
				elif Input.is_action_pressed("right") and direction == 1:
					state = STATES.WALL
					continue
						
		
			if Input.is_action_pressed("right"):
				$AnimatedSprite.flip_h = false
				velocity.x = speed
			elif Input.is_action_pressed("left"):
				$AnimatedSprite.flip_h = true				
				velocity.x = -speed
			else:
				velocity.x = lerp(velocity.x, 0, 0.1)
				
			set_direction()
		
		STATES.WALL:
			if is_on_floor():
				state = STATES.FLOOR
				continue
			elif not $WallChecker.is_colliding():
				state = STATES.AIR
				continue	
			elif Input.is_action_just_released("left") or Input.is_action_just_released("right"):
				if is_on_floor():
					state = STATES.FLOOR
				elif not is_on_floor():
					state = STATES.AIR
			
			apply_gravity(true)	
			
		STATES.LANDED:
			landed_particles()
			high = false
			state = STATES.FLOOR
			continue	
			
		STATES.COYOTETIME:
			if Input.is_action_pressed("right"):
				$AnimatedSprite.play("running")
				$AnimatedSprite.flip_h = false
				velocity.x = min(velocity.x + acc, speed)
			elif Input.is_action_pressed("left"):
				$AnimatedSprite.play("running")
				$AnimatedSprite.flip_h = true
				velocity.x = max(velocity.x + -acc, -speed)
			else:
				$AnimatedSprite.play("idle")
				velocity.x = lerp(velocity.x, 0, 0.3)
				
			if Input.is_action_just_pressed("jump"):
				jump_particles()
				velocity.y = jump_velocity
	
			
						
	if not is_on_floor() and velocity.y < 0:
		$AnimatedSprite.play("jump")
	elif not is_on_floor() and velocity.y > 0:
		$AnimatedSprite.play("falling") 
	if direction == 1:
		$AnimatedSprite.flip_h = false
	elif direction == -1:
		$AnimatedSprite.flip_h = true
	
	if state == 4:
		$AnimatedSprite.play("isonwall")	
		
	if is_dashing == true and is_dashing_upward == false:
		velocity.y = 0	
		
	if Input.is_action_just_pressed("dash"):
		dash()	

func apply_gravity(slow_fall: bool):
	if slow_fall:
		velocity.y = 22
		
func get_gravity() -> float:
	return jump_gravity if velocity.y < 0.0 else fall_gravity	
	
func _on_Timer_timeout():
	gravity = 20
	$Particles2D.emitting = false
	is_dashing = false
	is_dashing_upward = false
	speed = 100
	$CandashTimer.start()
	
func _on_CandashTimer_timeout():
	candash = true

func _on_GhostTimer_timeout():
	if is_dashing == true or is_dashing_upward == true:
		var this_ghost = preload("res://Ghost.tscn").instance()
		get_parent().add_child(this_ghost)
		this_ghost.position = position
		this_ghost.texture = $AnimatedSprite.frames.get_frame($AnimatedSprite.animation, $AnimatedSprite.frame)
		this_ghost.scale = $AnimatedSprite.scale
		this_ghost.flip_h = $AnimatedSprite.flip_h

func _on_CoyoteTimer_timeout():
	state = STATES.AIR

TopBat69 | 2022-05-04 05:41

:bust_in_silhouette: Reply From: Inces

What is the problem with this ? Why don’t You just set state to JUMPBUFFER in place of STATE.AIR when your jump is pressed ?
All your JUNPBUFFER state needs to do is count some time before changing to AIR. You can do it by choosing treshold of time and checking if this amount of delta time has accumulated using some higher scope variable

var tick : float
states.jumpbuffer :
      animationplayer.play("jumptelemark")
      tick += delta
      if tick > treshold :
           state = states.air
           tick = 0