diff --git a/scripts/autoload/AudioManager.gd b/scripts/autoload/AudioManager.gd index 713a8b0..f84419c 100644 --- a/scripts/autoload/AudioManager.gd +++ b/scripts/autoload/AudioManager.gd @@ -3,6 +3,7 @@ extends Node const CROSSFADE_DURATION: float = 0.8 +const DEFAULT_MUSIC_VOLUME: float = 0.6 const _MUSIC_MAP: Dictionary = { 0: "res://assets/audio/music/floor_0.ogg", diff --git a/scripts/autoload/GameState.gd b/scripts/autoload/GameState.gd index 34c0ff2..58fa529 100644 --- a/scripts/autoload/GameState.gd +++ b/scripts/autoload/GameState.gd @@ -73,6 +73,11 @@ func clear_chest_state(chest_id: String) -> void: state_changed.emit() +func set_current_room(room: String) -> void: + current_room = room + state_changed.emit() + + func get_save_data() -> Dictionary: var positions: Dictionary = {} for key: String in _character_positions: diff --git a/scripts/main/main.gd b/scripts/main/main.gd index 00d1062..5be287a 100644 --- a/scripts/main/main.gd +++ b/scripts/main/main.gd @@ -8,6 +8,7 @@ func _ready() -> void: AudioManager.set_music_volume(GameState.music_volume) AudioManager.set_sfx_volume(GameState.sfx_volume) _apply_saved_state() + RoomNavigator.go_to_room_by_name(GameState.current_room) func _apply_saved_state() -> void: diff --git a/scripts/systems/room_navigator.gd b/scripts/systems/room_navigator.gd index f567ea5..418f00b 100644 --- a/scripts/systems/room_navigator.gd +++ b/scripts/systems/room_navigator.gd @@ -10,6 +10,21 @@ const ROOM_WIDTH: float = 1280.0 const HOME_CAMERA_X: float = 640.0 const HOME_CAMERA_Y: float = 1080.0 const CAMERA_TWEEN_DURATION: float = 0.6 +const HOME_ROOM_NAME: String = "garden_party" + +const _ROOM_NAMES: Dictionary = { + Vector2i(0, 0): "reception", + Vector2i(0, 1): "giftshop", + Vector2i(0, 2): "restaurant", + Vector2i(0, 3): "emergency", + Vector2i(1, 0): "xray", + Vector2i(1, 1): "pharmacy", + Vector2i(1, 2): "lab", + Vector2i(1, 3): "patient_rooms", + Vector2i(2, 0): "ultrasound", + Vector2i(2, 1): "delivery_room", + Vector2i(2, 2): "nursery", +} var _current_floor: int = 0 var _current_room: int = 0 @@ -27,13 +42,16 @@ func go_to_floor(floor_index: int) -> void: func go_to_room(floor_index: int, room_index: int) -> void: - if _camera == null: - return if not _is_at_home and floor_index == _current_floor and room_index == _current_room: return _is_at_home = false _current_floor = floor_index _current_room = room_index + var room_name: String = _ROOM_NAMES.get(Vector2i(floor_index, room_index), "") + if not room_name.is_empty(): + GameState.set_current_room(room_name) + if _camera == null: + return var target_x: float = room_index * ROOM_WIDTH + ROOM_WIDTH * 0.5 var target_y: float = floor_index * -FLOOR_HEIGHT + FLOOR_HEIGHT * 0.5 if _active_tween != null: @@ -46,11 +64,12 @@ func go_to_room(floor_index: int, room_index: int) -> void: func go_to_home() -> void: - if _camera == null: - return if _is_at_home: return _is_at_home = true + GameState.set_current_room(HOME_ROOM_NAME) + if _camera == null: + return if _active_tween != null: _active_tween.kill() _active_tween = create_tween() @@ -61,11 +80,14 @@ func go_to_home() -> void: func go_to_hospital() -> void: - if _camera == null: - return if not _is_at_home: return _is_at_home = false + var room_name: String = _ROOM_NAMES.get(Vector2i(_current_floor, _current_room), "") + if not room_name.is_empty(): + GameState.set_current_room(room_name) + if _camera == null: + return var target_x: float = _current_room * ROOM_WIDTH + ROOM_WIDTH * 0.5 var target_y: float = _current_floor * -FLOOR_HEIGHT + FLOOR_HEIGHT * 0.5 if _active_tween != null: @@ -77,6 +99,20 @@ func go_to_hospital() -> void: _active_tween.finished.connect(func() -> void: hospital_entered.emit()) +func go_to_room_by_name(room_name: String) -> void: + if room_name == HOME_ROOM_NAME: + go_to_home() + return + for key: Vector2i in _ROOM_NAMES: + if _ROOM_NAMES[key] == room_name: + go_to_room(key.x, key.y) + return + + +func get_room_name(floor_index: int, room_index: int) -> String: + return _ROOM_NAMES.get(Vector2i(floor_index, room_index), "") + + func get_current_floor() -> int: return _current_floor diff --git a/test/unit/test_audio_manager.gd b/test/unit/test_audio_manager.gd index d4f0b40..b33bfa1 100644 --- a/test/unit/test_audio_manager.gd +++ b/test/unit/test_audio_manager.gd @@ -69,3 +69,7 @@ func test_music_map_has_all_four_floors() -> void: assert_true(AudioManager._MUSIC_MAP.has(1)) assert_true(AudioManager._MUSIC_MAP.has(2)) assert_true(AudioManager._MUSIC_MAP.has(3)) + + +func test_default_music_volume_constant_is_0_6() -> void: + assert_eq(AudioManager.DEFAULT_MUSIC_VOLUME, 0.6) diff --git a/test/unit/test_game_state.gd b/test/unit/test_game_state.gd index 5d0515a..5dc429c 100644 --- a/test/unit/test_game_state.gd +++ b/test/unit/test_game_state.gd @@ -181,3 +181,16 @@ func test_apply_save_data_restores_chest_state() -> void: } GameState.apply_save_data(data) assert_eq(GameState.get_chest_state("reception_desk_test"), ["clipboard", "pen"]) + + +func test_set_current_room_updates_value() -> void: + GameState.set_current_room("xray") + assert_eq(GameState.current_room, "xray") + GameState.set_current_room("reception") + + +func test_set_current_room_emits_state_changed() -> void: + watch_signals(GameState) + GameState.set_current_room("pharmacy") + assert_signal_emitted(GameState, "state_changed") + GameState.set_current_room("reception") diff --git a/test/unit/test_room_navigator.gd b/test/unit/test_room_navigator.gd index 89195ff..7e2a8e4 100644 --- a/test/unit/test_room_navigator.gd +++ b/test/unit/test_room_navigator.gd @@ -74,13 +74,13 @@ func test_go_to_floor_does_not_emit_if_already_on_floor_room_zero() -> void: assert_signal_not_emitted(_nav, "room_changed") -func test_initialize_with_null_camera_prevents_state_update() -> void: +func test_initialize_with_null_camera_still_updates_state() -> void: var nav: Node = RoomNavigatorScript.new() add_child_autofree(nav) nav.initialize(null) nav.go_to_room(1, 2) - assert_eq(nav.get_current_floor(), 0) - assert_eq(nav.get_current_room(), 0) + assert_eq(nav.get_current_floor(), 1) + assert_eq(nav.get_current_room(), 2) func test_multiple_room_changes_update_state() -> void: @@ -138,3 +138,40 @@ func test_go_to_room_after_home_clears_is_at_home() -> void: _nav.go_to_home() _nav.go_to_room(0, 0) assert_false(_nav.is_at_home()) + + +func test_room_names_dict_has_eleven_entries() -> void: + assert_eq(RoomNavigator._ROOM_NAMES.size(), 11) + + +func test_get_room_name_floor0_room0_is_reception() -> void: + assert_eq(RoomNavigator.get_room_name(0, 0), "reception") + + +func test_get_room_name_floor0_room3_is_emergency() -> void: + assert_eq(RoomNavigator.get_room_name(0, 3), "emergency") + + +func test_get_room_name_floor1_room2_is_lab() -> void: + assert_eq(RoomNavigator.get_room_name(1, 2), "lab") + + +func test_get_room_name_floor2_room1_is_delivery_room() -> void: + assert_eq(RoomNavigator.get_room_name(2, 1), "delivery_room") + + +func test_get_room_name_unknown_returns_empty_string() -> void: + assert_eq(RoomNavigator.get_room_name(99, 0), "") + assert_eq(RoomNavigator.get_room_name(0, 99), "") + + +func test_go_to_room_by_name_garden_party_sets_is_at_home() -> void: + RoomNavigator.go_to_room_by_name("garden_party") + assert_true(RoomNavigator.is_at_home()) + RoomNavigator._is_at_home = false + + +func test_go_to_room_by_name_unknown_is_noop() -> void: + var floor_before: int = RoomNavigator.get_current_floor() + RoomNavigator.go_to_room_by_name("nonexistent_room_xyz") + assert_eq(RoomNavigator.get_current_floor(), floor_before)