feat: Implement core player movement, input, and player scene setup, including grid-based movement, rotation, push mechanics, and multiplayer synchronization.

This commit is contained in:
Yogi Wiguna
2026-03-04 12:33:06 +08:00
parent 8b33ed3f56
commit b32565203f
3 changed files with 161 additions and 61 deletions
+28 -14
View File
@@ -22,7 +22,7 @@ func initialize(p_player: Node3D, p_gridmap: Node):
use_diagonal_movement = player.use_diagonal_movement
signal movement_finished
var buffered_direction: Vector2i = Vector2i.ZERO
var movement_queue: Array[Vector2i] = [] # Queue of target grid positions
var current_move_direction: Vector2i = Vector2i.ZERO
func _process(delta):
@@ -49,10 +49,17 @@ func _can_rpc() -> bool:
func simple_move_to(grid_position: Vector2i) -> bool:
if is_moving:
var direction = grid_position - player.current_position
if direction != current_move_direction:
buffer_move_input(direction)
return false
# Check if we are already moving to this position or if it's already queued
var current_target = player.target_position
if movement_queue.is_empty():
if current_target == grid_position:
return false
elif movement_queue[-1] == grid_position:
return false
if movement_queue.size() < 1: # Buffer at most 1 future move
movement_queue.append(grid_position)
return true
if not player.is_multiplayer_authority():
print("[Move] Failed: Not authority for %s (Authority: %d, My Peer: %d)" % [player.name, player.get_multiplayer_authority(), player.multiplayer.get_unique_id()])
@@ -67,13 +74,15 @@ func simple_move_to(grid_position: Vector2i) -> bool:
if main and main.goals_cycle_manager and not main.goals_cycle_manager.is_match_active:
return false
var distance: int
if use_diagonal_movement:
distance = max(abs(grid_position.x - player.current_position.x), abs(grid_position.y - player.current_position.y))
else:
distance = abs(grid_position.x - player.current_position.x) + abs(grid_position.y - player.current_position.y)
if distance > movement_range:
return false
if not enhanced_gridmap.is_position_valid(grid_position):
# print("[Move] Failed: Position not valid on GridMap %s" % grid_position)
return false
@@ -130,11 +139,13 @@ func simple_move_to(grid_position: Vector2i) -> bool:
current_move_direction = grid_position - player.current_position
if player.is_multiplayer_authority():
# Authority starts their own tween locally
var is_bot = player.is_bot or player.is_in_group("Bots")
player.start_movement_along_path(path, not is_bot)
# Authority sends RPC to others (call_remote) to start their tweens
if _can_rpc():
player.rpc("start_movement_along_path", path, not is_bot)
else:
player.start_movement_along_path(path, not is_bot)
return true
@@ -250,14 +261,17 @@ func set_speed_multiplier(multiplier: float):
# Let's check how 'start_movement_along_path' is implemented in player.gd.
func buffer_move_input(direction: Vector2i):
buffered_direction = direction
func _on_movement_finished():
if buffered_direction != Vector2i.ZERO:
var target = player.current_position + buffered_direction
buffered_direction = Vector2i.ZERO
simple_move_to(target)
if not movement_queue.is_empty():
var next_target = movement_queue.pop_front()
# Use a small delay or call_deferred to avoid recursion issues,
# but keep it snappy by executing immediately if possible.
if not simple_move_to(next_target):
# If next move failed, clear queue and signal finished
movement_queue.clear()
current_move_direction = Vector2i.ZERO
emit_signal("movement_finished")
else:
current_move_direction = Vector2i.ZERO
emit_signal("movement_finished")