feat(snap-receiver): implement snap detection, position snapping, and pose animation trigger

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Steven Wroblewski
2026-05-08 22:12:18 +02:00
parent 60fba44316
commit 2f5e9d99a6
2 changed files with 126 additions and 4 deletions
+44 -4
View File
@@ -1,5 +1,5 @@
## SnapReceiver — scans for nearby SnapPoints when the parent Character is released.
## Attach as child of Character. Full implementation connects to DragDropComponent signals.
## Attach as child of Character. Connects automatically to DragDropComponent signals.
class_name SnapReceiver extends Node
const SCAN_RADIUS: float = 80.0
@@ -10,6 +10,44 @@ var _character: Character
func _ready() -> void:
_character = get_parent() as Character
var drag: DragDropComponent = _character.get_node_or_null("DragDropComponent") as DragDropComponent
if drag != null:
drag.drag_picked_up.connect(_on_drag_picked_up)
drag.drag_released.connect(_on_drag_released)
func _on_drag_picked_up(_pos: Vector2) -> void:
if _current_snap != null:
_current_snap.unsnap()
_current_snap = null
_character.set_animation_state("held")
func _on_drag_released(_pos: Vector2) -> void:
var nearest: SnapPoint = _find_nearest_accepting_snap()
if nearest != null:
_current_snap = nearest
nearest.snap(_character)
_character.global_position = nearest.global_position
_character.set_animation_state(nearest.pose)
else:
_character.set_animation_state("idle")
func _find_nearest_accepting_snap() -> SnapPoint:
var best: SnapPoint = null
var best_dist: float = SCAN_RADIUS
for node: Node in get_tree().get_nodes_in_group("snap_points"):
var snap_point: SnapPoint = node as SnapPoint
if snap_point == null:
continue
if not snap_point.accepts(_character):
continue
var dist: float = _character.global_position.distance_to(snap_point.global_position)
if dist < best_dist:
best_dist = dist
best = snap_point
return best
func get_current_snap() -> SnapPoint:
@@ -17,6 +55,8 @@ func get_current_snap() -> SnapPoint:
func force_unsnap() -> void:
if _current_snap != null:
_current_snap.unsnap()
_current_snap = null
if _current_snap == null:
return
_current_snap.unsnap()
_current_snap = null
_character.set_animation_state("idle")