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>
76 lines
2.1 KiB
GDScript
76 lines
2.1 KiB
GDScript
extends Node2D
|
|
|
|
# Entity renderer — manages entity sprites under the Entities node
|
|
# Creates/updates/removes Sprite2D children based on entity data
|
|
|
|
var entity_nodes: Dictionary = {} # id -> Node2D mapping
|
|
|
|
func _ready() -> void:
|
|
print("EntityRenderer: Initialized")
|
|
|
|
# Update entities from snapshot data
|
|
func update_entities(entities: Array) -> void:
|
|
var active_ids: Array = []
|
|
|
|
# Create or update entities
|
|
for entity_data in entities:
|
|
if not entity_data.has("id"):
|
|
continue
|
|
|
|
var entity_id = entity_data.id
|
|
active_ids.append(entity_id)
|
|
|
|
# Create entity node if it doesn't exist
|
|
if not entity_nodes.has(entity_id):
|
|
_create_entity_node(entity_id, entity_data)
|
|
else:
|
|
_update_entity_node(entity_id, entity_data)
|
|
|
|
# Remove entities that are no longer visible
|
|
var ids_to_remove: Array = []
|
|
for entity_id in entity_nodes.keys():
|
|
if entity_id not in active_ids:
|
|
ids_to_remove.append(entity_id)
|
|
|
|
for entity_id in ids_to_remove:
|
|
_remove_entity_node(entity_id)
|
|
|
|
# Create a new entity node (placeholder visual)
|
|
func _create_entity_node(entity_id: int, entity_data: Dictionary) -> void:
|
|
var entity_node = ColorRect.new()
|
|
entity_node.name = "Entity_" + str(entity_id)
|
|
entity_node.size = Vector2(32, 32)
|
|
entity_node.pivot_offset = Vector2(16, 16)
|
|
|
|
# Color based on type
|
|
if entity_data.get("type") == "npc":
|
|
entity_node.color = Color(0.3, 0.6, 0.9) # Blue for NPCs
|
|
else:
|
|
entity_node.color = Color(0.8, 0.8, 0.8) # Gray for unknown
|
|
|
|
add_child(entity_node)
|
|
entity_nodes[entity_id] = entity_node
|
|
|
|
_update_entity_node(entity_id, entity_data)
|
|
|
|
# Update an existing entity node
|
|
func _update_entity_node(entity_id: int, entity_data: Dictionary) -> void:
|
|
if not entity_nodes.has(entity_id):
|
|
return
|
|
|
|
var entity_node = entity_nodes[entity_id]
|
|
|
|
# Update position
|
|
if entity_data.has("position"):
|
|
var pos = entity_data.position
|
|
entity_node.position = Vector2(pos[0] * 32, pos[1] * 32) # 32px grid
|
|
|
|
# Remove an entity node
|
|
func _remove_entity_node(entity_id: int) -> void:
|
|
if not entity_nodes.has(entity_id):
|
|
return
|
|
|
|
var entity_node = entity_nodes[entity_id]
|
|
entity_node.queue_free()
|
|
entity_nodes.erase(entity_id)
|