feat(audio): add tap handler and SFX to RoomChest

Adds _get_press_position helper and _unhandled_input tap detection to
RoomChest, wires AudioManager.play_sfx calls for chest_tap and
item_spawn events. Guards AudioManager audio load calls with Dummy
driver check so headless unit tests stay green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Steven Wroblewski
2026-05-10 20:18:16 +02:00
parent bad2fbe65f
commit a220b641ca
3 changed files with 44 additions and 0 deletions
+4
View File
@@ -50,6 +50,8 @@ func _ready() -> void:
func play_floor_music(floor: int) -> void:
if AudioServer.get_driver_name() == "Dummy":
return
if floor == _current_floor:
return
if not _MUSIC_MAP.has(floor):
@@ -80,6 +82,8 @@ func play_floor_music(floor: int) -> void:
func play_sfx(event: String) -> void:
if AudioServer.get_driver_name() == "Dummy":
return
if not _SFX_MAP.has(event):
return
var path: String = _SFX_MAP[event]
+22
View File
@@ -8,6 +8,7 @@ signal item_received(chest: RoomChest, item_id: String)
const SPAWN_TWEEN_DURATION: float = 0.3
@export var chest_id: String = ""
@export var tap_radius: float = 50.0
var _spawned_items: Array[HoldableItem] = []
var _item_configs: Array[ChestItemData] = []
@@ -21,9 +22,22 @@ func _ready() -> void:
call_deferred("spawn_items")
func _unhandled_input(event: InputEvent) -> void:
var press_pos: Vector2 = _get_press_position(event)
if press_pos == Vector2.INF:
return
var canvas_pos: Vector2 = get_viewport().get_canvas_transform().affine_inverse() * press_pos
if canvas_pos.distance_to(global_position) > tap_radius:
return
get_viewport().set_input_as_handled()
AudioManager.play_sfx("chest_tap")
spawn_items()
func spawn_items() -> void:
if not _spawned_items.is_empty():
return
AudioManager.play_sfx("item_spawn")
var parent: Node = get_parent()
for config: ChestItemData in _item_configs:
var item: HoldableItem = _create_item(config)
@@ -71,6 +85,14 @@ func get_spawned_item(index: int) -> HoldableItem:
return _spawned_items[index]
func _get_press_position(event: InputEvent) -> Vector2:
if event is InputEventScreenTouch and event.pressed:
return event.position
if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
return event.position
return Vector2.INF
func _create_item(config: ChestItemData) -> HoldableItem:
var item: HoldableItem
if config.item_type == ChestItemData.ItemType.OUTFIT:
+18
View File
@@ -83,3 +83,21 @@ func test_receive_item_decrements_spawned_count() -> void:
var item: HoldableItem = chest.get_spawned_item(0)
chest.receive_item(item)
assert_eq(chest.get_spawned_count(), 2)
func test_get_press_position_returns_position_for_screen_touch_pressed() -> void:
var chest: RoomChest = RoomChest.new()
add_child_autofree(chest)
var event: InputEventScreenTouch = InputEventScreenTouch.new()
event.pressed = true
event.position = Vector2(100.0, 200.0)
assert_eq(chest._get_press_position(event), Vector2(100.0, 200.0))
func test_get_press_position_returns_inf_for_screen_touch_released() -> void:
var chest: RoomChest = RoomChest.new()
add_child_autofree(chest)
var event: InputEventScreenTouch = InputEventScreenTouch.new()
event.pressed = false
event.position = Vector2(100.0, 200.0)
assert_eq(chest._get_press_position(event), Vector2.INF)