diff --git a/addons/property-inspector/pro_animation_sprite2d/pro_animated_sprite.gd b/addons/property-inspector/pro_animation_sprite2d/pro_animated_sprite.gd index c4735850..b26245b5 100644 --- a/addons/property-inspector/pro_animation_sprite2d/pro_animated_sprite.gd +++ b/addons/property-inspector/pro_animation_sprite2d/pro_animated_sprite.gd @@ -127,7 +127,7 @@ func _on_animation_finished() -> void: var next = auto_checkout_dict[intro].animation_next if wait_time > 0: pause() - get_tree().create_timer(wait_time).timeout.connect(play.bind(next)) + Util.timer(wait_time, play.bind(next)) else: play(next) diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/0.png b/asset/art/gif/c01_书店外街道/报童给报纸/0.png index dff2e118..9e60efa9 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/0.png and b/asset/art/gif/c01_书店外街道/报童给报纸/0.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/1.png b/asset/art/gif/c01_书店外街道/报童给报纸/1.png index 59d23c4f..562b1b09 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/1.png and b/asset/art/gif/c01_书店外街道/报童给报纸/1.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/10.png b/asset/art/gif/c01_书店外街道/报童给报纸/10.png index 090a8aa1..fa3b7860 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/10.png and b/asset/art/gif/c01_书店外街道/报童给报纸/10.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/11.png b/asset/art/gif/c01_书店外街道/报童给报纸/11.png index 8e5b7bba..e80e634b 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/11.png and b/asset/art/gif/c01_书店外街道/报童给报纸/11.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/12.png b/asset/art/gif/c01_书店外街道/报童给报纸/12.png index 1803a474..7fac76a3 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/12.png and b/asset/art/gif/c01_书店外街道/报童给报纸/12.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/13.png b/asset/art/gif/c01_书店外街道/报童给报纸/13.png index 975d9b55..f7afaca2 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/13.png and b/asset/art/gif/c01_书店外街道/报童给报纸/13.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/14.png b/asset/art/gif/c01_书店外街道/报童给报纸/14.png index 1803a474..7fac76a3 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/14.png and b/asset/art/gif/c01_书店外街道/报童给报纸/14.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/15.png b/asset/art/gif/c01_书店外街道/报童给报纸/15.png index 975d9b55..f7afaca2 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/15.png and b/asset/art/gif/c01_书店外街道/报童给报纸/15.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/16.png b/asset/art/gif/c01_书店外街道/报童给报纸/16.png index 1803a474..7fac76a3 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/16.png and b/asset/art/gif/c01_书店外街道/报童给报纸/16.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/17.png b/asset/art/gif/c01_书店外街道/报童给报纸/17.png index 975d9b55..f7afaca2 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/17.png and b/asset/art/gif/c01_书店外街道/报童给报纸/17.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/18.png b/asset/art/gif/c01_书店外街道/报童给报纸/18.png index b4ab1f5a..ad56ef72 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/18.png and b/asset/art/gif/c01_书店外街道/报童给报纸/18.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/19.png b/asset/art/gif/c01_书店外街道/报童给报纸/19.png index c463505e..73d1b4fb 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/19.png and b/asset/art/gif/c01_书店外街道/报童给报纸/19.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/2.png b/asset/art/gif/c01_书店外街道/报童给报纸/2.png index f2782982..090b08a5 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/2.png and b/asset/art/gif/c01_书店外街道/报童给报纸/2.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/20.png b/asset/art/gif/c01_书店外街道/报童给报纸/20.png index 8ed35639..d1c4e9b9 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/20.png and b/asset/art/gif/c01_书店外街道/报童给报纸/20.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/21.png b/asset/art/gif/c01_书店外街道/报童给报纸/21.png index eb32fe14..463df156 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/21.png and b/asset/art/gif/c01_书店外街道/报童给报纸/21.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/22.png b/asset/art/gif/c01_书店外街道/报童给报纸/22.png index 86e9139f..00603f7b 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/22.png and b/asset/art/gif/c01_书店外街道/报童给报纸/22.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/23.png b/asset/art/gif/c01_书店外街道/报童给报纸/23.png index 1c84ab79..180e49ed 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/23.png and b/asset/art/gif/c01_书店外街道/报童给报纸/23.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/24.png b/asset/art/gif/c01_书店外街道/报童给报纸/24.png index 59d23c4f..562b1b09 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/24.png and b/asset/art/gif/c01_书店外街道/报童给报纸/24.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/3.png b/asset/art/gif/c01_书店外街道/报童给报纸/3.png index 59d23c4f..562b1b09 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/3.png and b/asset/art/gif/c01_书店外街道/报童给报纸/3.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/4.png b/asset/art/gif/c01_书店外街道/报童给报纸/4.png index 1c84ab79..180e49ed 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/4.png and b/asset/art/gif/c01_书店外街道/报童给报纸/4.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/5.png b/asset/art/gif/c01_书店外街道/报童给报纸/5.png index 86e9139f..00603f7b 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/5.png and b/asset/art/gif/c01_书店外街道/报童给报纸/5.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/6.png b/asset/art/gif/c01_书店外街道/报童给报纸/6.png index eb32fe14..463df156 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/6.png and b/asset/art/gif/c01_书店外街道/报童给报纸/6.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/7.png b/asset/art/gif/c01_书店外街道/报童给报纸/7.png index 8ed35639..d1c4e9b9 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/7.png and b/asset/art/gif/c01_书店外街道/报童给报纸/7.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/8.png b/asset/art/gif/c01_书店外街道/报童给报纸/8.png index c463505e..73d1b4fb 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/8.png and b/asset/art/gif/c01_书店外街道/报童给报纸/8.png differ diff --git a/asset/art/gif/c01_书店外街道/报童给报纸/9.png b/asset/art/gif/c01_书店外街道/报童给报纸/9.png index b4ab1f5a..ad56ef72 100644 Binary files a/asset/art/gif/c01_书店外街道/报童给报纸/9.png and b/asset/art/gif/c01_书店外街道/报童给报纸/9.png differ diff --git a/asset/art/prop/c02/海报特写/青岛啤酒.png b/asset/art/prop/c02/海报特写/青岛啤酒.png old mode 100755 new mode 100644 index 1eb36172..5d62e751 Binary files a/asset/art/prop/c02/海报特写/青岛啤酒.png and b/asset/art/prop/c02/海报特写/青岛啤酒.png differ diff --git a/asset/art/prop/c02/海报特写/青岛啤酒(未用).png b/asset/art/prop/c02/海报特写/青岛啤酒(未用).png new file mode 100755 index 00000000..1eb36172 Binary files /dev/null and b/asset/art/prop/c02/海报特写/青岛啤酒(未用).png differ diff --git a/asset/art/prop/c02/海报特写/青岛啤酒(未用).png.import b/asset/art/prop/c02/海报特写/青岛啤酒(未用).png.import new file mode 100644 index 00000000..d61cdf18 --- /dev/null +++ b/asset/art/prop/c02/海报特写/青岛啤酒(未用).png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b0bkwqv86sc0" +path="res://.godot/imported/青岛啤酒(未用).png-80f5ab64f6d0a693fa9d7a06bf9521c2.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://asset/art/prop/c02/海报特写/青岛啤酒(未用).png" +dest_files=["res://.godot/imported/青岛啤酒(未用).png-80f5ab64f6d0a693fa9d7a06bf9521c2.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/asset/dialogue/c01.csv b/asset/dialogue/c01.csv index 1827fae9..2531a20e 100644 --- a/asset/dialogue/c01.csv +++ b/asset/dialogue/c01.csv @@ -43,7 +43,7 @@ c01_7老板_7,手脚麻利点,不要耽误店里的生意。,书店老板,,, c01_8监督小孩_1,发赏钱喽!发赏钱喽!,监督小孩,,,, c01_8监督小孩_2,哟,吕萍?你咋表演结束了才回来...,监督小孩,,,, c01_8监督小孩_3,你手里攥的什么东西?给我看看,不然我就找班主告状!,监督小孩,,,, -c01_8监督小孩_4,这上头咋还刻着个人哩,脑袋圆圆的,一根毛都没有!,监督小孩,,[#wait=3.0],, +c01_8监督小孩_4,这上头咋还刻着个人哩,脑袋圆圆的,一根毛都没有!,监督小孩,,[#wait=1.0],, c01_8监督小孩_5,吕萍,你从哪弄来的?,监督小孩,,,, c01_8小小蝶_1,你们...都看见了吗?,吕萍,,,, c01_8幼年陆仁_1,它要来了,快跑!,陆仁,,,, diff --git a/asset/dialogue/c01.dialogue b/asset/dialogue/c01.dialogue index af7cbbcf..b2e49713 100644 --- a/asset/dialogue/c01.dialogue +++ b/asset/dialogue/c01.dialogue @@ -85,7 +85,7 @@ ~ c01_s12_鬼差来之前对话 -监督小孩: 这上头咋还刻着个人哩,脑袋圆圆的,一根毛都没有! [#wait=3.0] [ID:c01_8监督小孩_4] +监督小孩: 这上头咋还刻着个人哩,脑袋圆圆的,一根毛都没有! [#wait=1.0] [ID:c01_8监督小孩_4] 监督小孩: 吕萍,你从哪弄来的? [ID:c01_8监督小孩_5] => END diff --git a/asset/dialogue/item_description.csv b/asset/dialogue/item_description.csv index 7e60feec..a84f192b 100644 --- a/asset/dialogue/item_description.csv +++ b/asset/dialogue/item_description.csv @@ -19,11 +19,12 @@ setting_日志,笔记(B),,,,,Open the Log setting_记忆,记忆(G),,,,, setting_全屏游戏,全屏游戏,,,,,Full Screen setting_窗口置顶,窗口置顶,,,,,Top Window +ux_panel_笔记,线索,,,,, index_新游戏,新游戏,,,,,New Game index_继续游戏,继续游戏,,,,,Resume index_退出游戏,退出游戏,,,,,Exit ux_panel_继续,继续,,,,, -ux_panel_笔记,笔记,,,,, +ux_panel_线索笔记,线索,,,,, ux_panel_设置,设置,,,,, ux_panel_返回主菜单,返回主菜单,,,,, ux_panel_退出游戏,退出游戏,,,,, diff --git a/asset/dialogue/item_description.dialogue b/asset/dialogue/item_description.dialogue index a4b21fbb..b720dc57 100644 --- a/asset/dialogue/item_description.dialogue +++ b/asset/dialogue/item_description.dialogue @@ -5,7 +5,7 @@ 退出游戏[ID:index_退出游戏] 继续 [ID:ux_panel_继续] -笔记 [ID:ux_panel_笔记] +线索 [ID:ux_panel_线索笔记] 设置 [ID:ux_panel_设置] 返回主菜单 [ID:ux_panel_返回主菜单] 退出游戏 [ID:ux_panel_退出游戏] diff --git a/manager/scene/global_functor.gd b/manager/scene/global_functor.gd index d52588b8..1d4a7d3f 100644 --- a/manager/scene/global_functor.gd +++ b/manager/scene/global_functor.gd @@ -25,7 +25,7 @@ func c02_cat_play_with_door(): var knock_stream = preload("uid://6q5qi1qon35r") AudioManager.play_sfx(knock_stream) SceneManager.lock_player(1.5, 6, true) - await get_tree().create_timer(1.5).timeout + await Util.wait(1.5) knocking = false @@ -59,14 +59,14 @@ func _on_c02_fire_count_down_timeout(): c02_fire_count_down_timer.stop() AudioManager.stop_bgm_music("霸凌救小蝉倒计时") DialogueManager.show_dialogue_balloon(dialogue_c02, "c02_未完成拯救小蝉的游戏", [GlobalConfig.DIALOG_IGNORE_INPUT]) - await get_tree().create_timer(1.0).timeout + await Util.wait(1.0) SceneManager.show_black_hand(true, 0.5) - await get_tree().create_timer(3.0).timeout + await Util.wait(3) SceneManager.unlock_player() SceneManager.get_ground_loader().transition_to_scene("c02_s03", "4") # TODO 音效 # res://asset/audio/BGM/心跳背景音.mp3 - await get_tree().create_timer(3.0).timeout + await Util.wait(3) SceneManager.pop_debug_dialog_info("音效", "霸凌救小蝉倒计时") AudioManager.loop_bgm_music("霸凌救小蝉倒计时", c02_fire_count_down_sfx, 5) c02_fire_count_down_timer.start() diff --git a/manager/scene/scene_manager.gd b/manager/scene/scene_manager.gd index 825ce7c0..bd47a2d7 100644 --- a/manager/scene/scene_manager.gd +++ b/manager/scene/scene_manager.gd @@ -9,7 +9,7 @@ enum VIBE { # 从 ground loader 控制该信号 signal ground_ready(ground: Ground2D) -signal ground_start(ground: Ground2D) +signal ground_start() func _ready(): @@ -25,6 +25,12 @@ func get_ground_loader() -> GroundLoader: return get_node_or_null("/root/Main/GroundLoader") as GroundLoader +func toggle_ground_mask( + display: bool, wait_time := 1.5, ease_min_duration := 0.5, mask_color := Color.BLACK +) -> Tween: + return get_ground_loader().toggle_mask(display, wait_time, ease_min_duration, mask_color) + + # restart scene in debug launch... func is_restarting() -> bool: var ground = get_ground() @@ -233,7 +239,7 @@ func pop_os_with_str(translation_key: String, auto_lock := true, auto_unlock := var player = get_player() as MainPlayer if player: var msg = tr(translation_key).replace("
", "\n") - var lines = await DialogueUtil.generate_lines(msg) + var lines = await Util.generate_lines(msg) player.pop_os(lines, auto_lock, auto_unlock) else: printerr("Player node not found") @@ -293,12 +299,9 @@ func checkout_index_page(transition := true): # 保存后,渐隐切换场景 ArchiveManager.save_all() if transition: - var ground = get_ground() - if ground: - var tween = create_tween() - if GlobalConfig.DEBUG: - print("transition to index page") - tween.tween_property(ground, "modulate:a", 0.0, 1.0) + var ground_loader = get_ground_loader() as GroundLoader + if ground_loader: + var tween = toggle_ground_mask(true) tween.tween_callback(_jump_back_to_index_and_quit_main) else: _jump_back_to_index_and_quit_main() @@ -387,12 +390,11 @@ func toggle_pause_counter(plus := true): func quit_game(): ArchiveManager.save_all() - var ground = get_ground() - if ground: - var tween = create_tween() + var ground_loader = get_ground_loader() as GroundLoader + if ground_loader: + var tween = toggle_ground_mask(true, 2.0, 1.0) if GlobalConfig.DEBUG: print("quit_game with transition") - tween.tween_property(ground, "modulate:a", 0.0, 1.5) tween.tween_callback(get_tree().quit) else: get_tree().quit() diff --git a/project.godot b/project.godot index 5060e1de..2265fbdc 100644 --- a/project.godot +++ b/project.godot @@ -43,6 +43,7 @@ buses/default_bus_layout="res://config/default_bus_layout.tres" [autoload] +Util="*res://util/util.gd" DebugMenu="*res://addons/debug_menu/debug_menu.tscn" GlobalConfigManager="*res://manager/config_manager/global_config_manager.gd" ArchiveManager="*res://manager/archive_manager/archive_manager.gd" diff --git a/scene/character/main_player.gd b/scene/character/main_player.gd index e3bd087f..4b1619da 100644 --- a/scene/character/main_player.gd +++ b/scene/character/main_player.gd @@ -424,8 +424,7 @@ func _os_load_line(line, duration): os_tween.pause() if os_pausing_timer and os_pausing_timer.timeout.is_connected(os_tween.play): os_pausing_timer.timeout.disconnect(os_tween.play) - os_pausing_timer = get_tree().create_timer(duration) - os_pausing_timer.timeout.connect(_on_os_line_timeout, CONNECT_ONE_SHOT) + Util.timer(duration, _on_os_line_timeout) func _on_os_line_timeout(naturally := true): diff --git a/scene/character/reenter_lock.gd b/scene/character/reenter_lock.gd index 19b33dc1..d378b01f 100644 --- a/scene/character/reenter_lock.gd +++ b/scene/character/reenter_lock.gd @@ -44,7 +44,7 @@ func _exit_tree() -> void: func _create_timer(duration: float, callable: Callable): if duration > 0 and callable: - get_tree().create_timer(duration).timeout.connect(callable) + Util.timer(duration, callable) # Freeze 相关方法 diff --git a/scene/dialog/balloon.gd b/scene/dialog/balloon.gd index 45a62b05..c6bf1e2b 100755 --- a/scene/dialog/balloon.gd +++ b/scene/dialog/balloon.gd @@ -243,23 +243,11 @@ func apply_dialogue_line() -> void: # eg. [#wait=2.5] if wait: wait_time = wait.to_float() - await get_tree().create_timer(wait_time).timeout + await Util.wait(wait_time) # 在 translation key 仍旧是当前 line 时跳转;如果不再是当前 line,则不跳转 if dialogue_line.translation_key == initial_translation_key: next(dialogue_line.next_id) - # var time = next_dialogue_line.text.length() * 0.2 if next_dialogue_line.time == "auto" else next_dialogue_line.time.to_float() - # await get_tree().create_timer(time).timeout - - # elif dialogue_line.time != "": - # var time = dialogue_line.text.length() * 0.02 if dialogue_line.time == "auto" else dialogue_line.time.to_float() - # await get_tree().create_timer(time).timeout - # next(dialogue_line.next_id) - # else: - # is_waiting_for_input = true - # balloon.focus_mode = Control.FOCUS_ALL - # balloon.grab_focus() - ## Go to the next line func next(next_id: String) -> void: diff --git a/scene/dialog/balloon_debug.gd b/scene/dialog/balloon_debug.gd index cf3a6bbf..4cd5bfa1 100644 --- a/scene/dialog/balloon_debug.gd +++ b/scene/dialog/balloon_debug.gd @@ -148,7 +148,7 @@ func apply_dialogue_line() -> void: is_waiting_for_input = true # balloon.focus_mode = Control.FOCUS_ALL # balloon.grab_focus() - await get_tree().create_timer(2.0).timeout + await Util.wait(2.0) # debug line 不需要下一行,直接释放(避免触发 dialogue_ended 信号) queue_free() diff --git a/scene/effect/shading_layer.gd b/scene/effect/shading_layer.gd index ad90f81c..e3f60a8c 100644 --- a/scene/effect/shading_layer.gd +++ b/scene/effect/shading_layer.gd @@ -210,11 +210,11 @@ func flash_palette(duration := 0.5) -> void: if not is_node_ready(): return add_mode("palette") - get_tree().create_timer(duration).timeout.connect(erase_mode.bind("palette")) + Util.timer(duration, erase_mode.bind("palette")) # glitch 闪烁 func flash_glitch(duration := 1.0) -> void: if not is_node_ready(): return add_mode("glitch") - get_tree().create_timer(duration).timeout.connect(erase_mode.bind("glitch")) + Util.timer(duration, erase_mode.bind("glitch")) diff --git a/scene/effect/黑手.gd b/scene/effect/黑手.gd index be792dbe..4b7597ac 100644 --- a/scene/effect/黑手.gd +++ b/scene/effect/黑手.gd @@ -17,5 +17,5 @@ func run_effect(play_sfx := true, queue_free_delay := 0.0): func _on_animation_finished(_a, queue_free_delay): if queue_free_delay > 0: - await get_tree().create_timer(queue_free_delay).timeout + await Util.wait(queue_free_delay) queue_free() diff --git a/scene/entity/npc.gd b/scene/entity/npc.gd index 9f3288ed..13cd065f 100644 --- a/scene/entity/npc.gd +++ b/scene/entity/npc.gd @@ -55,6 +55,31 @@ var dialogue_res = preload("res://asset/dialogue/npc.dialogue") var base_scale := Vector2.ONE var base_mod := Color.WHITE_SMOKE +var speaking_sign_tween: Tween + +# 0 hide; 1 silent; 2 speaking +var speaking_sign_mode := 0: + set(val): + if speaking_sign_mode != val: + speaking_sign_mode = val + if speaking_sign_tween and speaking_sign_tween.is_valid(): + speaking_sign_tween.kill() + speaking_sign_tween = create_tween() + if val == 0: + speaking_sign_tween.tween_property(speaking_sign, "modulate:a", 0.0, 0.3) + elif val == 1: + speaking_sign_tween.tween_property(speaking_sign, "modulate", base_mod, 0.3) + speaking_sign_tween.parallel().tween_property( + speaking_sign, "scale", base_scale, 0.3 + ) + speaking_animation.play("speaking") + elif val == 2: + speaking_sign_tween.tween_property(speaking_sign, "modulate", Color.WHITE, 0.3) + speaking_sign_tween.parallel().tween_property( + speaking_sign, "scale", base_scale * 1.3, 0.3 + ) + speaking_animation.play("speaking") + func _ready() -> void: # sign position @@ -69,10 +94,14 @@ func _ready() -> void: sign_snapper.action_on_arrived = action_key sign_snapper.radius = walk_to_edge_width sign_snapper.enabled = snap_to_edge + # 设置 speaking_sign 默认值 + base_scale = speaking_sign.scale + base_mod = speaking_sign.modulate + speaking_sign.modulate.a = 0.0 if Engine.is_editor_hint(): # editor 下都显示 speaking_sign.visible = true - speaking_sign.modulate.a = 1 + speaking_sign.modulate.a = 1.0 speaking_sign.get_node("Sprite2D").position.x = -60.0 speaking_sign.get_node("Sprite2D").frame = 2 sign_mark.display_sign = true @@ -80,10 +109,6 @@ func _ready() -> void: # setup default value ground_archive = ArchiveManager.archive.ground_archive() icount = ground_archive.get_value(name, "icount", 0) - # 默认为 0 - speaking_sign.modulate.a = 0.0 - base_scale = speaking_sign.scale - base_mod = speaking_sign.modulate if snap_to_edge: sign_snapper.arrived.connect(_on_interacted) else: @@ -106,10 +131,10 @@ func _align_signs_status(): func _on_toggle_active(activated: bool) -> void: - if activated: - speaking_animation.play("speaking") - # icount 影响 visible; activated 影响 modulate - speaking_sign.modulate.a = 1 if activated else 0 + if activated and speaking_sign_mode == 0: + speaking_sign_mode = 1 + elif not activated and speaking_sign_mode > 0: + speaking_sign_mode = 0 func _on_interacted() -> void: @@ -122,13 +147,9 @@ func _on_interacted() -> void: ground_archive.set_pair(name, "icount", icount) DialogueManager.show_dialogue_balloon(dialogue_res, dialogue_title) interacted.emit() - var tween = create_tween() - tween.tween_property(speaking_sign, "modulate", Color.WHITE, 0.5) - tween.parallel().tween_property(speaking_sign, "scale", base_scale * 1.3, 0.3) + speaking_sign_mode = 2 await DialogueManager.dialogue_ended - tween = create_tween() - tween.tween_property(speaking_sign, "modulate", base_mod, 0.5) - tween.parallel().tween_property(speaking_sign, "scale", base_scale, 0.3) + speaking_sign_mode = 1 if GlobalConfig.DEBUG: print("[" + name + "] call lock") SceneManager.unlock_player() diff --git a/scene/entity/npc.tscn b/scene/entity/npc.tscn index 3a80463a..68452025 100644 --- a/scene/entity/npc.tscn +++ b/scene/entity/npc.tscn @@ -116,7 +116,7 @@ script = ExtResource("4_j5svs") [node name="Sign" parent="." instance=ExtResource("4_nokx4")] unique_name_in_owner = true -sign_mark_offset = Vector2(0, -60) +sign_mark_offset = Vector2(0, -10) [node name="SpeakingAnimationPlayer" type="AnimationPlayer" parent="."] unique_name_in_owner = true @@ -141,7 +141,7 @@ scale = Vector2(0.07, 0.07) [node name="Sprite2D" type="AnimatedSprite2D" parent="SpeakingSign2D"] light_mask = 16 -position = Vector2(60, 0) +position = Vector2(-60, 0) sprite_frames = SubResource("SpriteFrames_k7dca") offset = Vector2(60, 0) @@ -158,5 +158,6 @@ unique_name_in_owner = true script = ExtResource("8_7lwt5") radius = 25.0 walk_to_edge = true +face_inside_on_edge = true action_on_arrived = 4 metadata/_custom_type_script = "uid://cnt01hiw52bmn" diff --git a/scene/entity/ux/sign_snapper.gd b/scene/entity/ux/sign_snapper.gd index 72b6f7f8..5668a340 100644 --- a/scene/entity/ux/sign_snapper.gd +++ b/scene/entity/ux/sign_snapper.gd @@ -13,6 +13,8 @@ signal arrived @export_range(0.0, 20.0, 0.1) var radius := 0.0 # 让玩家走到边缘,特别适用于 npc 对话等情景 @export var walk_to_edge := false +# 如果 walk_to_edge 为 true,那么走到 edge 后面朝内侧 +@export var face_inside_on_edge := false @export var action_on_arrived := 3 @export_tool_button("debug 检查玩家触发位置") var debug_check_player_pos = _debug_check_player_pos @@ -65,6 +67,12 @@ func _on_interacted(): tween = create_tween() else: tween = player.walk_to(target_pos) + if walk_to_edge and face_inside_on_edge: + # 玩家向右走到 target_pos.x 后,向左看向 global_position.x + if player_x < target_pos.x and target_pos.x > global_position.x: + tween.tween_callback(player.set_facing_direction.bind(Vector2(-1, 0))) + elif player_x > target_pos.x and target_pos.x < global_position.x: + tween.tween_callback(player.set_facing_direction.bind(Vector2(1, 0))) if delay_arrived > 0: tween.tween_interval(delay_arrived) if action_on_arrived != 3: diff --git a/scene/ground/camera/camera_focus_marker.gd b/scene/ground/camera/camera_focus_marker.gd index 880df4e5..07e9f041 100644 --- a/scene/ground/camera/camera_focus_marker.gd +++ b/scene/ground/camera/camera_focus_marker.gd @@ -22,7 +22,6 @@ var _tweeked_position := Vector2.ZERO var zoom_tween: Tween var focus_offset := Vector2.ZERO -var shaked_offset := Vector2.ZERO var shake_ignore_boundary := false @@ -31,7 +30,7 @@ func _ready() -> void: push_error("Focusing node not found") -func shake_camera(strength := 7.0, recovery_speed := 4.0, ignore_boundary := false): +func shake_camera(strength := 6.0, recovery_speed := 2.0, ignore_boundary := true): shake_strength = strength shake_recovery_speed = recovery_speed shake_ignore_boundary = ignore_boundary @@ -56,43 +55,56 @@ func tweak_position(velocity, facing_direction): _tweeked_position.y = facing_direction.y * abs(velocity.y) * 0.2 +# 处理过程的当下理想位置 +var progressing_position: Vector2 + + func _physics_process(delta: float) -> void: if not focusing_node: return - # handle shake, via _shaked_position - if shake_strength > 0.0: - shake_strength = lerpf(shake_strength, 0.0, shake_recovery_speed * delta) - shaked_offset = Vector2( - randf_range(-shake_strength, shake_strength), - randf_range(-shake_strength, shake_strength) - ) - else: - shaked_offset = Vector2.ZERO - shake_ignore_boundary = false - # set camera's position - var target_position = ( - focusing_node.global_position - + _tweeked_position - + force_offset - + focus_offset - + shaked_offset - ) + # 最终目标位置 + var target_position = focusing_node.global_position + _tweeked_position + force_offset if focusing_node is MainPlayer: # player 的焦点在脚底,所以需要偏移 player 的高度。注意 y 轴是向下的,所以是减去 player 的高度 target_position.y -= focusing_node.current_animation_config.os_height * 0.7 # clamp the position - if not shake_ignore_boundary: - var margin = half_screen_size / zoom_ratio - margin.y += shaded_height - target_position.x = clamp(target_position.x, limit_left + margin.x, limit_right - margin.x) - target_position.y = clamp(target_position.y, limit_top + margin.y, limit_bottom - margin.y) + target_position = _clamp_boundary(target_position) # easing with speed - global_position = lerp(global_position, target_position, speed * delta) + progressing_position = lerp(progressing_position, target_position, speed * delta) + global_position = progressing_position + + # handle shake + if shake_strength > 0.0: + # 让 shake_strength 逐帧衰减 + shake_strength = lerpf(shake_strength, 0.0, shake_recovery_speed * delta) + # [-shake_strength, +shake_strength] 范围内的同时,尽可能偏离中心 + # 在 0 – 2π 之间随机一个方向,在 _last_shake_angle 的对角范围 + # _last_shake_angle = wrapf(_last_shake_angle + randf_range(-2.0, 2.0), 0, TAU) # TAU = 2π + var _last_shake_angle := randf_range(-TAU, TAU) # TAU = 2π + var shaked_offset := ( + Vector2(cos(_last_shake_angle), sin(_last_shake_angle)) * shake_strength + ) + # var shaked_offset := Vector2( + # randf_range(-shake_strength, shake_strength), + # randf_range(-shake_strength, shake_strength) + # ) + global_position += shaked_offset + if not shake_ignore_boundary: + global_position = _clamp_boundary(global_position) + # var taget_zoom = lerpf(zoom.x, zoom_ratio, speed * delta) # zoom = Vector2(taget_zoom, taget_zoom) zoom = Vector2(zoom_ratio, zoom_ratio) +func _clamp_boundary(target: Vector2) -> Vector2: + var margin = half_screen_size / zoom_ratio + margin.y += shaded_height + target.x = clamp(target.x, limit_left + margin.x, limit_right - margin.x) + target.y = clamp(target.y, limit_top + margin.y, limit_bottom - margin.y) + return target + + func tween_zoom(ratio: float, duration := 1.5): if zoom_tween and zoom_tween.is_running(): zoom_tween.kill() diff --git a/scene/ground/camera/camera_focus_marker.tscn b/scene/ground/camera/camera_focus_marker.tscn index 92e5f9b5..1c73f089 100644 --- a/scene/ground/camera/camera_focus_marker.tscn +++ b/scene/ground/camera/camera_focus_marker.tscn @@ -3,5 +3,5 @@ [ext_resource type="Script" uid="uid://dphabatkubjgf" path="res://scene/ground/camera/camera_focus_marker.gd" id="1_7t4e6"] [node name="CameraFocusMarker" type="Camera2D"] -process_mode = 3 +process_mode = 1 script = ExtResource("1_7t4e6") diff --git a/scene/ground/ground_loader.gd b/scene/ground/ground_loader.gd index 2440f6ef..efd40c40 100644 --- a/scene/ground/ground_loader.gd +++ b/scene/ground/ground_loader.gd @@ -18,7 +18,6 @@ class_name GroundLoader extends Node2D var has_entered := false var ground: Ground2D -var display_mask_sec = 0.0 # 场景名字映射到路径 static var GROUND_SCENE_PATH_DICT = { @@ -52,9 +51,11 @@ static var GROUND_SCENE_PATH_DICT = { func _ready() -> void: - mask_layer.layer = GlobalConfig.CANVAS_LAYER_GROUND_MASK mask.visible = true mask.color.a = 0.0 + mask_layer.layer = GlobalConfig.CANVAS_LAYER_GROUND_MASK + # mask layer 独立的 always 处理模式,可以保证转场正常运行 + # toggle_mask = mask_layer.toggle_mask ground = get_node_or_null("Ground") as Ground2D if ground: print("GroundLoader remove old ground:", ground.scene_name) @@ -69,6 +70,35 @@ func _ready() -> void: # transition_to_scene(current_scene, entrance_portal, 0.0) +# # var toggle_mask:Callable +# func toggle_mask(display: bool, mask_color: Color, wait_time: float) -> Tween: +# return mask_layer.toggle_mask(display, mask_color, wait_time) + +var display_start_sec = 0.0 + +# wait_time 包含 ease in + wait + ease out 完整时长 +# ease duration = min(ease_min_duration, wait_time * 0.5) +func toggle_mask( + display: bool, wait_time: float, ease_min_duration := 0.3, mask_color:= Color.BLACK +) -> Tween: + var tween = get_tree().create_tween() + mask_color.a = mask.color.a + mask.color = mask_color + var duration = min(ease_min_duration, wait_time * 0.5) + if display: + display_start_sec = Time.get_ticks_msec() * 0.001 + tween.tween_property(mask, "color:a", 1.0, duration).set_trans(Tween.TRANS_CUBIC) + else: + # 转场至少 0.6s, 除去 0.3s 最后的淡出,需要 0.3s 的等待时间(包含 mask 的淡入) + if wait_time: + var time = Time.get_ticks_msec() * 0.001 + wait_time = max(wait_time + display_start_sec - time - 0.3, 0.0) + if wait_time: + tween.tween_interval(wait_time) + tween.tween_property(mask, "color:a", 0.0, duration).set_trans(Tween.TRANS_CUBIC) + return tween + + func _load_save(): # 强制覆盖 archive 记录 if force_archive_scene or force_archive_portal: @@ -82,27 +112,8 @@ func _load_save(): entrance_portal = ArchiveManager.archive.entrance_portal -func toggle_mask(display: bool, mask_color: Color, wait_time: float) -> Tween: - var tween = get_tree().create_tween() - mask_color.a = mask.color.a - mask.color = mask_color - var duration = min(0.3, wait_time * 0.5) - if display: - tween.tween_property(mask, "color:a", 1.0, duration).set_trans(Tween.TRANS_CUBIC) - display_mask_sec = Time.get_ticks_msec() * 0.001 - else: - # 转场至少 0.6s, 除去 0.3s 最后的淡出,需要 0.3s 的等待时间(包含 mask 的淡入) - if wait_time: - var time = Time.get_ticks_msec() * 0.001 - wait_time = max(wait_time + display_mask_sec - time - 0.3, 0.0) - if wait_time: - tween.tween_interval(wait_time) - tween.tween_property(mask, "color:a", 0.0, duration).set_trans(Tween.TRANS_CUBIC) - return tween - - func transition_to_scene( - scene_name: String, portal: String, wait_time := 1.4, mask_color := Color.BLACK + scene_name: String, portal: String, wait_time := 1.4 ) -> void: if ground: print("GroundLoader transition_to_scene: pause prev ground.") @@ -119,11 +130,11 @@ func transition_to_scene( _update_archive() if wait_time > 0.0: # 转场效果,在 _load_ground_node 之前播放 - var tween = toggle_mask(true, mask_color, wait_time) + var tween = toggle_mask(true, wait_time) tween.tween_callback(_do_transition.call_deferred.bind(scene_name)) _allow_ground_start = false # 等到 toggle_mask 结束,再重置 freeze 状态 - toggle_mask(false, mask_color, wait_time).tween_callback( + toggle_mask(false, wait_time).tween_callback( func(): _allow_ground_start = true ) else: @@ -141,7 +152,7 @@ var _allow_ground_start := false: if val: if ground.process_mode != Node.PROCESS_MODE_INHERIT: # ground_start 信号 - SceneManager.ground_start.emit(ground) + SceneManager.ground_start.emit() ground.process_mode = Node.PROCESS_MODE_INHERIT print( "GroundLoader _allow_ground_start: unfrozen. frozen duration(ms):", @@ -177,7 +188,7 @@ func _do_transition(scene_name: String) -> void: _add_ground() if _allow_ground_start: # 如果不阻塞,直接 ground_start 信号 - SceneManager.ground_start.emit(ground) + SceneManager.ground_start.emit() # 预先加载邻居场景 _post_transition() if GlobalConfig.DEBUG and not Engine.is_editor_hint(): diff --git a/scene/ground/ground_loader.tscn b/scene/ground/ground_loader.tscn index 7b71f20b..5c0510ae 100644 --- a/scene/ground/ground_loader.tscn +++ b/scene/ground/ground_loader.tscn @@ -25,6 +25,7 @@ color = Color(0, 0, 0, 1) [node name="MaskLayer" type="CanvasLayer" parent="."] unique_name_in_owner = true +process_mode = 3 layer = 14 [node name="Mask" type="ColorRect" parent="MaskLayer"] diff --git a/scene/ground/scene/animation_root.gd b/scene/ground/scene/animation_root.gd index d27ac868..b21f7ca5 100644 --- a/scene/ground/scene/animation_root.gd +++ b/scene/ground/scene/animation_root.gd @@ -56,10 +56,6 @@ func _on_ground_ready() -> void: pass -func _on_ground_start() -> void: - pass - - func _on_ready() -> void: if Engine.is_editor_hint(): return diff --git a/scene/ground/scene/c01/s05_院长房间.gd b/scene/ground/scene/c01/s05_院长房间.gd index be3c1b71..aa1063d4 100644 --- a/scene/ground/scene/c01/s05_院长房间.gd +++ b/scene/ground/scene/c01/s05_院长房间.gd @@ -21,7 +21,7 @@ func intro_start(): await animation_finished SceneManager.release_player() $"../DeployLayer/床".enabled = true - await get_tree().create_timer(1.0).timeout + await Util.wait(1) show_interact_help() func play_intro_dialogue(): @@ -37,7 +37,7 @@ func _on_ground_ready() -> void: piano = $"../DeployLayer/钢琴" if data["oneshot_animation_played"]: $"../DeployLayer/床".enabled = true - get_tree().create_timer(1.0).timeout.connect(show_interact_help) + Util.timer(1.0, show_interact_help) # 画框是否已经正位 data.frame_relocated = ambush.played and ambush.one_shot # 禁用鸡毛掸子 @@ -81,15 +81,15 @@ func cant_read(): func _on_note_read(): frame.enabled = false # 稍加延时后显示鸡毛掸子 - get_tree().create_timer(4.5).timeout.connect(func(): ambush.enabled = true) + Util.timer(4.5, func(): ambush.enabled = true) func _on_ambush_triggered(): ambush.enabled = false frame.note_key = "c01_摆正的洋相片" - get_tree().create_timer(5.5).timeout.connect(func(): frame.enabled = true) + Util.timer(5.5, func(): frame.enabled = true) # 鸡毛掸子 4.5s,再等待 3s 后掉落纸片 - get_tree().create_timer(8).timeout.connect(_play_paper_animation) + Util.timer(8, _play_paper_animation) func lock_on_use_stick(): SceneManager.lock_player(4.0) diff --git a/scene/ground/scene/c01/s06_孤儿院长廊围墙.gd b/scene/ground/scene/c01/s06_孤儿院长廊围墙.gd index 5aeb33bc..d12e0e68 100644 --- a/scene/ground/scene/c01/s06_孤儿院长廊围墙.gd +++ b/scene/ground/scene/c01/s06_孤儿院长廊围墙.gd @@ -97,12 +97,12 @@ func pre_game_intro(): camera.tween_zoom(1.5, 3.0) var p = $"../DeployLayer/四小孩画鬼差的对话ambush/FocusPoint" camera.focus_node(p, 3.0) - await get_tree().create_timer(1.5).timeout + await Util.wait(1.5) DialogueManager.show_dialogue_balloon(dialogue_c01, "c01_s06_四个小孩画鬼差的对话") await DialogueManager.dialogue_ended # 重置镜头 SceneManager.focus_player_and_reset_zoom(2.5) - await get_tree().create_timer(1.5).timeout + await Util.wait(1.5) await SceneManager.pop_os_with_str("c01_s06_熟悉的墙画") SceneManager.unlock_player() @@ -117,7 +117,6 @@ func game_intro() -> void: var camera = SceneManager.get_camera_marker() as CameraFocusMarker camera.tween_zoom(1.5, 3.0) camera.focus_node(focus_point, 3.0) - # get_tree().create_timer(1.0).timeout.connect(camera.focus_node.bind(focus_point, 3.)) standing_kid1.play("【站立小孩-1】挠痒呼吸") standing_kid2.play("【站立小孩-2】转身") # 只有 1、2 是跟班,3 不参与 @@ -144,7 +143,7 @@ func _game_counting_down(_res = null): var player = SceneManager.get_player() as MainPlayer var left = player.global_position.x player.player_movement_rect.position.x = left - get_tree().create_timer(2.0).timeout.connect(_kids_start_run) + Util.timer(2.0, _kids_start_run) cat.visible = true cat.play("【墙上黑猫】跑步") cat.get_node("猫咪嘶吼音效").play() @@ -175,7 +174,7 @@ func _on_talked(): # 三个小孩都对话完毕 await DialogueManager.dialogue_ended SceneManager.lock_player() - await get_tree().create_timer(1.0).timeout + await Util.wait(1) await SceneManager.pop_os_with_str("c01_s06_四小孩对话结束") SceneManager.unlock_player() @@ -243,6 +242,7 @@ func obstacles_ambush3_triggered(): game_kid.sprite_frames.set_animation_loop("【胖小孩背着残疾小孩】摔倒", false) game_kid.animation_finished.connect(_on_kid_fall_finished, CONNECT_ONE_SHOT) + # 残疾小孩冲刺 func _on_kid_fall_finished(): obstacles.get_node("遮盖").visible = true @@ -258,7 +258,6 @@ func _on_kid_fall_finished(): tween.tween_property(cat_shadow, "modulate:a", 0.0, 4.0) - func _on_mid_ambush_success(): obstacles_success = true # TODO 获得成就 @@ -273,11 +272,10 @@ func game_restart(): game_kid.play("【胖小孩背着残疾小孩】侧面呼吸") SceneManager.freeze_player(0) SceneManager.pop_debug_dialog_info("音效", "玩家被抓住,猫鼠游戏重新开始") - await get_tree().create_timer(1.5).timeout - var ground_loader = SceneManager.get_ground_loader() + await Util.wait(1.5) # 过场黑屏 - ground_loader.toggle_mask(true, Color.BLACK, 0.5) - await get_tree().create_timer(0.5).timeout + SceneManager.toggle_ground_mask(true) + await Util.wait(0.5) # 重置桌椅 obstacles_pushed = false obstacles_success = false @@ -288,13 +286,13 @@ func game_restart(): standing_kid1.global_position.x = kids_start_run_initial_x[0] standing_kid2.global_position.x = kids_start_run_initial_x[1] game_kid.global_position.x = kids_start_run_initial_x[2] - ground_loader.toggle_mask(false, Color.BLACK, 1.0) - await get_tree().create_timer(1.0).timeout + SceneManager.toggle_ground_mask(false) + await Util.wait(1.0) # 开始跑 SceneManager.release_player() $"Sfx猫鼠游戏".set("parameters/switch_to_clip", "Intro") DialogueManager.show_dialogue_balloon(dialogue_c01, "c01_s06_猫鼠游戏倒计时") - await get_tree().create_timer(1.5).timeout + await Util.wait(1.5) _kids_start_run() @@ -369,7 +367,7 @@ func transport_player_to_next_scene(win: bool): _show_next_scene(true) SceneManager.pop_debug_dialog_info("音效", "猫鼠游戏胜利,无缝转场") else: - get_tree().create_timer(0.7).timeout.connect(_show_next_scene.bind(false)) + Util.timer(0.7, _show_next_scene.bind(false)) SceneManager.pop_debug_dialog_info("音效", "猫鼠游戏失败,传送下一场景") diff --git a/scene/ground/scene/c01/s07_书店外.gd b/scene/ground/scene/c01/s07_书店外.gd index ad016eec..a07dc05a 100644 --- a/scene/ground/scene/c01/s07_书店外.gd +++ b/scene/ground/scene/c01/s07_书店外.gd @@ -34,7 +34,7 @@ func _on_ground_ready() -> void: var camera = SceneManager.get_camera_marker() camera.limit_left = -400 create_tween().tween_property(camera, "limit_left", 0, 5.0) - get_tree().create_timer(5.0).timeout.connect(_on_fog_disappear) + Util.timer(5.0, _on_fog_disappear) seller = $"../DeployLayer/报童" as AnimatedSprite2D ambush_seller = $"../DeployLayer/报童/Ambush报童" as Ambush2D bookstore_portal = $"../DeployLayer/portal_2" @@ -67,9 +67,9 @@ func _on_luren_animation_finished() -> void: func _knock_door(): # 6 号动作:敲门 SceneManager.lock_player(3.5, 6) - await get_tree().create_timer(2.2).timeout + await Util.wait(2.2) $"敲门音效".play() - await get_tree().create_timer(1.2).timeout + await Util.wait(1.2) var stream = preload("res://asset/audio/sfx/交互/序章/03_书店外黄昏_开门.wav") AudioManager.play_sfx(stream) @@ -80,8 +80,6 @@ func _on_fog_disappear() -> void: var chapter_title = preload("res://asset/art/scene/c01/s02_旧版序章/f_序章标题.png") SceneManager.pop_center_texture(chapter_title) fog.tween_fog(0, Color.TRANSPARENT, Fog2D.FOG_OFFSET_DEFAULT, 15.0, true) - # await get_tree().create_timer(5.0).timeout - func seller_interacted(): bookstore_portal.holding = false @@ -90,7 +88,7 @@ func seller_interacted(): seller.play("报童给报纸") # 提前写入 prop 中,防止存档 bug,稍后播放获得动画 SceneManager.enable_prop_item_silently("prop_信碎片2") - await get_tree().create_timer(1.5).timeout + await Util.wait(1.5) $"报童音效".play() SceneManager.pop_os_with_str("c01_s07_获得报纸") await SceneManager.get_player().os_finished diff --git a/scene/ground/scene/c01/s07_书店外.tscn b/scene/ground/scene/c01/s07_书店外.tscn index 5f3e99d9..9358361b 100644 --- a/scene/ground/scene/c01/s07_书店外.tscn +++ b/scene/ground/scene/c01/s07_书店外.tscn @@ -210,7 +210,7 @@ loop = true metadata/_custom_type_script = "uid://wapo47a1oddf" [node name="Npc吉祥话4" parent="Ground/DeployLayer/陆仁舞刀" instance=ExtResource("6_fw22n")] -position = Vector2(-22, 51) +position = Vector2(-14, 51) enabled = false speaking_sign_height = 47.0 dialogue_title = "c01_s07_陆仁吉祥话" diff --git a/scene/ground/scene/c01/s08_书店.gd b/scene/ground/scene/c01/s08_书店.gd index 02ca2f31..6a7b8fb2 100644 --- a/scene/ground/scene/c01/s08_书店.gd +++ b/scene/ground/scene/c01/s08_书店.gd @@ -91,7 +91,7 @@ func _on_envolope_table_interacted() -> void: func first_enter_door() -> void: SceneManager.freeze_player(0) - await get_tree().create_timer(1.5).timeout + await Util.wait(1.5) DialogueManager.show_dialogue_balloon(dialogue_c01, "c01_s08_书店进门老板台词") await DialogueManager.dialogue_ended SceneManager.release_player() @@ -100,7 +100,7 @@ func first_enter_door() -> void: func assign_tasks() -> void: # 放报纸动作 SceneManager.freeze_player(0, 8, false) - await get_tree().create_timer(4.5).timeout + await Util.wait(4.5) $"放报纸音效".play() DialogueManager.show_dialogue_balloon(dialogue_c01, "c01_s08_书店老板任务") await DialogueManager.dialogue_ended @@ -126,7 +126,9 @@ func _on_shelf_game_exiting() -> void: create_tween().tween_property(mask, "color:a", 0.0, 1.0).from(1.0) SceneManager.release_player() -var fall_off + +var fall_off + func _on_shelf_game_success() -> void: ArchiveManager.archive.set_global_entry(&"c01_shelf_game_success", true) @@ -146,31 +148,35 @@ func _on_shelf_game_success() -> void: fall_off.play() fall_off.animation_finished.connect(_on_fall_off_finished) # 从 sfx_生死簿演出 中退出时播放不出来,需要在此处播放 - $"摔倒音效".play() + Util.timer(0.5, $"摔倒音效".play) _check_portal() + func _on_fall_off_finished() -> void: fall_off.visible = false # 最后释放玩家 SceneManager.release_player() SceneManager.get_player().hide_sprite = false - await get_tree().create_timer(1.2).timeout + await Util.wait(1.2) SceneManager.pop_os_with_str("c01_s08_书架游戏完成") + func _setup_weird_bookstore() -> void: # 切换背景音效 $"环境音".stop() $"诡异环境音".play() # 光变红 $"../AmbientLayer/PointLight2D".color = Color.html("#ff2719") - + coin.enabled = true ladder.enabled = false manager.visible = false mice.visible = true $"../DirectionalLight2D".energy = 0.7 $"../BGSprite2D".texture = preload("res://asset/art/scene/c01/s08_书店/夜晚版/bg_书店夜晚.png") - $"../ParallaxForeground/FGParallaxLayer/FGSprite2D".texture = preload("res://asset/art/scene/c01/s08_书店/夜晚版/fg_书店夜晚前景.png") + $"../ParallaxForeground/FGParallaxLayer/FGSprite2D".texture = preload( + "res://asset/art/scene/c01/s08_书店/夜晚版/fg_书店夜晚前景.png" + ) ladder.texture = preload("res://asset/art/scene/c01/s08_书店/夜晚版/e_梯子 夜晚.png") @@ -199,10 +205,9 @@ func _on_envelope_game_success() -> void: func pay_off_wage() -> void: SceneManager.enable_prop_item("prop_银元") SceneManager.enable_important_item("prop_银元") - SceneManager.get_inspector().quit_and_hidden.connect( - _on_quit_inspect_coin, CONNECT_ONE_SHOT - ) + SceneManager.get_inspector().quit_and_hidden.connect(_on_quit_inspect_coin, CONNECT_ONE_SHOT) _check_portal() + func _on_quit_inspect_coin() -> void: SceneManager.pop_os_with_str("c01_s08_获得袁大头后") diff --git a/scene/ground/scene/c01/s11_黄包车演出.gd b/scene/ground/scene/c01/s11_黄包车演出.gd index 7bf0365e..67e6fa13 100644 --- a/scene/ground/scene/c01/s11_黄包车演出.gd +++ b/scene/ground/scene/c01/s11_黄包车演出.gd @@ -27,25 +27,26 @@ func _ready() -> void: func _on_ground_ready() -> void: + var camera = SceneManager.get_camera_marker() + camera.limit_top = -1000 + camera.limit_bottom = 158 + await Util.wait(1.0) + # 相机抖动 + camera.shake_camera() # 不显示玩家,锁定玩家移动 SceneManager.freeze_player(0) main_character = $"../DeployLayer/车夫与吕萍" footstep_sfx = $"黄包车Sfx" chapter_sfx = $chapter_sfx - SceneManager.get_camera_marker().limit_bottom = 158 - SceneManager.get_camera_marker().limit_top = -158 - SceneManager.set_camera_boundary(Rect2(0, -1000, 11360, 1158)) - await get_tree().create_timer(1.0).timeout - # 相机抖动 - SceneManager.get_camera_marker().shake_camera(8.0, 2.0) # 注意第一段 dialog 在鬼差探头阶段播放 play("intro") - + # ## test 测试最后运镜 ## # main_character.global_position.x = target_x # await get_tree().create_timer(1.0).timeout # _on_finished() + func dialog1() -> void: DialogueManager.dialogue_ended.connect(_start_running, CONNECT_ONE_SHOT) # 注意第一段 dialog 在鬼差探头阶段播放 @@ -102,6 +103,7 @@ func dialog3() -> void: dialogue_c01, "c01_s11_车夫对话3", [GlobalConfig.DIALOG_IGNORE_INPUT] ) + func dialog4() -> void: DialogueManager.show_dialogue_balloon( dialogue_c01, "c01_s11_车夫对话4", [GlobalConfig.DIALOG_IGNORE_INPUT] @@ -126,17 +128,19 @@ func _on_finished(): tween.tween_property(marker, "global_position:y", target_y, building_duration) tween.tween_callback(_show_chapter) + func final_dialog(): - await get_tree().create_timer(2.0).timeout + await Util.wait(2.0) DialogueManager.show_dialogue_balloon( dialogue_c01, "c01_s11_车夫对话5", [GlobalConfig.DIALOG_IGNORE_INPUT] ) + # 展示章节转场 func _show_chapter(): chapter_sfx.play() SceneManager.pop_center_texture(chapter_title) - get_tree().create_timer(3.5).timeout.connect(_transition) + Util.timer(3.5, _transition) func _transition(): diff --git a/scene/ground/scene/c01/s11_黄包车演出.tscn b/scene/ground/scene/c01/s11_黄包车演出.tscn index eca70692..fcbadf9b 100644 --- a/scene/ground/scene/c01/s11_黄包车演出.tscn +++ b/scene/ground/scene/c01/s11_黄包车演出.tscn @@ -547,7 +547,7 @@ character = "小小蝶" [node name="CameraFocusMarker" parent="Ground" index="6" node_paths=PackedStringArray("focusing_node")] focusing_node = NodePath("../DeployLayer/车夫与吕萍") -force_offset = Vector2(50, -48) +force_offset = Vector2(30, -30) [node name="点缀 黄包车车夫" type="Sprite2D" parent="Ground/ParallaxForeground/BGParallaxLayer" index="0"] position = Vector2(687, 77) diff --git a/scene/ground/scene/c01/s12_书店外_诡异版.gd b/scene/ground/scene/c01/s12_书店外_诡异版.gd index faf88ab8..211932d0 100644 --- a/scene/ground/scene/c01/s12_书店外_诡异版.gd +++ b/scene/ground/scene/c01/s12_书店外_诡异版.gd @@ -56,7 +56,7 @@ func intro() -> void: begger.play("杂戏团夜晚_小孩举碗呼吸") # SceneManager.freeze_player(0) # SceneManager.focus_node(begger, 5.) - get_tree().create_timer(1.).timeout.connect(_intro_dialog) + Util.timer(1., _intro_dialog) func _intro_dialog() -> void: @@ -70,7 +70,7 @@ func _intro_dialog() -> void: func ambush_begger_interacted(): begger.play("杂戏团夜晚_小孩放下碗") SceneManager.lock_player(0) - await get_tree().create_timer(1.).timeout + await Util.wait(1) DialogueManager.show_dialogue_balloon(dialogue_c01, "c01_s12_小孩放下碗") await DialogueManager.dialogue_ended SceneManager.unlock_player() @@ -83,7 +83,7 @@ func _on_interactable_bowl_interacted() -> void: DialogueManager.show_dialogue_balloon(dialogue_c01, "c01_s12_鬼差来之前对话") await DialogueManager.dialogue_ended _ghost_move() - await get_tree().create_timer(1.0).timeout + await Util.wait(1) # 害怕过渡 -> 害怕 begger.play("举碗小孩害怕过渡") var kids = $"../DeployLayer/其余小孩" @@ -91,7 +91,7 @@ func _on_interactable_bowl_interacted() -> void: var kid = $"../DeployLayer/举腿小孩" kid.play("夜晚举腿小孩杂耍到害怕过渡") $"Sfx鬼差出场".play() - await get_tree().create_timer(1.0).timeout + await Util.wait(1) DialogueManager.show_dialogue_balloon(dialogue_c01, "c01_s12_鬼差来了") var tween = create_tween() var camera = SceneManager.get_camera_marker() @@ -143,14 +143,12 @@ func player_been_catched(transition := true) -> void: SceneManager.pop_debug_dialog_info("美术", "玩家被鬼差抓住") # 等待动画播放完成 # TODO 添加转场前效果? - await get_tree().create_timer(1.5).timeout - var ground_loader = SceneManager.get_ground_loader() + await Util.wait(1.5) # 传送到起点,继续跑 - ground_loader.toggle_mask(true, Color.BLACK, 0.5) - await get_tree().create_timer(0.5).timeout + await SceneManager.toggle_ground_mask(true).finished # 恢复花朵 flower.reset_all_blooming() - ground_loader.toggle_mask(false, Color.BLACK, 1.0) + await SceneManager.toggle_ground_mask(false).finished # reset player and ghost position ghost.global_position.x = ghost_start_x + 100.0 SceneManager.get_player().global_position.x = player_start_x diff --git a/scene/ground/scene/c02/s01_公寓门口.gd b/scene/ground/scene/c02/s01_公寓门口.gd index f1d8856a..dc35e5e6 100644 --- a/scene/ground/scene/c02/s01_公寓门口.gd +++ b/scene/ground/scene/c02/s01_公寓门口.gd @@ -14,7 +14,7 @@ func _ready() -> void: return # if not data["received_letter"]: # SceneManager.freeze_player(1.5) - # get_tree().create_timer(1.5).timeout.connect(_give_letter) + # Util.timer(1.5, _give_letter) # elif GlobalConfig.DEBUG: # print("_give_letter 已发放") diff --git a/scene/ground/scene/c02/s03_院子.gd b/scene/ground/scene/c02/s03_院子.gd index 9d482f93..9985ea2d 100644 --- a/scene/ground/scene/c02/s03_院子.gd +++ b/scene/ground/scene/c02/s03_院子.gd @@ -86,7 +86,7 @@ func _on_ground_ready() -> void: if EventManager.get_stage("c02_madman_interacted") == 1: SceneManager.lock_player(0) # 等待转场 - await get_tree().create_timer(1.0).timeout + await Util.wait(1) small_shoe.enabled = true var y2 = small_shoe.position.y var y1 = y2 - 150 @@ -175,16 +175,16 @@ func eavesdrop() -> void: # 12 c00_吕萍_蹲下 13 c00_吕萍_蹲下呼吸 14 c00_吕萍_起立 SceneManager.lock_player(0, 12) # play("eavesdrop") - await get_tree().create_timer(1.0).timeout + await Util.wait(1) SceneManager.player_action(13) # 对话 DialogueManager.show_dialogue_balloon(dialogue_c02, "c02_04_李氏癞子") await DialogueManager.dialogue_ended eavesdrop_window.visible = false - await get_tree().create_timer(1.0).timeout + await Util.wait(1) SceneManager.player_action(14, true) ArchiveManager.set_global_entry(&"c02_eavesdrop_finished", true) - await get_tree().create_timer(1.5).timeout + await Util.wait(1.5) SceneManager.unlock_player() diff --git a/scene/ground/scene/c02/s04_保卫科.gd b/scene/ground/scene/c02/s04_保卫科.gd index aac9a6fc..230be9d5 100644 --- a/scene/ground/scene/c02/s04_保卫科.gd +++ b/scene/ground/scene/c02/s04_保卫科.gd @@ -27,5 +27,5 @@ func _on_closeup_tin_coin_exited(arg = null): if arg == true: ArchiveManager.set_global_entry(&"c02_tin_coin_taken", true) SceneManager.enable_prop_item_silently("prop_锡箔元宝") - await get_tree().create_timer(0.5).timeout + await Util.wait(0.5) SceneManager.enable_prop_item("prop_锡箔元宝") diff --git a/scene/ground/scene/c02/s06_二楼.gd b/scene/ground/scene/c02/s06_二楼.gd index 911839ad..225cff94 100644 --- a/scene/ground/scene/c02/s06_二楼.gd +++ b/scene/ground/scene/c02/s06_二楼.gd @@ -44,7 +44,7 @@ func _on_ground_ready() -> void: mice_hole.enabled = false gas_light_upon_hole.lighted.connect(func(): mice_hole.enabled = true - get_tree().create_timer(1.5).timeout.connect( + Util.timer(1.5, SceneManager.pop_os_with_str.bind("c02_二楼血脚印") ) ) diff --git a/scene/ground/scene/c02/s07_二楼内侧楼道.gd b/scene/ground/scene/c02/s07_二楼内侧楼道.gd index d5fae4ba..7270f635 100644 --- a/scene/ground/scene/c02/s07_二楼内侧楼道.gd +++ b/scene/ground/scene/c02/s07_二楼内侧楼道.gd @@ -43,12 +43,4 @@ func take_off_flyer(immediatelly = false): flyer.visible = false var hand = $"../DeployLayer/小手讨东西" hand.enabled = true - # if hand.icount == 0: - # await get_tree().create_timer(1.0).timeout - # hand.icount += 1 - # SceneManager.lock_player() - # await hand.do_first_interact(immediatelly) - # SceneManager.unlock_player() - - diff --git a/scene/ground/scene/c02/s08_瞎子卧室.gd b/scene/ground/scene/c02/s08_瞎子卧室.gd index 31d954e1..acdd7a29 100644 --- a/scene/ground/scene/c02/s08_瞎子卧室.gd +++ b/scene/ground/scene/c02/s08_瞎子卧室.gd @@ -98,7 +98,7 @@ func eavesdrop_start() -> void: var node = $"../DeployLayer/瞎子小蝉对话" node.visible = true # 偷听动作 - await get_tree().create_timer(2.0).timeout + await Util.wait(2.0) # 动作后先出声音 DialogueManager.show_dialogue_balloon(dialogue_c02, "c02_05_瞎子与小蝉") var tween = create_tween() diff --git a/scene/ground/scene/c02/s09_裂缝.gd b/scene/ground/scene/c02/s09_裂缝.gd index 624e6812..1f694250 100644 --- a/scene/ground/scene/c02/s09_裂缝.gd +++ b/scene/ground/scene/c02/s09_裂缝.gd @@ -36,7 +36,7 @@ func _on_ground_ready() -> void: var half_length = rope_length / 2.0 rope_range.x = rope.global_position.x - half_length rope_range.y = rope.global_position.x + half_length - await get_tree().create_timer(0.1).timeout + await Util.wait(0.1) var player = %MainPlayer # 玩家位置更新时,更新麻绳隆起 player.position_updated.connect(_on_player_position_updated) diff --git a/scene/ground/scene/c02/s13_盒子猫二楼.gd b/scene/ground/scene/c02/s13_盒子猫二楼.gd index 71d092d5..db1811bb 100644 --- a/scene/ground/scene/c02/s13_盒子猫二楼.gd +++ b/scene/ground/scene/c02/s13_盒子猫二楼.gd @@ -24,12 +24,12 @@ func knock_light_door(): for _i in range(100): AudioManager.play_sfx(knock_stream) SceneManager.lock_player(0, 6) - await get_tree().create_timer(0.5).timeout + await Util.wait(0.5) # 被抓时打断 if not player.visible or player.hide_sprite: _outtro_show() break - await get_tree().create_timer(0.5).timeout + await Util.wait(0.5) # 被抓时打断 if not player.visible or player.hide_sprite: _outtro_show() @@ -42,10 +42,10 @@ func _outtro_show(): # 禁止猪头怪动画播放结束后重开游戏 $"../DeployLayer/追猫猪头怪_传送".allow_restart_game = false $"Sfx结尾演出".play() - await get_tree().create_timer(8.0).timeout + await Util.wait(8.0) $"../盒子猫CanvasLayer".show_footprint() $"Sfx脚印".play() # 盒子猫逃脱成功/被抓走,游戏结束,解锁瞎子卧室门 - await get_tree().create_timer(10.0).timeout + await Util.wait(10.0) ArchiveManager.set_global_entry(&"c02_the_blind_room_unlocked", true) SceneManager.get_ground_loader().transition_to_scene("c02_s08", "1") diff --git a/scene/ground/script/c01/s10_鬼差探头.gd b/scene/ground/script/c01/s10_鬼差探头.gd index 6d56a25e..d5e06cef 100644 --- a/scene/ground/script/c01/s10_鬼差探头.gd +++ b/scene/ground/script/c01/s10_鬼差探头.gd @@ -22,7 +22,7 @@ func play_bgm(): func pre_finished(): # 在 animation player 结束前 1 秒调用 - CanvasUtil.shake_layer(self, 2.0, 4.0, 15.0) + Util.shake_layer(self, 2.0, 4.0, 15.0) # debug 模式允许跳过 if GlobalConfig.DEBUG: DialogueManager.show_dialogue_balloon(dialogue_c01, "c01_s11_车夫对话1") diff --git a/scene/ground/script/c01/s12_飘动的寻人启事.gd b/scene/ground/script/c01/s12_飘动的寻人启事.gd index 472ba5f8..8f4f452f 100644 --- a/scene/ground/script/c01/s12_飘动的寻人启事.gd +++ b/scene/ground/script/c01/s12_飘动的寻人启事.gd @@ -71,8 +71,8 @@ func _on_interacted() -> void: $SfxOpen.play() var inspect_texture = preload("res://asset/art/scene/c01/s07_书店外/纸片_正面.png") var res = preload("res://asset/dialogue/inspect_content.dialogue") - var lines = await DialogueUtil.get_lines(res, "c01_飘落的寻人启事") - var note = DialogueUtil.concact_content_from_lines(lines) + var lines = await Util.get_lines(res, "c01_飘落的寻人启事") + var note = Util.concact_content_from_lines(lines) SceneManager.get_inspector().pop_standard_inspection(inspect_texture, null, note, false) diff --git a/scene/ground/script/c02/s00_煤油灯.gd b/scene/ground/script/c02/s00_煤油灯.gd index ca7ae739..57bcd800 100644 --- a/scene/ground/script/c02/s00_煤油灯.gd +++ b/scene/ground/script/c02/s00_煤油灯.gd @@ -135,14 +135,14 @@ func _gaslight_interacted(): else: # 高位 5 号 SceneManager.freeze_player(2.0, 5) - await get_tree().create_timer(0.8).timeout + await Util.wait(0.8) sfx_success.play() - await get_tree().create_timer(1.0).timeout + await Util.wait(1) _switch_gaslight(true, true) lighted.emit() if not ArchiveManager.get_global_value(&"c02_gaslight_first_lighted"): ArchiveManager.set_global_entry(&"c02_gaslight_first_lighted", true) var scene = ArchiveManager.archive.current_scene if scene == "c02_s02" or scene == "c02_s03": - await get_tree().create_timer(1.0).timeout + await Util.wait(1) SceneManager.pop_os_with_str("c02_使用煤油灯") diff --git a/scene/ground/script/c02/刮海报_过道.tscn b/scene/ground/script/c02/刮海报_过道.tscn index 0e485781..12c8ca43 100644 --- a/scene/ground/script/c02/刮海报_过道.tscn +++ b/scene/ground/script/c02/刮海报_过道.tscn @@ -52,6 +52,7 @@ texture = SubResource("ImageTexture_cffxi") stretch_mode = 5 [node name="Sfx撕海报" type="AudioStreamPlayer" parent="."] +process_mode = 1 stream = ExtResource("5_xjg44") bus = &"game_sfx" script = ExtResource("6_cffxi") diff --git a/scene/ground/script/c02/小手讨东西.gd b/scene/ground/script/c02/小手讨东西.gd index 76708492..198ffc80 100644 --- a/scene/ground/script/c02/小手讨东西.gd +++ b/scene/ground/script/c02/小手讨东西.gd @@ -66,7 +66,7 @@ var icount: int: # 9 小手交互,吓摔倒 SceneManager.lock_player(0, 9, true) SceneManager.pop_os_with_str("c02_小手出现摔倒") - get_tree().create_timer(1.5).timeout.connect($"Sfx摔倒".play) + Util.timer(1.5, $"Sfx摔倒".play) await SceneManager.get_player().animation_finished SceneManager.unlock_player() elif stage == 1: @@ -194,7 +194,7 @@ func _on_interacted() -> void: SceneManager.pop_debug_dialog_info( "美术", "叠成纸杯: 小手_锡箔_hide + 小手_纸杯_show + 小手_纸杯_idle" ) - await get_tree().create_timer(2).timeout + await Util.wait(2.0) # 稍等片刻再给小鞋子 SceneManager.enable_prop_item("prop_小鞋子1") await SceneManager.get_inspector().quit_and_hidden @@ -210,7 +210,7 @@ func _on_interacted() -> void: # 先设置允许 pickable,然后再设置可见性,等待动画播完再显示 tin_coin_drop = true coin.visible = false - await get_tree().create_timer(1.5).timeout + await Util.wait(1.5) coin.visible = true if not ArchiveManager.get_global_value(&"c02_little_hand_dropped_tin"): SceneManager.pop_os_with_str("c02_小手要东西") @@ -224,7 +224,7 @@ func _on_interacted() -> void: SceneManager.disable_prop_item("prop_老虎钳") animated_sprite.play("小手_老虎钳_hide") SceneManager.pop_debug_dialog_info("美术", "小手_老虎钳_hide + 小手_弹珠_show + 小手_弹珠_idle") - await get_tree().create_timer(1.5).timeout + await Util.wait(1.5) holding_prop = "prop_弹珠" EventManager.set_stage_if_greater("handnote_stage", 4) elif id == 0 and key == "prop_弹珠" and not pliers_to_ball: @@ -233,7 +233,7 @@ func _on_interacted() -> void: SceneManager.disable_prop_item("prop_弹珠") animated_sprite.play("小手_弹珠_hide") SceneManager.pop_debug_dialog_info("美术", "小手_弹珠_hide + 小手_老虎钳_show + 小手_老虎钳_idle") - await get_tree().create_timer(1.5).timeout + await Util.wait(1.5) holding_prop = "prop_老虎钳" if interacted_success: diff --git a/scene/ground/script/c02/敲门游戏.gd b/scene/ground/script/c02/敲门游戏.gd index eede0b98..e8a7edcf 100644 --- a/scene/ground/script/c02/敲门游戏.gd +++ b/scene/ground/script/c02/敲门游戏.gd @@ -59,7 +59,7 @@ func _on_button_pressed() -> void: button.disabled = true # 肉落下的声音,然后自动退出界面 SceneManager.pop_debug_dialog_info("音效", "肉落下的声音(敲门游戏成功)") - await get_tree().create_timer(2.0).timeout + await Util.wait(2) exit.emit(true) else: SceneManager.pop_debug_dialog_info("音效", "敲门:" + str(current_id)) diff --git a/scene/ground/script/c02/水盆特写.gd b/scene/ground/script/c02/水盆特写.gd index ac6f3111..d566bce0 100644 --- a/scene/ground/script/c02/水盆特写.gd +++ b/scene/ground/script/c02/水盆特写.gd @@ -25,7 +25,7 @@ func _ready() -> void: tween.tween_property(child_sprite, "modulate:a", 0.0, 0.5) else: child_sprite.modulate.a = 0 - await get_tree().create_timer(1.5).timeout + await Util.wait(1.5) _try_ripple() func _try_ripple(): diff --git a/scene/ground/script/c02/裂缝议论文字.gd b/scene/ground/script/c02/裂缝议论文字.gd index e6b4319d..d6730d7b 100644 --- a/scene/ground/script/c02/裂缝议论文字.gd +++ b/scene/ground/script/c02/裂缝议论文字.gd @@ -28,7 +28,7 @@ func _on_area_entered(_body): if not _body is MainPlayer: return label.visible = true - await get_tree().create_timer(randf()).timeout + await Util.wait(randf()) var tween = create_tween() tween.tween_property(label, "position:y", 3.0, 0.6).set_trans(Tween.TRANS_BOUNCE) tween.tween_property(label, "position:y", 0.0, 0.6).set_trans(Tween.TRANS_BOUNCE) diff --git a/scene/ground/script/c02/谢幕演出.gd b/scene/ground/script/c02/谢幕演出.gd index c451aaea..2798fbc1 100644 --- a/scene/ground/script/c02/谢幕演出.gd +++ b/scene/ground/script/c02/谢幕演出.gd @@ -72,7 +72,7 @@ func start(): #### part3: 小蝉捂眼,瞎子、胖子声音 # 小蝉身体回正、捂眼 DialogueManager.show_dialogue_balloon(dialogue_c02, "c02_s11_谢幕交谈2") - get_tree().create_timer(5.0).timeout.connect(_hand_cover_eyes) + Util.timer(5.0, _hand_cover_eyes) await DialogueManager.dialogue_ended SceneManager.pop_debug_dialog_info("音效", "小蝉笑声/耳鸣") await create_tween().tween_interval(3.0).finished @@ -100,9 +100,9 @@ func _on_got_dialogue(line: DialogueLine): if speak: if first_speak: first_speak = false - await get_tree().create_timer(2.0).timeout + await Util.wait(2) else: - await get_tree().create_timer(1.0).timeout + await Util.wait(1) toggle_speak(speak) diff --git a/scene/ground/script/c02/追猫猪头怪.gd b/scene/ground/script/c02/追猫猪头怪.gd index 603ebd7f..2e7b01dd 100644 --- a/scene/ground/script/c02/追猫猪头怪.gd +++ b/scene/ground/script/c02/追猫猪头怪.gd @@ -92,7 +92,7 @@ func _on_ground_ready(): # 禁用传送过来的 portal 3s _disable_portal_a_few_seconds(portal_node) # 3 秒后传送 - get_tree().create_timer(1.0).timeout.connect(_do_transfer) + Util.timer(1.0, _do_transfer) if GlobalConfig.DEBUG: print("猪头怪 Transfer to: " + portal) else: @@ -108,7 +108,7 @@ func _on_footstep_timer_timeout() -> void: footstep_count += 1 if footstep_count % 2 == 0: # shake camera - camera.shake_camera(4.0, 5.0) + camera.shake_camera() if abs(signed_x_diff) > 250: if footstep_count % 3 == 0: sfx_footstep.play() @@ -177,7 +177,7 @@ func do_catch(front: bool): # 其次 catch_nearby 播放 猪头怪抓盒子猫后段 sprite2d.play("猪头怪抓盒子猫后段") # 被抓音效 - get_tree().create_timer(0.5).timeout.connect($"Sfx猫被抓".play) + Util.timer(0.5, $"Sfx猫被抓".play) # 呼吸声渐隐 $"Sfx喘气".easing_kill() SceneManager.pop_debug_dialog_info("音效", "抓取过程。 从捡小猫开始=" + str(front)) diff --git a/scene/little_game/书架/书架.gd b/scene/little_game/书架/书架.gd index 2a44064d..c1119540 100644 --- a/scene/little_game/书架/书架.gd +++ b/scene/little_game/书架/书架.gd @@ -249,7 +249,7 @@ func _success() -> void: func _on_target_book_pressed(): $"Shelf/生死簿".play("书架扶正") - await get_tree().create_timer(1.5).timeout + await Util.wait(1.5) $"生死簿".show() # 完成后释放信号 $"生死簿".finished.connect(_on_success_finished) diff --git a/scene/little_game/八音盒/八音盒.gd b/scene/little_game/八音盒/八音盒.gd index e5762e67..a62cf2a2 100644 --- a/scene/little_game/八音盒/八音盒.gd +++ b/scene/little_game/八音盒/八音盒.gd @@ -119,7 +119,7 @@ func _on_drawer_picked(_node): box_animation.play() drawer_btn.visible = false await box_animation.animation_finished - await get_tree().create_timer(1.0).timeout + await Util.wait(1) box_animation.visible = false box_broken.visible = false box_drawer.visible = true @@ -200,7 +200,7 @@ func _on_wheel_rotated(radiant: float) -> void: sfx_music.play() else: sfx_music.stream_paused = false - get_tree().create_timer(playing_step_sec).timeout.connect(_on_playing_step_finished) + Util.timer(playing_step_sec, _on_playing_step_finished) func _on_playing_step_finished(): @@ -211,7 +211,7 @@ func _on_playing_step_finished(): return if continue_playing: continue_playing = false - get_tree().create_timer(playing_step_sec).timeout.connect(_on_playing_step_finished) + Util.timer(playing_step_sec, _on_playing_step_finished) else: playing = false sfx_music.stream_paused = true @@ -226,7 +226,7 @@ func _checkout_auto_play(): # var audio_len = audio_auto.get_length() # 音效 9.5 秒时关闭盒子 var audio_len = 9.5 - get_tree().create_timer(audio_len).timeout.connect(_on_auto_play_finished) + Util.timer(audio_len, _on_auto_play_finished) func _on_auto_play_finished(): diff --git a/scene/little_game/八音盒/八音盒_old.gd b/scene/little_game/八音盒/八音盒_old.gd index f62136a8..859d8243 100644 --- a/scene/little_game/八音盒/八音盒_old.gd +++ b/scene/little_game/八音盒/八音盒_old.gd @@ -66,7 +66,7 @@ func _ready() -> void: # # test close shaking effect # ArchiveManager.archive.bayinhe_mode = "playing" # _chechout_mode(true) - # get_tree().create_timer(1.0).timeout.connect(_on_auto_play_finished) + # Util.timer(1.0, _on_auto_play_finished) func _on_visibility_changed() -> void: @@ -224,7 +224,7 @@ func _on_wheel_rotated(radiant: float) -> void: audio_player.play() else: audio_player.stream_paused = false - get_tree().create_timer(playing_step_sec).timeout.connect(_on_playing_step_finished) + Util.timer(playing_step_sec, _on_playing_step_finished) func _on_playing_step_finished(): @@ -235,7 +235,7 @@ func _on_playing_step_finished(): return if continue_playing: continue_playing = false - get_tree().create_timer(playing_step_sec).timeout.connect(_on_playing_step_finished) + Util.timer(playing_step_sec, _on_playing_step_finished) else: playing = false audio_player.stream_paused = true @@ -250,7 +250,7 @@ func _checkout_auto_play(): # var audio_len = audio_auto.get_length() # 音效 9.5 秒时关闭盒子 var audio_len = 9.5 - get_tree().create_timer(audio_len).timeout.connect(_on_auto_play_finished) + Util.timer(audio_len, _on_auto_play_finished) func _on_auto_play_finished(): diff --git a/scene/little_game/弹珠游戏/弹珠游戏.gd b/scene/little_game/弹珠游戏/弹珠游戏.gd index 39ca182b..c3cee8c2 100644 --- a/scene/little_game/弹珠游戏/弹珠游戏.gd +++ b/scene/little_game/弹珠游戏/弹珠游戏.gd @@ -245,13 +245,13 @@ func game_win() -> void: # 0:默认 1:寻找弹珠(老虎钳可以换弹珠) 2:给出弹珠 3:游戏结束 ArchiveManager.set_global_entry(&"c02_ball_game_stage", 3) %"Sfx结尾小孩跑".play() - CanvasUtil.shake_layer(self, 2.0) + Util.shake_layer(self, 2.0) # 弹珠雨 $BallsFalling.emitting = true pivot.visible = false DialogueManager.show_dialogue_balloon_scene(self, dialogue_c02, "c02_弹珠游戏4") await ball_dialogue_ended - await get_tree().create_timer(3.0).timeout + await Util.wait(3.0) exit.emit(true) @@ -303,15 +303,4 @@ func apply_dialogue_line() -> void: tween.tween_property(label, "modulate:a", 1.0, 0.5) tween.tween_interval(2.0) tween.tween_property(label, "modulate:a", 0.0, 0.5) - # # 因为版权问题,有些 mp3 文件打不开,所以使用 ogg 格式 - # var audio_path = "res://asset/audio/peiyin/ogg/%s.ogg" % translation_key - # if FileAccess.file_exists(audio_path): - # var stream = load(audio_path) - # audio_player.stream = stream - # audio_player.play() - # await audio_player.finished - # await get_tree().create_timer(1.0).timeout - # else: - # push_warning("No audio file found for " + translation_key) - # await get_tree().create_timer(3.0).timeout ball_dialogue_ended.emit() diff --git a/scene/little_game/拼凑信件.gd b/scene/little_game/拼凑信件.gd index e2358a9a..ba23f867 100644 --- a/scene/little_game/拼凑信件.gd +++ b/scene/little_game/拼凑信件.gd @@ -32,7 +32,7 @@ func _ready() -> void: func _enter_tree() -> void: SceneManager.pop_center_notification(tr("input_拼凑信件")) - await get_tree().create_timer(4.0).timeout + await Util.wait(4.0) SceneManager.pop_center_notification(tr("ui_press_q_to_exit")) func _setup() -> void: @@ -144,7 +144,7 @@ func _post_success(): SceneManager.enable_important_item("prop_院长的信") whole.visible = false # 1s 后退出 - await get_tree().create_timer(1.0).timeout + await Util.wait(1.0) if get_parent() != null: success.emit() get_parent().remove_child(self) diff --git a/scene/settings/settings.gd b/scene/settings/settings.gd index c4b9f9fa..31c4b8f2 100644 --- a/scene/settings/settings.gd +++ b/scene/settings/settings.gd @@ -76,9 +76,9 @@ func _ready(): # navigation return_btn.pressed.connect(_on_return_btn_pressed) return_btn.grab_focus() + SceneManager.toggle_pause_counter(true) # open $"Sfx打开".play() - SceneManager.toggle_pause_counter(true) func _on_master_bus_slider_value_changed(value: float) -> void: diff --git a/scene/ux/memory/clips/clip2.gd b/scene/ux/memory/clips/clip2.gd index bcdf2649..58571784 100644 --- a/scene/ux/memory/clips/clip2.gd +++ b/scene/ux/memory/clips/clip2.gd @@ -11,7 +11,7 @@ func run_clip(card_mode: bool): tween.tween_interval(5.0) tween.tween_property($"井", "modulate:a", 1.0, 5.0) if not card_mode: - await get_tree().create_timer(3.0).timeout + await Util.wait(3.0) # 增加配音 dialog_node = DialogueManager.show_dialogue_balloon(dialogue_res, "c02_s11_井边疯子对话") dialog_node.process_mode = Node.PROCESS_MODE_ALWAYS diff --git a/scene/ux/panel/ux_panel.gd b/scene/ux/panel/ux_panel.gd index 9c40a82d..0ad34a9a 100644 --- a/scene/ux/panel/ux_panel.gd +++ b/scene/ux/panel/ux_panel.gd @@ -12,10 +12,10 @@ func _ready() -> void: $SfxOpen.play() layer = GlobalConfig.CANVAS_LAYER_UX_PANEL SceneManager.toggle_pause_counter(true) - continue_btn.pressed.connect(quit) + continue_btn.pressed.connect(_continue) note_btn.pressed.connect(SceneManager.show_note) settings_btn.pressed.connect(SceneManager.show_settings) - main_menu_btn.pressed.connect(SceneManager.checkout_index_page) + main_menu_btn.pressed.connect(_index_menu) quit_btn.pressed.connect(_quit_game) func _quit_game() -> void: @@ -23,16 +23,22 @@ func _quit_game() -> void: ArchiveManager.notification(NOTIFICATION_WM_CLOSE_REQUEST) # 退出游戏过程隐藏界面 # 隐藏 panel - quit() + _continue() -func quit(): - $SfxOpen.global_play() +func _continue(): + $SfxClose.global_play() SceneManager.toggle_pause_counter(false) queue_free() +func _index_menu(): + SceneManager.checkout_index_page() + # 允许 ground loader 运行 transition + _continue() + + func _unhandled_input(event: InputEvent) -> void: # panel 界面接受所有输入事件 get_viewport().set_input_as_handled() if event.is_action_pressed("cancel") or event.is_action_pressed("escape"): - quit() + _continue() diff --git a/scene/ux/panel/ux_panel.tscn b/scene/ux/panel/ux_panel.tscn index f87e9c13..b02ad0f9 100644 --- a/scene/ux/panel/ux_panel.tscn +++ b/scene/ux/panel/ux_panel.tscn @@ -99,7 +99,7 @@ theme_override_fonts/font = ExtResource("4_mns6r") theme_override_font_sizes/font_size = 20 theme_override_styles/hover = SubResource("StyleBoxLine_v1oku") theme_override_styles/pressed = SubResource("StyleBoxLine_a3uyd") -text = "ux_panel_笔记" +text = "ux_panel_线索笔记" flat = true [node name="MarginContainer3" type="MarginContainer" parent="Bag"] diff --git a/scene/ux/tabs.gd b/scene/ux/tabs.gd index 3a9f8fd7..fa90d4c7 100644 --- a/scene/ux/tabs.gd +++ b/scene/ux/tabs.gd @@ -81,10 +81,23 @@ func _on_tab_memory_pressed(): root.quit() -func _exit_tree() -> void: - sfx_close.global_play() +var play_close_on_exit_tree = true -# func _unhandled_input(event: InputEvent) -> void: -# if event.is_action_pressed("memory") and current_type != "回忆": -# get_viewport().set_input_as_handled() -# SceneManager.show_memory() +func _exit_tree() -> void: + if play_close_on_exit_tree: + sfx_close.global_play() + + +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed("memory") and current_type != "回忆": + get_viewport().set_input_as_handled() + play_close_on_exit_tree = false + _on_tab_memory_pressed() + elif event.is_action_pressed("note") and current_type != "线索": + get_viewport().set_input_as_handled() + play_close_on_exit_tree = false + _on_tab_note_pressed() + elif event.is_action_pressed("bag") and current_type != "物品": + get_viewport().set_input_as_handled() + play_close_on_exit_tree = false + _on_tab_bag_pressed() diff --git a/util/canvas_util.gd b/util/canvas_util.gd deleted file mode 100644 index a2cd7ab1..00000000 --- a/util/canvas_util.gd +++ /dev/null @@ -1,14 +0,0 @@ -class_name CanvasUtil extends Object - - -static func shake_layer(layer: CanvasLayer, duration: float, delta := 2.0, fps := 20.0) -> void: - var tween = layer.create_tween() - # shake layer's offset - var origin_offset = layer.offset - var count = int(duration * fps) - var delta_t = 1.0 / fps - for i in range(count): - var offset = Vector2(randf_range(-delta, delta), randf_range(-delta, delta)) - tween.tween_property(layer, "offset", origin_offset + offset, delta_t) - # tween back to origin - tween.tween_property(layer, "offset", origin_offset, delta_t) \ No newline at end of file diff --git a/util/canvas_util.gd.uid b/util/canvas_util.gd.uid deleted file mode 100644 index 67b46eeb..00000000 --- a/util/canvas_util.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://l4egv2jc0vjb diff --git a/util/debug_label.gd b/util/debug_label.gd deleted file mode 100644 index c2b68da9..00000000 --- a/util/debug_label.gd +++ /dev/null @@ -1,22 +0,0 @@ -class_name DebugLabel extends Label - -@export var enabled := false: - set(value): - enabled = value - if enabled: - _display() - else: - _hide() - - -func _ready() -> void: - if not GlobalConfig.DEBUG: - return - - -func _hide(): - visible = false - - -func _display(): - pass diff --git a/util/debug_label.gd.uid b/util/debug_label.gd.uid deleted file mode 100644 index b2679654..00000000 --- a/util/debug_label.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://cgi8uhk7ii5o6 diff --git a/util/dialogue_util.gd b/util/dialogue_util.gd deleted file mode 100644 index bff3a6da..00000000 --- a/util/dialogue_util.gd +++ /dev/null @@ -1,30 +0,0 @@ -class_name DialogueUtil extends RefCounted - -static func concact_content_from_lines(lines:=[]): - if lines.is_empty(): - return "" - var content = "" - for i in range(len(lines) - 1): - var line = lines[i] as DialogueLine - content += TranslationServer.tr(line.translation_key) + "\n" - # last line without "\n" - content += TranslationServer.tr(lines[-1].translation_key) - return content - -static func get_lines(res: DialogueResource, title: String) -> Array: - var lines = [] - var current_line = await res.get_next_dialogue_line(title) - while current_line: - lines.append(current_line) - if current_line.next_id != "end": - current_line = await res.get_next_dialogue_line(current_line.next_id) - else: - break - return lines - -# pop os lines -static func generate_lines(content: String) -> Array: - var text = "~ title\n" + content + "\n=> END" - var res = DialogueManager.create_resource_from_text(text) - return await get_lines(res, "title") - diff --git a/util/dialogue_util.gd.uid b/util/dialogue_util.gd.uid deleted file mode 100644 index 5266ee96..00000000 --- a/util/dialogue_util.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://ckwvshyrj4vns diff --git a/util/util.gd b/util/util.gd new file mode 100644 index 00000000..658d03be --- /dev/null +++ b/util/util.gd @@ -0,0 +1,58 @@ +extends Node + + +#### Timer +func wait(duration: float) -> void: + await get_tree().create_timer(duration).timeout + + +func timer(duration: float, callable: Callable) -> SceneTreeTimer: + var t = get_tree().create_timer(duration, false) + t.timeout.connect(callable) + return t + + +#### Canvas +func shake_layer(layer: CanvasLayer, duration: float, delta := 2.0, fps := 20.0) -> void: + var tween = layer.create_tween() + # shake layer's offset + var origin_offset = layer.offset + var count = int(duration * fps) + var delta_t = 1.0 / fps + for i in range(count): + var offset = Vector2(randf_range(-delta, delta), randf_range(-delta, delta)) + tween.tween_property(layer, "offset", origin_offset + offset, delta_t) + # tween back to origin + tween.tween_property(layer, "offset", origin_offset, delta_t) + + +###### Dialogue +func concact_content_from_lines(lines := []): + if lines.is_empty(): + return "" + var content = "" + for i in range(len(lines) - 1): + var line = lines[i] as DialogueLine + content += TranslationServer.tr(line.translation_key) + "\n" + # last line without "\n" + content += TranslationServer.tr(lines[-1].translation_key) + return content + + +func get_lines(res: DialogueResource, title: String) -> Array: + var lines = [] + var current_line = await res.get_next_dialogue_line(title) + while current_line: + lines.append(current_line) + if current_line.next_id != "end": + current_line = await res.get_next_dialogue_line(current_line.next_id) + else: + break + return lines + + +# pop os lines +func generate_lines(content: String) -> Array: + var text = "~ title\n" + content + "\n=> END" + var res = DialogueManager.create_resource_from_text(text) + return await get_lines(res, "title") diff --git a/util/util.gd.uid b/util/util.gd.uid new file mode 100644 index 00000000..ee8a1871 --- /dev/null +++ b/util/util.gd.uid @@ -0,0 +1 @@ +uid://cqkbvu00n5ao8