feat: Implement Phase 4 Trigger Events System
- Added a new event-driven system for reactive storytelling, allowing rules like "When X happens, do Y." - Introduced TriggerArea class for placeable sensors in the stage. - Enhanced StickmanRig to emit signals for actions and arrivals. - Updated StageDirectorVisuals to render rules visually with labels and badges. - Modified StageSpawner to support spawning TriggerAreas. - Improved text baseline calculations in speech bubbles and rule labels. - Added tests for text baseline fixes to ensure proper rendering. - Documented the implementation plan for Phase 4 in PHASE_4_TRIGGER_EVENTS.md. - Created a polish plan for Phase 4 in PHASE_4b_POLISH.md.
This commit is contained in:
@@ -15,6 +15,7 @@ const TERRAIN_UTILS := preload("res://scripts/terrain_utils.gd")
|
||||
const PROP_UTILS := preload("res://scripts/prop_utils.gd")
|
||||
const PROP_BLOCK := preload("res://scripts/prop_block.gd")
|
||||
const STICKMAN_FACTORY := preload("res://scripts/stickman_factory.gd")
|
||||
const TRIGGER_AREA := preload("res://scripts/trigger_area.gd")
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Constants
|
||||
@@ -87,6 +88,8 @@ func spawn(id: String, world_position: Vector2) -> Node2D:
|
||||
return _spawn_prop(entry, pos)
|
||||
"stickman":
|
||||
return _spawn_stickman(pos)
|
||||
"area":
|
||||
return _spawn_area(pos)
|
||||
_:
|
||||
push_warning("StageSpawner: unknown spawn kind '%s'." % entry.get("kind", ""))
|
||||
return null
|
||||
@@ -98,6 +101,9 @@ func spawn(id: String, world_position: Vector2) -> Node2D:
|
||||
static func get_world_aabb(node: Node2D) -> Rect2:
|
||||
if node == null or not is_instance_valid(node):
|
||||
return Rect2()
|
||||
# Duck-typed TriggerArea: expose its centered local rect through the transform.
|
||||
if node.has_method("get_area_rect"):
|
||||
return node.global_transform * (node.call("get_area_rect") as Rect2)
|
||||
var poly := node.get_node_or_null(NodePath("Polygon2D")) as Polygon2D
|
||||
if poly != null and not poly.polygon.is_empty():
|
||||
var rect := Rect2(node.to_global(poly.polygon[0]), Vector2.ZERO)
|
||||
@@ -174,6 +180,10 @@ func _build_registry() -> void:
|
||||
"id": "stickman", "label": "Stickman", "kind": "stickman",
|
||||
"spawn_offset": STICKMAN_FOOT_OFFSET,
|
||||
},
|
||||
{
|
||||
"id": "area", "label": "Area", "kind": "area",
|
||||
"spawn_offset": Vector2.ZERO,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
@@ -213,6 +223,14 @@ func _spawn_prop(entry: Dictionary, world_position: Vector2) -> PropBlock:
|
||||
return PROP_UTILS.spawn_prop(_world, world_position, payload, preset, Vector2.ZERO)
|
||||
|
||||
|
||||
func _spawn_area(world_position: Vector2) -> Node2D:
|
||||
var area: Node2D = TRIGGER_AREA.new()
|
||||
area.name = "TriggerArea"
|
||||
area.position = world_position
|
||||
_world.add_child(area)
|
||||
return area
|
||||
|
||||
|
||||
func _spawn_stickman(world_position: Vector2) -> StickmanRig:
|
||||
if _stickman_data.is_empty():
|
||||
push_warning("StageSpawner: no stickman data loaded; check '%s'." % DEFAULT_STICKMAN_PATH)
|
||||
|
||||
Reference in New Issue
Block a user