diff --git a/README.md b/README.md index d196060e..f80dd1d8 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,52 @@ ProAnimatedSprite2D,增强 AnimatedSprite2D 的表现,在其基础上增加 - 正常游戏:Main -> GroundLoader -> Ground - 开发阶段:直接编辑 Ground +### Ground 说明 + +#### AnimationPlayer:每个 Ground 都有一个 AnimationPlayer,脚本继承自定义的 AnimationRoot + +主要功能说明: + +1. 正常的 AnimationPlayer 功能 +2. oneshot_animation 场景首次加载时播放的 animation + +主要方法与数据说明: + +1. _default_data() : 本场景的默认存档数据 +2. _on_ground_ready(): 在父节点 Ground 加载完成后回调 +3. set_data(property: StringName, value: Variant):用于设置需要存档的数据 +4. ground_archive:存档数据 + +#### Entity 说明 + +位置:res://scene/entity/ + +子目录说明: + +1. ambient:光照 +2. general:音效等 +3. partical:粒子效果 +4. ux:用户交互 + +主要类型说明: + +1. ambush:触发区域,触发后执行回调 + 1. 可以配置是否一次性 + 2. 可配置触发方式:enter, area_enter, interact + 3. 可在场景加载时触发 + 4. 触发效果有:播放对话(期间锁定玩家);播放动画;回调方法(AnimationPlayer 的方法,注意“_”开头的方法会被忽略) +2. inspectable:可在检阅窗口进行审视的物品,可以附加文案 +3. local_inspectable:运镜+检阅,无需检阅窗口 +4. note:显示文案 + 1. 显示方式:os(玩家头顶气泡),ballon(下方字幕,可播放配音) +5. npc +6. portal:传送门 + 1. 名称有: left(默认), right(默认), 1, 2, 3, ... + 2. 关键参数:targer_scene 与 target_portal(target_portal 为 none 时不启用) + 3. 三种模式:default(通道);opened(打开的门);locked(锁定的门);对应不同图标与操作音效 + 4. 锁定的门可以配置启用钥匙(prop_key),可在使用后自动消耗该钥匙 + + ## 存档结构 - 存档命名为:"save"+三位数字 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 117d3092..b900d931 100644 --- a/addons/property-inspector/pro_animation_sprite2d/pro_animated_sprite.gd +++ b/addons/property-inspector/pro_animation_sprite2d/pro_animated_sprite.gd @@ -18,7 +18,7 @@ class_name ProAnimatedSprite2D extends AnimatedSprite2D const ACTION_CONFIG = { "animation_intro": "", "intro_loop": 1, "animation_wait_time": 0.0, "animation_next": "" } - +# 参数 {duration} 目前无需求,暂且保留 const MOVE_CONFIG = {"animation": "", "velocity": Vector2.ZERO, "duration": 10000000.0} diff --git a/scene/entity/old/inspectable.gd b/scene/entity/inspectable.gd similarity index 100% rename from scene/entity/old/inspectable.gd rename to scene/entity/inspectable.gd diff --git a/scene/entity/old/inspectable.tscn b/scene/entity/inspectable.tscn similarity index 94% rename from scene/entity/old/inspectable.tscn rename to scene/entity/inspectable.tscn index 1af1881b..4e52da38 100644 --- a/scene/entity/old/inspectable.tscn +++ b/scene/entity/inspectable.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=7 format=3 uid="uid://wyj4qdjyn4ql"] -[ext_resource type="Script" path="res://scene/entity/old/inspectable.gd" id="1_0pc4s"] +[ext_resource type="Script" path="res://scene/entity/inspectable.gd" id="1_0pc4s"] [ext_resource type="PackedScene" uid="uid://c85t6stvytvjn" path="res://scene/entity/general/sfx.tscn" id="2_wrnix"] [ext_resource type="AudioStream" uid="uid://dky3j8lwcy5sk" path="res://asset/audio/sfx/ui/物品查看.mp3" id="3_kilnm"] [ext_resource type="Texture2D" uid="uid://bei1s1uucktso" path="res://asset/art/tool/neutral_point_light.webp" id="3_vbivp"] diff --git a/scene/ground/ground.gd b/scene/ground/ground.gd index 42f3b99b..4608e305 100644 --- a/scene/ground/ground.gd +++ b/scene/ground/ground.gd @@ -140,7 +140,7 @@ func play_footstep_sound() -> void: func move_player_to_portal(portal_name: String) -> void: var portal_node = get_node_or_null("DeployLayer/portal_" + portal_name) as Node2D - if portal_node: + if portal_node and player: player.global_position.x = portal_node.global_position.x if portal_name == "left": player.set_facing_direction(Vector2.RIGHT) diff --git a/scene/ground/ground_loader.gd b/scene/ground/ground_loader.gd index f889bc62..cf18cbbc 100644 --- a/scene/ground/ground_loader.gd +++ b/scene/ground/ground_loader.gd @@ -111,15 +111,16 @@ func _update_archive(): func _do_transition(scene_name: String): # SceneManager.freeze_player(0) + ground = get_node_or_null("Ground") as Ground2D if ground: - # 提前移除,防止命名冲突 - remove_child(ground) + # 防止命名冲突 + ground.name = "removed_ground" + call_deferred("remove_child", ground) ground.queue_free() - var ground_node = _load_ground_node(scene_name) # 先设置 ground,再添加到场景中 # 因为 ground 在 enter_tree 时会用到 SceneManager 的方法 # 其中间接用到了 GroundLoader 的 ground - ground = ground_node + ground = _load_ground_node(scene_name) _add_ground() # 预先加载邻居场景 _post_transition() @@ -128,8 +129,8 @@ func _do_transition(scene_name: String): func _add_ground(): - ground.name = "Ground" add_child(ground) + ground.name = "Ground" if not Engine.is_editor_hint(): # move player to portal ground.move_player_to_portal(entrance_portal) diff --git a/scene/ground/scene/c01/s05_animation.gd b/scene/ground/scene/c01/s05_animation.gd index 15f3c48f..f736d6da 100644 --- a/scene/ground/scene/c01/s05_animation.gd +++ b/scene/ground/scene/c01/s05_animation.gd @@ -6,7 +6,7 @@ var frame: Note2D var paper: Interactable2D var right_door: Portal2D var piano: Interactable2D - +var bed_reading: AnimatedSprite2D # 覆盖该方法 func _default_data() -> Dictionary: @@ -31,6 +31,8 @@ func _on_ground_ready() -> void: paper = $"../DeployLayer/oneshot纸片" right_door = $"../DeployLayer/portal_right" piano = $"../DeployLayer/钢琴" + bed_reading = $"../DeployLayer/小小蝶看书" + bed_reading.frame_changed.connect(_on_bed_reading_frame_changed) # 画框是否已经正位 data.frame_relocated = ambush.played and ambush.one_shot # 禁用鸡毛掸子 @@ -66,6 +68,11 @@ func _on_ground_ready() -> void: piano.interacted.connect(_on_piano_interacted) +func _on_bed_reading_frame_changed(): + if bed_reading.animation == "c01_小小蝶_床上看书" and bed_reading.frame == 10: + # 播放结束,0.5s 后释放角色 + get_tree().create_timer(0.5).timeout.connect(SceneManager.release_player) + func _on_note_read(): frame.enabled = false diff --git a/scene/ground/scene/c01/s05_院长房间.tscn b/scene/ground/scene/c01/s05_院长房间.tscn index 549d1777..f46ed6ae 100644 --- a/scene/ground/scene/c01/s05_院长房间.tscn +++ b/scene/ground/scene/c01/s05_院长房间.tscn @@ -235,7 +235,7 @@ tracks/16/keys = { [sub_resource type="Animation" id="Animation_7k2c8"] resource_name = "intro" -length = 7.5 +length = 7.0 capture_included = true tracks/0/type = "value" tracks/0/imported = false @@ -307,7 +307,7 @@ tracks/5/keys = { "times": PackedFloat32Array(0), "transitions": PackedFloat32Array(1), "values": [{ -"args": [7.0, -1, false], +"args": [0.0, -1, false], "method": &"freeze_player" }] } diff --git a/scene/ground/scene/c01/s06_animation.gd b/scene/ground/scene/c01/s06_animation.gd index 6c5f04ea..823643e3 100644 --- a/scene/ground/scene/c01/s06_animation.gd +++ b/scene/ground/scene/c01/s06_animation.gd @@ -92,9 +92,7 @@ func _game_counting_down(_res = null): # 重置镜头 SceneManager.focus_player_and_reset_zoom() DialogueManager.show_dialogue_balloon( - dialogue_c01, - "c01_s06_猫鼠游戏", - [GlobalConfig.DIALOG_IGNORE_INPUT] + dialogue_c01, "c01_s06_猫鼠游戏", [GlobalConfig.DIALOG_IGNORE_INPUT] ) # 禁止玩家向左移动,同时可以使右侧腾出空间,玩家可以继续向右移动 var player = SceneManager.get_player() as MainPlayer @@ -230,19 +228,24 @@ func _post_catch(): func transport_player_to_next_scene(win: bool): - SceneManager.get_shading_layer().tween_fog( - ShadingLayer.FOG_FRAME_MAX, - ShadingLayer.FOG_COLOR_DARK_GRAY, - ShadingLayer.FOG_OFFSET_DEFAULT, - 1.0, - true - ) - get_tree().create_timer(0.7).timeout.connect(_show_next_scene) if win: - SceneManager.pop_debug_dialog_info("音效", "猫鼠游戏胜利,传送下一场景") + _show_next_scene(true) + SceneManager.pop_debug_dialog_info("音效", "猫鼠游戏胜利,无缝转场") else: + SceneManager.get_shading_layer().tween_fog( + ShadingLayer.FOG_FRAME_MAX, + ShadingLayer.FOG_COLOR_BLACK, + ShadingLayer.FOG_OFFSET_DEFAULT, + 1.0, + true + ) + get_tree().create_timer(0.7).timeout.connect(_show_next_scene.bind(false)) SceneManager.pop_debug_dialog_info("音效", "猫鼠游戏失败,传送下一场景") -func _show_next_scene(): - SceneManager.get_ground_loader().transition_to_scene("c01_s07", "left", false) +func _show_next_scene(seamless: bool): + if seamless: + #TODO 无缝转场过程细化 + SceneManager.get_ground_loader().transition_to_scene("c01_s07", "left", true) + else: + SceneManager.get_ground_loader().transition_to_scene("c01_s07", "left", false) diff --git a/scene/ground/scene/c02/s02_走道.tscn b/scene/ground/scene/c02/s02_走道.tscn index a2e8a07d..82d88307 100644 --- a/scene/ground/scene/c02/s02_走道.tscn +++ b/scene/ground/scene/c02/s02_走道.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=22 format=3 uid="uid://brck77w81fhvc"] +[gd_scene load_steps=24 format=3 uid="uid://brck77w81fhvc"] [ext_resource type="PackedScene" uid="uid://dayyx4jerj7io" path="res://scene/ground/ground.tscn" id="1_wrr6r"] [ext_resource type="Script" path="res://scene/ground/scene/c02/s02_animation.gd" id="2_5p8ev"] @@ -16,6 +16,8 @@ [ext_resource type="Texture2D" uid="uid://c4c7t2lttcf0a" path="res://asset/art/临时草稿/煤油灯.png" id="14_db4pu"] [ext_resource type="Texture2D" uid="uid://doqtpiaf1weqc" path="res://asset/art/临时草稿/煤油灯_点燃.png" id="15_5rpxj"] [ext_resource type="Texture2D" uid="uid://b7gyapghy3tsy" path="res://asset/art/neutral_point_light.png" id="16_asses"] +[ext_resource type="AudioStream" uid="uid://dvwiuesd0qi1l" path="res://asset/audio/sfx/ui/门牌互动音.wav" id="16_d08tt"] +[ext_resource type="AudioStream" uid="uid://dky3j8lwcy5sk" path="res://asset/audio/sfx/ui/物品查看.mp3" id="17_lqks2"] [sub_resource type="Animation" id="Animation_abofy"] resource_name = "oneshot_天冷" @@ -159,9 +161,11 @@ interacted_texture = ExtResource("15_5rpxj") prop_key = "prop_火柴" [node name="SfxInvalid" parent="Ground/DeployLayer/Interactable煤油灯" index="0"] +stream = ExtResource("16_d08tt") file = "门牌互动音.wav" [node name="SfxSuccess" parent="Ground/DeployLayer/Interactable煤油灯" index="1"] +stream = ExtResource("17_lqks2") file = "物品查看.mp3" [node name="CollisionShape2D" parent="Ground/DeployLayer/Interactable煤油灯/Area2D" index="0"] diff --git a/scene/ground/scene/c02/s05_1012外间现实版.tscn b/scene/ground/scene/c02/s05_1012外间现实版.tscn index 16aa4357..94d1ae65 100644 --- a/scene/ground/scene/c02/s05_1012外间现实版.tscn +++ b/scene/ground/scene/c02/s05_1012外间现实版.tscn @@ -5,7 +5,7 @@ [ext_resource type="Texture2D" uid="uid://cl8no405v4hsk" path="res://asset/art/scene/c02/s05_1012外间现实版/bg_1012外间.png" id="3_8jr2p"] [ext_resource type="Texture2D" uid="uid://d04bppjl5h3vo" path="res://asset/art/scene/c02/s05_1012外间现实版/fg_1012外间.png" id="4_quka7"] [ext_resource type="Texture2D" uid="uid://bykkjm7wker46" path="res://asset/art/scene/c02/s05_1012外间现实版/ux_公寓告示1.png" id="5_8vm4y"] -[ext_resource type="PackedScene" uid="uid://wyj4qdjyn4ql" path="res://scene/entity/old/inspectable.tscn" id="6_stoff"] +[ext_resource type="PackedScene" uid="uid://wyj4qdjyn4ql" path="res://scene/entity/inspectable.tscn" id="6_stoff"] [node name="S05" type="Node2D"] diff --git a/scene/player/main_player.gd b/scene/player/main_player.gd index 91b7a5f1..97aebe7b 100644 --- a/scene/player/main_player.gd +++ b/scene/player/main_player.gd @@ -169,7 +169,7 @@ func _get_speed(direction: Vector2) -> Vector2: func _physics_process(_delta: float) -> void: - if action_locked or action_freezed or Engine.is_editor_hint(): + if action_locked or action_freezed or Engine.is_editor_hint() or not is_visible_in_tree(): velocity = Vector2.ZERO return var x_direction := Input.get_axis("left", "right") diff --git a/scene/shading/shading_layer.tscn b/scene/shading/shading_layer.tscn index 3b83b770..75cf742b 100644 --- a/scene/shading/shading_layer.tscn +++ b/scene/shading/shading_layer.tscn @@ -85,9 +85,6 @@ animations = [{ "texture": ExtResource("12_k6v1x") }, { "duration": 1.0, -"texture": ExtResource("13_kjyug") -}, { -"duration": 1.0, "texture": ExtResource("14_yy2gj") }, { "duration": 1.0, @@ -97,6 +94,9 @@ animations = [{ "texture": ExtResource("16_86yqr") }, { "duration": 1.0, +"texture": ExtResource("13_kjyug") +}, { +"duration": 1.0, "texture": ExtResource("17_5psqe") }, { "duration": 1.0,