0 votes

Hi everyone :)

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

in Engine by (60 points)
edited by

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

  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

1 Answer

0 votes

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
by (5,557 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.