feat(client): initialize Godot 4 project boilerplate (epic #277)
Set up the complete Godot 4.6 client foundation as a pure renderer (D-020): - project.godot with 2D rendering, autoloads, input actions - Main scene: Game > World (TileMapLayer, Entities, FogOverlay) + Camera2D + UILayer - Autoloads: SimBridge (connection state machine + test mode), GameState, InputMapper - Rendering stubs: WorldRenderer, EntityRenderer, FogRenderer - UI stubs: HUD (health/perception/time), Minimap, MonologueDisplay - Input mapping: WASD/arrows, E (interact), Tab (perception), Esc (menu), Space (pause) - gdUnit4 smoke tests: scene loads, autoloads registered (2/2 passing) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
extends Node
|
||||
|
||||
# Semantic actions — NO raw key codes cross the bridge
|
||||
enum Action {
|
||||
MOVE_NORTH, MOVE_SOUTH, MOVE_EAST, MOVE_WEST,
|
||||
INTERACT, USE_PERCEPTION_MODE, OPEN_MENU, PAUSE
|
||||
}
|
||||
|
||||
var input_queue: Array[Dictionary] = []
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
# Only process key press events (not releases or repeats)
|
||||
if not event is InputEventKey:
|
||||
return
|
||||
if not event.pressed or event.echo:
|
||||
return
|
||||
|
||||
var action: Action = -1
|
||||
var action_name: String = ""
|
||||
|
||||
# Map input actions to semantic Action enum
|
||||
if event.is_action_pressed("move_north"):
|
||||
action = Action.MOVE_NORTH
|
||||
action_name = "move_north"
|
||||
elif event.is_action_pressed("move_south"):
|
||||
action = Action.MOVE_SOUTH
|
||||
action_name = "move_south"
|
||||
elif event.is_action_pressed("move_east"):
|
||||
action = Action.MOVE_EAST
|
||||
action_name = "move_east"
|
||||
elif event.is_action_pressed("move_west"):
|
||||
action = Action.MOVE_WEST
|
||||
action_name = "move_west"
|
||||
elif event.is_action_pressed("interact"):
|
||||
action = Action.INTERACT
|
||||
action_name = "interact"
|
||||
elif event.is_action_pressed("perception_mode"):
|
||||
action = Action.USE_PERCEPTION_MODE
|
||||
action_name = "perception_mode"
|
||||
elif event.is_action_pressed("open_menu"):
|
||||
action = Action.OPEN_MENU
|
||||
action_name = "open_menu"
|
||||
elif event.is_action_pressed("pause"):
|
||||
action = Action.PAUSE
|
||||
action_name = "pause"
|
||||
|
||||
# Queue the action if valid
|
||||
if action != -1:
|
||||
input_queue.append({
|
||||
"action": action,
|
||||
"timestamp_msec": Time.get_ticks_msec()
|
||||
})
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
func flush_queue() -> Array[Dictionary]:
|
||||
var queue = input_queue.duplicate()
|
||||
input_queue.clear()
|
||||
return queue
|
||||
Reference in New Issue
Block a user