Godot Version
4.7.1
Question
Can anyone help me with this code, programmed a run function for the the character but he only goes only one direction and doesn’t stop, and moves when hes not moving.
match active_state:
State.idle:
velocity.x = _direction * speed
if _direction:
$AnimatedSprite2D.flip_h = _direction < 0
else:
$AnimatedSprite2D.play("idle")
if Input.is_action_just_pressed("jump"):
active_state = State.jump
if not is_on_floor():
active_state = State.fall
if Input.is_action_just_pressed("ui_run"):
active_state = State.run
if Input.is_action_just_released("ui_run"):
active_state = State.idle
if Input.is_action_just_pressed("dash") and _direction:
switch_state(State.dash)
State.run:
if _direction:
$AnimatedSprite2D.play("run")
$AnimatedSprite2D.flip_h = _direction < 0
velocity.x += acceleration * _delta
velocity.y += gravity * _delta
if Input.is_action_just_released("ui_run"):
switch_state(State.idle)
if Input.is_action_just_pressed("jump"):
switch_state(State.jump)
State.run:
$AnimatedSprite2D.play("walk")
var _direction := Input.get_axis("ui_left", "ui_right")
velocity.x = _direction * 1.5 * speed
Approximately like that
# the _direction is defined there, now you can access it from anywhere in that script.
@onready var _direction : float = 0.0
# other your code there
func _physics_process(delta: float) -> void:
match active_state:
State.idle:
_idle(delta) # incapsualted to separated function
State.walk:
_walk(delta) # same as above
State.run:
_run(delta) # same as above
func _idle(delta: float) -> void:
$AnimatedSprite2D.play("idle")
if Input.is_action_just_pressed("dash"):
switch_state("dash")
return
if not is_on_floor():
switch_state("fall")
return
# in case you want chang state to run
if Input.is_action_just_pressed("jump"):
# not change state yourself, just add velocity to make it change to fall automatically.
# if you need separated jump state you should add logic that runs on entering jump state.
velocity.y += JUMP_IMPULSE
# add input control in idle to determine when to change state to run
_direction = Input.get_axis("ui_left", "ui_right")
velocity.x = _direction * 1.5 * speed
velocity.y += gravity * delta
# use velocity instead of is_action_just_pressed()
if velocity.x != 0:
switch_state("run")
func _walk(delta: float) -> void:
$AnimatedSprite2D.play("walk")
# i suppose you want to let player dash from walk state ...
if Input.is_action_just_pressed("dash"):
switch_state("dash")
return
# ... and in run state ...
if Input.is_action_just_pressed("ui_run"):
switch_state("run")
return
# ... and in fall state
if not is_on_floor():
switch_state("fall")
return
# same as in previous func, changing direction while running
_direction = Input.get_axis("ui_left", "ui_right")
velocity.x = _direction * 1.5 * speed
velocity.y += gravity * delta
# when no input is given switching back to idle state
if velocity.x == 0:
switch_state("idle")
func _run(delta: float) -> void:
$AnimatedSprite2D.play("run")
if not is_on_floor():
switch_state("fall")
return
if Input.is_action_just_pressed("jump"):
velocity.y += JUMP_IMPULSE
return
# use sign() function to allow running in different directions
velocity.x += sign(_direction) * acceleration * _delta
velocity.y += gravity * _delta
#returning to run state
if not Input.is_action_pressed("ui_run"):
switch_state(State.idle)
# rest of your code
Do you have several ‘run’ options in a single ‘match’ block? In that case only the first ‘run’ will work. The problem with continuing running happens because of you don’t zero direction and velocity neither in ‘idle’ state nor in ‘run’ state. Also you shadows ‘_direction’ in second ‘run’ block, if you want to change ‘_direction’ make it global and don’t use ‘var’ keyword in ‘run’ and change it not only in ‘run’ state, but also in ‘idle’ state.
Also i’d recommend not to use is_action_just_released() method everywhere, use current velocity to identify when you should switch states. For easier debugging and state programming i’d recommended to use ‘state charts’ plugin.
thank you.
i copied and pasted your code but i got errors
That looks like you pasted State.fall: line outside of match block. Check this match syntax ref: GDScript reference — Godot Engine (stable) documentation in English .