Feat/1 movement foundation #5
@@ -1,78 +1,56 @@
|
||||
extends CharacterBody3D
|
||||
class_name PlayerMovementController
|
||||
|
||||
## PlayerMovementController — root node for all player 3D locomotion.
|
||||
## Attach to a CharacterBody3D with a CollisionShape3D.
|
||||
## States are expected to be children: state_ground, state_air,
|
||||
## state_wall_run, state_wall_cling, state_slide, state_dash.
|
||||
|
||||
signal chain_updated(count: int, bonus: float)
|
||||
|
||||
@export var params: MovementParams = preload("res://movement/movement_params.gd").new()
|
||||
|
||||
var machine: MovementStateMachine
|
||||
var jump_buffered: bool = false
|
||||
var _ready_ran: bool = false
|
||||
var _machine: MovementStateMachine = null
|
||||
|
||||
# ── Helpers ───────────────────────────────────────────────────────────────────
|
||||
|
||||
func _ensure_machine() -> MovementStateMachine:
|
||||
if typeof(_machine) != TYPE_NIL and is_instance_valid(_machine):
|
||||
return _machine as MovementStateMachine
|
||||
var candidates := [
|
||||
get_node("MovementStateMachine") if has_node("MovementStateMachine") else null,
|
||||
_machine if is_instance_valid(_machine) and _machine.has_method("register_chain_mechanic") else null,
|
||||
]
|
||||
for c in candidates:
|
||||
if c and (c is MovementStateMachine or (c.has_method("switch_to") and c.has_method("register_chain_mechanic"))):
|
||||
_machine = c
|
||||
if is_instance_valid(_machine):
|
||||
return _machine
|
||||
if has_node("MovementStateMachine"):
|
||||
_machine = $MovementStateMachine
|
||||
if _machine is MovementStateMachine:
|
||||
return _machine
|
||||
_machine = null
|
||||
return null
|
||||
|
||||
# ── Input references ─────────────────────────────────────────────────────────
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("ui_accept"):
|
||||
# Space / jump
|
||||
pass
|
||||
var node := _ensure_machine()
|
||||
if not node:
|
||||
var sm := _ensure_machine()
|
||||
if not sm:
|
||||
return
|
||||
node.input_jump_just_pressed = Input.is_action_just_pressed("jump")
|
||||
node.input_jump_pressed = Input.is_action_pressed("jump")
|
||||
node.input_sprint = Input.is_action_pressed("sprint")
|
||||
node.input_crouch = Input.is_action_pressed("crouch")
|
||||
node.input_dash = Input.is_action_just_pressed("dash")
|
||||
var input_v := Input.get_vector("move_left", "move_right", "move_forward", "move_back")
|
||||
node.input_dir = input_v
|
||||
|
||||
|
||||
@onready var _machine = get_node("MovementStateMachine")
|
||||
sm.input_jump_just_pressed = Input.is_action_just_pressed("jump")
|
||||
sm.input_jump_pressed = Input.is_action_pressed("jump")
|
||||
sm.input_sprint = Input.is_action_pressed("sprint")
|
||||
sm.input_crouch = Input.is_action_pressed("crouch")
|
||||
sm.input_dash = Input.is_action_just_pressed("dash")
|
||||
sm.input_dir = Input.get_vector("move_left", "move_right", "move_forward", "move_back")
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if _ready_ran:
|
||||
return
|
||||
_ready_ran = true
|
||||
var node := _ensure_machine()
|
||||
if node:
|
||||
var sm := node
|
||||
var sm := _ensure_machine()
|
||||
if sm:
|
||||
sm.player = self
|
||||
sm.params = params
|
||||
# Mirror signal up
|
||||
sm.movement_event.connect(func(ev, data):
|
||||
if ev == "chain_updated":
|
||||
chain_updated.emit(data.count, data.bonus)
|
||||
)
|
||||
sm.movement_event.connect(_on_movement_event)
|
||||
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
var node := _ensure_machine()
|
||||
if not node:
|
||||
var sm := _ensure_machine()
|
||||
if not sm:
|
||||
return
|
||||
# Keep one consistent source of truth for inputs
|
||||
node.input_jump_just_pressed = Input.is_action_just_pressed("jump") and not node.input_jump_pressed
|
||||
node.input_jump_pressed = Input.is_action_pressed("jump")
|
||||
node.input_sprint = Input.is_action_pressed("sprint")
|
||||
node.input_crouch = Input.is_action_pressed("crouch")
|
||||
node.input_dash = Input.is_action_just_pressed("dash") and not node.input_dash
|
||||
node.input_dir = Input.get_vector("move_left", "move_right", "move_forward", "move_back")
|
||||
sm.input_jump_just_pressed = Input.is_action_just_pressed("jump") and not sm.input_jump_pressed
|
||||
sm.input_jump_pressed = Input.is_action_pressed("jump")
|
||||
sm.input_sprint = Input.is_action_pressed("sprint")
|
||||
sm.input_crouch = Input.is_action_pressed("crouch")
|
||||
sm.input_dash = Input.is_action_just_pressed("dash") and not sm.input_dash
|
||||
sm.input_dir = Input.get_vector("move_left", "move_right", "move_forward", "move_back")
|
||||
|
||||
|
||||
func _on_movement_event(ev: String, data: Dictionary) -> void:
|
||||
if ev == "chain_updated":
|
||||
chain_updated.emit(data.count, data.bonus)
|
||||
|
||||
Reference in New Issue
Block a user