Dash/Movement help

Godot Version

4.2

Question

So… I’ve created a FSM within the player script and am running into a small issue with the dash and movement.

Dash: In-short I simply want to have the dash timed. So after 0.5 seconds the player will stop moving no matter if they hold or press the dash key.

Movement: I’m trying to create a celeste dash, basically where the player is unable to change direction during the dash.

extends CharacterBody2D
class_name PC

var walk_speed = 250
var dash_speed = 600
var accel = 100

var direction: Vector2
var dash_vector = Vector2.LEFT

enum States { Idle, Move, Dash, Death }

var state = States.Idle

func change_state(newstate):
	state = newstate 

func _physics_process(delta):
	match state:
		States.Idle:
			IdleData()
		States.Move:
			MoveData(delta)
		States.Dash:
			DashData()
		States.Death:
			DeathData()

func IdleData():
	print("Idle")
	pass

func MoveData(delta):
	print("move")
	direction = Input.get_vector("Key_Left", "Key_Right", "Key_Up", "Key_Down")
	velocity = lerp(velocity, walk_speed * direction, accel * delta)
	velocity.normalized()
	
	move_and_slide()

func DashData():
	print(velocity)
	if direction != Vector2.ZERO:
		dash_vector = direction.normalized()
	velocity = dash_speed * dash_vector
	
	move_and_slide()

func DeathData():
	pass

func _input(delta): #add death event for once PC dies
	if Input.is_action_just_pressed("Dash"):
		change_state(States.Dash)
	elif Input.get_vector("Key_Left", "Key_Right", "Key_Up", "Key_Down"):
		change_state(States.Move)
	else:
		change_state(States.Idle)

You can use a one-shot timer like this to change state from dash to idel after 0.5s.

get_tree().create_timer(0.5).timeout.connect(change_state.bind(States.Idle))

To stop the player from moving when dashing, you can use a guard in form of a bool i.e

var can_move: bool = true

When state is changed to dash, set can_move to false. Before changing state to move in _input, check first if can_move is true.

To reset can_move to true after dash is complete, the updated one shot timer will look like this:

func _input(delta):
    ...
	if Input.is_action_just_pressed("Dash"):
        can_move = false
		change_state(States.Dash)
        ##This calls the _end_dash function after 0.5seconds
        get_tree().create_timer(0.5).timeout.connect(_end_dash)
    ...

func _end_dash() -> void:
   change_state(States.Idle)
   can_move = true

The movement works, but the dash doesn’t end if I’m holding it. Also if I’m not moving prior to pressing the dash key, the dash wont work at all.

func MoveData(delta):
	print("move")
	if !is_dashing:
		direction = Input.get_vector("Key_Left", "Key_Right", "Key_Up", "Key_Down")
		velocity = lerp(velocity, walk_speed * direction, accel * delta)
		velocity.normalized()
	
	move_and_slide()

func DashData():
	print(velocity)
	if direction != Vector2.ZERO:
		is_dashing = true
		$dash_timer.start()
		dash_vector = direction.normalized()
	velocity = dash_speed * dash_vector
	
	move_and_slide()


func DeathData():
	pass

func _input(delta): #add death event for once PC dies
	if Input.is_action_just_pressed("Dash") && can_dash && !is_dashing:
		change_state(States.Dash)
	elif Input.get_vector("Key_Left", "Key_Right", "Key_Up", "Key_Down"):
		change_state(States.Move)
	else:
		change_state(States.Idle)

func _on_dash_timer_timeout():
	is_dashing = false

Not sure what is wrong, but are you sure your code can reach the point it changes to Idle? You should add a print statement there to be sure it changes to Idle.

The easiest way will be to just change to idle when dash timer is finished.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.