Question
Hi everyone,
Rather of attempting to transfer the complete design at once, I chose to begin the migration with the most basic component of my state machine system.
Replicating the state machine architecture from a functional “sample” project into a new “target” project is my aim. I’m attempting to replicate the structure of the states, handlers, and actions rather than the gameplay itself .
I am currently concentrating on the states of the player s.
StatePlayerBase.gd
extends StateBase
class_name StatePlayerBase
var player_handler:PlayerStateHandler
var player:GameCharacter
func _init(state_handler:BaseStateHandler) -> void:
super._init(state_handler)
player_handler = state_handler as PlayerStateHandler
player = player_handler.player
SignalsManager.on_input.connect(on_input)
func on_input(_inputs_dict:Dictionary):
pass
StatePlayerWalk.gd
extends StatePlayerBase
class_name StatePlayerWalk
var action_walk:ActionWalk
var in_sea:bool
func _init(state_handler:BaseStateHandler) -> void:
super._init(state_handler)
action_walk = ActionWalk.new(player)
SignalsManager.on_entered_sea.connect(on_entered_sea)
func on_input(inputs_dict:Dictionary):
if handler.current_state == self:
action_walk.execute(inputs_dict, delta)
func on_entered_sea(body:CharacterBody2D):
if body == player:
in_sea = true
func enter_state():
super.enter_state()
in_sea = false
func do_state_body():
super.do_state_body()
if in_sea:
return_state = player_handler.state_player_swim
StatePlayerWalk.gd
extends StatePlayerBase
class_name StatePlayerWalk
var action_walk:ActionWalk
var in_sea:bool
func _init(state_handler:BaseStateHandler) -> void:
super._init(state_handler)
action_walk = ActionWalk.new(player)
SignalsManager.on_entered_sea.connect(on_entered_sea)
func on_input(inputs_dict:Dictionary):
if handler.current_state == self:
action_walk.execute(inputs_dict, delta)
func on_entered_sea(body:CharacterBody2D):
if body == player:
in_sea = true
func enter_state():
super.enter_state()
in_sea = false
func do_state_body():
super.do_state_body()
if in_sea:
return_state = player_handler.state_player_swim
StatePlayerSwim.gd
extends StatePlayerBase
class_name StatePlayerSwim
var action_swim:ActionSwim
var outside_sea:bool
func _init(state_handler:BaseStateHandler) -> void:
super._init(state_handler)
action_swim = ActionSwim.new(player)
SignalsManager.on_exited_sea.connect(on_exited_sea)
func on_input(inputs_dict:Dictionary):
if handler.current_state == self:
action_swim.execute(inputs_dict, delta)
func on_exited_sea(body:CharacterBody2D):
if body == player:
outside_sea = true
func enter_state():
super.enter_state()
outside_sea = false
func do_state_body():
super.do_state_body()
if outside_sea:
return_state = player_handler.state_player_walk
How the States Work
The player starts in a walking state.
When the player enters a sea area:
return_state = player_handler.state_player_swim
the state changes from Walk to Swim.
When the player exits the sea area:
return_state = player_handler.state_player_walk
the state changes back from Swim to Walk.
Input is received through a global signal system (SignalsManager) and each state executes its corresponding action (ActionWalk or ActionSwim) only when it is the current active state.
Missing Piece
I suspect the most important file for understanding the architecture is PlayerStateHandler.gd, because it creates the states, stores references to them, and defines the initial state. I can also post that file if needed.
My Questions
1. Do you identify any architectural flaws in these state files that would make it difficult to transfer them to another project?
2. To have a better understanding of the state machine’s construction, would you need to view PlayerStateHandler.gd?
Any guidance would be appreciated.
Best Regards,
Nick