Godot Version
4.3
Question
I have set up a state machine. If it is on the ROLL state, the y velocity of the character (stored just before hitting the floor in y_force global variable) is assigned to the x velocity multiplied by get_axis(). Every ROLL physics frame, the y_force is reduced by 2.
If it goes below 30, the below threshold variable is set to true, and if its set to true, the machine is allowed to change to a different state.
Whenever it enters the ROLL state, it automatically exits to other of the states, on the first frame.
(Regardless of the y_force being much greater.)
The code:
extends Node2D
@onready var player:Character = self.owner
@onready var ray_cast_2d: RayCast2D = $"../Hitbox/RayCast2D"
@onready var timer: Timer = $"../Timer"
@onready var animated_sprite_2d: AnimatedSprite2D = $"../AnimatedSprite2D"
#Basic movement
const velocity_vector := 20
const jump_force := 50
#tweaks
const cenit := -22.25
var has_released_jump := false
var has_jumped := false
#gravity
const base_gravity := 35
var current_Gravity := base_gravity
const fall_gravity := 75
#roll
var y_force:float = 0
var previous_state = default_state
var below_threshold:bool = false
#estados
enum {IDLE,RUNNING,ON_AIR,ROLL}
const default_state = IDLE
var current_state = default_state
func ready():
ray_cast_2d.enabled = false
func _physics_process(delta: float) -> void:
match current_state:
IDLE:
animated_sprite_2d.play(&"0-Idle")
ray_cast_2d.enabled = false
has_jumped = false
has_released_jump = false
current_Gravity = base_gravity
player.velocity.x = 0
#salto
if Input.is_action_just_pressed("Jump") and player.is_on_floor():
player.velocity.y -= jump_force
#cambios
if Input.is_action_pressed("Left") and player.is_on_floor() and not Input.is_action_pressed("Right") or Input.is_action_pressed("Right") and player.is_on_floor() and not Input.is_action_pressed("Left"):
current_state = RUNNING
previous_state = IDLE
elif not player.is_on_floor():
current_state = ON_AIR
previous_state = IDLE
RUNNING:
ray_cast_2d.enabled = false
has_jumped = false
has_released_jump = false
current_Gravity = base_gravity
#movimiento
if Input.is_action_pressed("Left"):
player.velocity.x = velocity_vector * -1
animated_sprite_2d.scale.x = -1
animated_sprite_2d.play(&"1-Walk")
if Input.is_action_pressed("Right"):
player.velocity.x = velocity_vector
animated_sprite_2d.scale.x = 1
animated_sprite_2d.play(&"1-Walk")
if Input.is_action_pressed("Left") and Input.is_action_pressed("Right"):
player.velocity.x = 0
#salto
if Input.is_action_just_pressed("Jump") and player.is_on_floor():
player.velocity.y -= jump_force
if previous_state == ON_AIR and Input.is_action_pressed("Down"):
current_state = ROLL
previous_state = ON_AIR
#cambios
if not Input.is_action_pressed("Left") and not Input.is_action_pressed("Right") and player.is_on_floor() or Input.is_action_pressed("Left") and Input.is_action_pressed("Right") and player.is_on_floor():
current_state = IDLE
previous_state = RUNNING
elif not player.is_on_floor():
current_state = ON_AIR
previous_state = RUNNING
ON_AIR:
animated_sprite_2d.stop()
player.velocity.y = player.velocity.y + current_Gravity * delta
#movimiento
if Input.is_action_pressed("Left"):
animated_sprite_2d.scale.x = -1
player.velocity.x = velocity_vector * -1
if Input.is_action_pressed("Right"):
animated_sprite_2d.scale.x = 1
player.velocity.x = velocity_vector
if Input.is_action_pressed("Left") and Input.is_action_pressed("Right"):
player.velocity.x = 0
if Input.is_action_pressed("Down"):
player.velocity.y += current_Gravity/10
#release
if Input.is_action_just_released("Jump") and not has_released_jump:
player.velocity.y = 0
player.velocity.y += 10
has_released_jump = true
current_Gravity = fall_gravity
if Input.is_action_pressed("Jump"):
has_jumped = true
if has_jumped and player.velocity.y >= cenit:
current_Gravity = fall_gravity
has_released_jump = true
if player.velocity.y >= cenit:
ray_cast_2d.enabled = true
else:
ray_cast_2d.enabled = false
if ray_cast_2d.is_colliding():
y_force = player.velocity.y
if not below_threshold:
player.velocity.x = (y_force * Input.get_axis("Left","Right"))
if y_force > 0:
y_force -= 2
if y_force < 30:
below_threshold = true
else:
below_threshold = false
#cambios
if not Input.is_action_pressed("Left") and not Input.is_action_pressed("Right") and player.is_on_floor() or Input.is_action_pressed("Left") and Input.is_action_pressed("Right") and player.is_on_floor():
current_state = IDLE
previous_state = ON_AIR
elif Input.is_action_pressed("Left") and player.is_on_floor() or Input.is_action_pressed("Right") and player.is_on_floor():
current_state = RUNNING
previous_state = ON_AIR
ROLL:
print(y_force)
player.velocity.y = player.velocity.y + current_Gravity * delta
animated_sprite_2d.play(&"4-Roll")
player.velocity.x = (y_force * Input.get_axis("Left","Right"))
if Input.is_action_just_pressed("Jump") and player.is_on_floor():
player.velocity.y -= jump_force
if y_force > 0:
y_force -= 2
#velocity_treshold
if y_force < 30:
below_threshold = true
else:
below_threshold = true
#cambios
if below_threshold == true:
if not Input.is_action_pressed("Left") and not Input.is_action_pressed("Right") and player.is_on_floor() or Input.is_action_pressed("Left") and Input.is_action_pressed("Right") and player.is_on_floor():
current_state = IDLE
previous_state = ROLL
elif not player.is_on_floor():
current_state = ON_AIR
previous_state = ROLL
elif Input.is_action_pressed("Left") and player.is_on_floor() or Input.is_action_pressed("Right") and player.is_on_floor():
current_state = RUNNING
previous_state = ROLL
player.move_and_slide()
If you decide to, thank you for trying to help me.