自动枯萎的花朵 & 拼凑信件碎片

This commit is contained in:
cakipaul 2025-01-27 23:13:37 +08:00
parent 79a7c0ff84
commit 14ce06e02a
40 changed files with 938 additions and 142 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cuyejl2kbp7y4"
path="res://.godot/imported/信件碎片.png-c35bdb7240fb280003e7b3bca88b316c.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://asset/art/little_game/拼凑信件/信件碎片.png"
dest_files=["res://.godot/imported/信件碎片.png-c35bdb7240fb280003e7b3bca88b316c.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dnjrdh1qnpony"
path="res://.godot/imported/完整信件.png-cfd076a390551cbdbbaeee723f1d98cc.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://asset/art/little_game/拼凑信件/完整信件.png"
dest_files=["res://.godot/imported/完整信件.png-cfd076a390551cbdbbaeee723f1d98cc.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://crdphnglw5tv8"
path="res://.godot/imported/花.png-253551d934c1db4768dd5bcf7b145c5b.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://asset/art/little_game/自动枯萎的花/花.png"
dest_files=["res://.godot/imported/花.png-253551d934c1db4768dd5bcf7b145c5b.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

View File

@ -0,0 +1,11 @@
~ this_is_a_node_title
Nathan: [[Hi|Hello|Howdy]], this is some dialogue.
Nathan: Here are some choices.
- First one
Nathan: You picked the first one.
- Second one
Nathan: You picked the second one.
- Start again => this_is_a_node_title
- End the conversation => END
Nathan: For more information see the online documentation.
=> END

View File

@ -0,0 +1,15 @@
[remap]
importer="dialogue_manager_compiler_13"
type="Resource"
uid="uid://b66v5hsf3tdox"
path="res://.godot/imported/c03.dialogue-c0384ecbb52edd7836345e985eb72b38.tres"
[deps]
source_file="res://asset/dialogue/c03.dialogue"
dest_files=["res://.godot/imported/c03.dialogue-c0384ecbb52edd7836345e985eb72b38.tres"]
[params]
defaults=true

View File

@ -0,0 +1,11 @@
~ this_is_a_node_title
Nathan: [[Hi|Hello|Howdy]], this is some dialogue.
Nathan: Here are some choices.
- First one
Nathan: You picked the first one.
- Second one
Nathan: You picked the second one.
- Start again => this_is_a_node_title
- End the conversation => END
Nathan: For more information see the online documentation.
=> END

View File

@ -0,0 +1,15 @@
[remap]
importer="dialogue_manager_compiler_13"
type="Resource"
uid="uid://cthsrdkrseijb"
path="res://.godot/imported/c04.dialogue-c094c22b3c3a3667c042516fadd04a57.tres"
[deps]
source_file="res://asset/dialogue/c04.dialogue"
dest_files=["res://.godot/imported/c04.dialogue-c094c22b3c3a3667c042516fadd04a57.tres"]
[params]
defaults=true

View File

@ -0,0 +1,11 @@
~ this_is_a_node_title
Nathan: [[Hi|Hello|Howdy]], this is some dialogue.
Nathan: Here are some choices.
- First one
Nathan: You picked the first one.
- Second one
Nathan: You picked the second one.
- Start again => this_is_a_node_title
- End the conversation => END
Nathan: For more information see the online documentation.
=> END

View File

@ -0,0 +1,15 @@
[remap]
importer="dialogue_manager_compiler_13"
type="Resource"
uid="uid://c2em7wb623pd7"
path="res://.godot/imported/c05.dialogue-de8e66d65fcfff540deb26ce3c92b0a4.tres"
[deps]
source_file="res://asset/dialogue/c05.dialogue"
dest_files=["res://.godot/imported/c05.dialogue-de8e66d65fcfff540deb26ce3c92b0a4.tres"]
[params]
defaults=true

View File

@ -5,39 +5,44 @@ shader_type canvas_item;
uniform sampler2D perlin_noise: repeat_enable; uniform sampler2D perlin_noise: repeat_enable;
uniform sampler2D cell_noise: repeat_enable; uniform sampler2D cell_noise: repeat_enable;
#define pow2(x) (x * x) //#define pow2(x) (x * x)
//#define iResolution 1.0/SCREEN_PIXEL_SIZE ////#define iResolution 1.0/SCREEN_PIXEL_SIZE
const int samples = 35; //const int samples = 16;
const float sigma = float(samples) * 0.25; //const int half_samples = 8;
//const float sigma = float(samples) * 0.25;
float gaussian(vec2 i) { //float gaussian(vec2 i) {
return 1.0 / (2.0 * PI * pow2(sigma)) * exp(-((pow2(i.x) + pow2(i.y)) / (2.0 * pow2(sigma)))); //return 1.0 / (2.0 * PI * pow2(sigma)) * exp(-((pow2(i.x) + pow2(i.y)) / (2.0 * pow2(sigma))));
} //}
//
vec3 blur(sampler2D sp, vec2 uv, vec2 scale) { //float blur(sampler2D sp, vec2 uv, vec2 scale) {
vec3 col = vec3(0.0); //float col = 0.0;
float accum = 0.0; //float accum = 0.0;
float weight; //float weight = 1.0;
vec2 offset; //vec2 offset;
for (int x = - samples >> 1 ; x < samples >> 1; ++x) { //for (int x = - half_samples ; x < half_samples; ++x) {
for (int y = -samples >> 1; y < samples >> 1; ++y) { //for (int y = - half_samples; y < half_samples; ++y) {
offset = vec2(float(x), float(y)); //offset = vec2(float(x), float(y));
weight = gaussian(offset); ////weight = gaussian(offset);
col += texture(sp, uv + scale * offset).rgb * weight; //col += texture(sp, uv + scale * offset).r * weight;
accum += weight; //accum += weight;
} //}
} //}
return col / accum; //return col / accum;
} //}
void fragment() { void fragment() {
vec2 uv1 = vec2(UV.x + TIME * .02, UV.y + TIME * .005); vec2 uv1 = vec2(UV.x + TIME * .02, UV.y + TIME * .005);
vec2 uv2 = vec2(UV.x + TIME * .03, UV.y + TIME * .005); vec2 uv2 = vec2(UV.x + TIME * .03, UV.y + TIME * .005);
float noise1 = blur(perlin_noise, uv1, SCREEN_PIXEL_SIZE).r;
float noise2 = blur(cell_noise, uv2, SCREEN_PIXEL_SIZE).r;
float noise = smoothstep(noise1 * noise2 * 1.0, .0, .15); //float noise1 = blur(perlin_noise, uv1, SCREEN_PIXEL_SIZE);
//float noise2 = blur(cell_noise, uv2, SCREEN_PIXEL_SIZE);
float noise1 = texture(perlin_noise, uv1).r;
float noise2 = texture(cell_noise, uv2).r;
//noise1 = 1.0;
//noise2 = 1.0;
float noise = smoothstep(noise1 * noise2, .0, .15);
COLOR.a *= noise; COLOR.a *= noise;
} }

View File

@ -1,6 +1,28 @@
[gd_resource type="ShaderMaterial" load_steps=2 format=3 uid="uid://7wllwmfkfvsb"] [gd_resource type="ShaderMaterial" load_steps=6 format=3 uid="uid://7wllwmfkfvsb"]
[ext_resource type="Shader" path="res://asset/shader/fog.gdshader" id="1_0axjk"] [ext_resource type="Shader" path="res://asset/shader/cloud.gdshader" id="1_53tbo"]
[sub_resource type="FastNoiseLite" id="FastNoiseLite_b87im"]
noise_type = 2
fractal_type = 2
fractal_octaves = 3
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_phjgp"]
invert = true
seamless = true
seamless_blend_skirt = 0.45
noise = SubResource("FastNoiseLite_b87im")
[sub_resource type="FastNoiseLite" id="FastNoiseLite_wt8y1"]
noise_type = 3
frequency = 0.005
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_km1py"]
seamless = true
seamless_blend_skirt = 0.3
noise = SubResource("FastNoiseLite_wt8y1")
[resource] [resource]
shader = ExtResource("1_0axjk") shader = ExtResource("1_53tbo")
shader_parameter/perlin_noise = SubResource("NoiseTexture2D_km1py")
shader_parameter/cell_noise = SubResource("NoiseTexture2D_phjgp")

View File

@ -14,6 +14,7 @@ const CANVAS_LAYER_SETTINGS = 20
const CANVAS_LAYER_BAG = 12 const CANVAS_LAYER_BAG = 12
const CANVAS_LAYER_GROUND_MASK = 11 const CANVAS_LAYER_GROUND_MASK = 11
const CANVAS_LAYER_SHADING = 10 const CANVAS_LAYER_SHADING = 10
const LAYER_LITTLE_GAME = 5
const CANVAS_LAYER_FG = 2 const CANVAS_LAYER_FG = 2
const CANVAS_LAYER_HD_ENTITY = 1 const CANVAS_LAYER_HD_ENTITY = 1

View File

@ -50,7 +50,7 @@ func focus_player_and_reset_zoom(duration := 1.2) -> void:
var marker = get_camera_marker() var marker = get_camera_marker()
if marker: if marker:
# marker.force_offset = Vector2.ZERO # marker.force_offset = Vector2.ZERO
marker.tween_zoom(1.0, duration, true) marker.tween_zoom(1.0, duration)
marker.focus_node(get_player()) marker.focus_node(get_player())

View File

@ -169,7 +169,7 @@ bag={
[internationalization] [internationalization]
locale/translations=PackedStringArray("res://asset/dialogue/c01.en.translation", "res://asset/dialogue/c02.en.translation", "res://asset/dialogue/item_description.en.translation", "res://asset/dialogue/names.en.translation", "res://asset/dialogue/inspect_content.en.translation", "res://asset/dialogue/npc.en.translation", "res://asset/dialogue/c01.zh_CN.translation", "res://asset/dialogue/c02.zh_CN.translation", "res://asset/dialogue/inspect_content.zh_CN.translation", "res://asset/dialogue/item_description.zh_CN.translation", "res://asset/dialogue/names.zh_CN.translation", "res://asset/dialogue/npc.zh_CN.translation") locale/translations=PackedStringArray("res://asset/dialogue/c01.en.translation", "res://asset/dialogue/c02.en.translation", "res://asset/dialogue/item_description.en.translation", "res://asset/dialogue/names.en.translation", "res://asset/dialogue/inspect_content.en.translation", "res://asset/dialogue/npc.en.translation", "res://asset/dialogue/c01.zh_CN.translation", "res://asset/dialogue/c02.zh_CN.translation", "res://asset/dialogue/inspect_content.zh_CN.translation", "res://asset/dialogue/item_description.zh_CN.translation", "res://asset/dialogue/names.zh_CN.translation", "res://asset/dialogue/npc.zh_CN.translation")
locale/translations_pot_files=PackedStringArray("res://asset/dialogue/item_description.dialogue", "res://asset/dialogue/c01.dialogue", "res://asset/dialogue/c02.dialogue", "res://asset/dialogue/inspect_content.dialogue", "res://asset/dialogue/npc.dialogue") locale/translations_pot_files=PackedStringArray("res://asset/dialogue/item_description.dialogue", "res://asset/dialogue/c01.dialogue", "res://asset/dialogue/c02.dialogue", "res://asset/dialogue/inspect_content.dialogue", "res://asset/dialogue/npc.dialogue", "res://asset/dialogue/c03.dialogue", "res://asset/dialogue/c04.dialogue", "res://asset/dialogue/c05.dialogue")
locale/test="zh-Hans" locale/test="zh-Hans"
locale/fallback="zh" locale/fallback="zh"

View File

@ -20,7 +20,7 @@ signal triggered
@export var freeze_time := 5.0 @export var freeze_time := 5.0
var hook_animation = "" var hook_animation = ""
@export var lock_player_on_playing_dialogue = true @export var lock_player_on_playing_dialogue = true
@export_enum("c01", "c02") var hook_dialogue_res = "c01": @export_enum("c01", "c02", "c03", "c04", "c05") var hook_dialogue_res = "c01":
set(val): set(val):
hook_dialogue_res = val hook_dialogue_res = val
match val: match val:
@ -28,13 +28,22 @@ var hook_animation = ""
dialogue_res = dialogue_c01 dialogue_res = dialogue_c01
"c02": "c02":
dialogue_res = dialogue_c02 dialogue_res = dialogue_c02
"c03":
dialogue_res = dialogue_c03
"c04":
dialogue_res = dialogue_c04
"c05":
dialogue_res = dialogue_c05
if is_node_ready() and Engine.is_editor_hint(): if is_node_ready() and Engine.is_editor_hint():
notify_property_list_changed() notify_property_list_changed()
var hook_dialogue_title = "" var hook_dialogue_title := ""
var hook_method = "" var hook_method := ""
var dialogue_c01 = preload("res://asset/dialogue/c01.dialogue") var dialogue_c01 = preload("res://asset/dialogue/c01.dialogue")
var dialogue_c02 = preload("res://asset/dialogue/c02.dialogue") var dialogue_c02 = preload("res://asset/dialogue/c02.dialogue")
var dialogue_c03 = preload("res://asset/dialogue/c03.dialogue")
var dialogue_c04 = preload("res://asset/dialogue/c04.dialogue")
var dialogue_c05 = preload("res://asset/dialogue/c05.dialogue")
var dialogue_res = dialogue_c01 var dialogue_res = dialogue_c01
var played_time := 0.0 var played_time := 0.0
@ -128,6 +137,7 @@ func _do_trigger():
return return
played_time = time played_time = time
played = true played = true
trigger_mutex.unlock()
# hook_animation # hook_animation
if hook_animation: if hook_animation:
var animation_player = _get_animation_player() var animation_player = _get_animation_player()
@ -146,7 +156,6 @@ func _do_trigger():
triggered.emit() triggered.emit()
if GlobalConfig.DEBUG: if GlobalConfig.DEBUG:
print("ambush triggered! name=", name) print("ambush triggered! name=", name)
trigger_mutex.unlock()
_check_sign_display() _check_sign_display()

View File

@ -24,6 +24,7 @@ func _reload_sfx():
if not Engine.is_editor_hint(): if not Engine.is_editor_hint():
return return
var path = sfx_root_path + dir + "/" + file var path = sfx_root_path + dir + "/" + file
print("path=", path)
if file and dir and FileAccess.file_exists(path): if file and dir and FileAccess.file_exists(path):
sfx = load(sfx_root_path + dir + "/" + file) as AudioStream sfx = load(sfx_root_path + dir + "/" + file) as AudioStream
else: else:

View File

@ -12,7 +12,7 @@ enum { STATUS_NORAML, STATUS_TRANSITIONING, STATUS_INSPECTING_COVER, STATUS_INSP
@export var entity_name: String = "" @export var entity_name: String = ""
@export var texture_cover: Texture2D @export var texture_cover: Texture2D
@export_enum("none", "c01", "c02", "c03", "c04", "c05", "c06") var editor_filter := "none": @export_enum("none", "c01", "c02", "c03", "c04", "c05") var editor_filter := "none":
set(val): set(val):
editor_filter = val editor_filter = val
if is_node_ready() and Engine.is_editor_hint(): if is_node_ready() and Engine.is_editor_hint():

View File

@ -9,7 +9,7 @@ signal read_note
if is_node_ready(): if is_node_ready():
sign_mark.enabled = val sign_mark.enabled = val
@export_enum("os", "ballon") var mode = "os" @export_enum("os", "ballon") var mode = "os"
@export_enum("items", "c01", "c02", "c03", "c04", "c05", "c06") var dialogue := "items": @export_enum("items", "c01", "c02", "c03", "c04", "c05") var dialogue := "items":
set(val): set(val):
dialogue = val dialogue = val
match dialogue: match dialogue:
@ -19,10 +19,16 @@ signal read_note
dialogue_res = dialogue_c01 dialogue_res = dialogue_c01
"c02": "c02":
dialogue_res = dialogue_c02 dialogue_res = dialogue_c02
"c03":
dialogue_res = dialogue_c03
"c04":
dialogue_res = dialogue_c04
"c05":
dialogue_res = dialogue_c05
if is_node_ready() and Engine.is_editor_hint(): if is_node_ready() and Engine.is_editor_hint():
notify_property_list_changed() notify_property_list_changed()
var note_key := "" var note_key := ""
@export_enum("none", "notes", "c01", "c02", "c03", "c04", "c05", "c06") var title_filter := "none": @export_enum("none", "notes", "c01", "c02", "c03", "c04", "c05") var title_filter := "none":
set(val): set(val):
title_filter = val title_filter = val
if is_node_ready() and Engine.is_editor_hint(): if is_node_ready() and Engine.is_editor_hint():
@ -34,7 +40,9 @@ var note_key := ""
var dialogue_items = preload("res://asset/dialogue/item_description.dialogue") var dialogue_items = preload("res://asset/dialogue/item_description.dialogue")
var dialogue_c01 = preload("res://asset/dialogue/c01.dialogue") var dialogue_c01 = preload("res://asset/dialogue/c01.dialogue")
var dialogue_c02 = preload("res://asset/dialogue/c02.dialogue") var dialogue_c02 = preload("res://asset/dialogue/c02.dialogue")
var dialogue_c03 = preload("res://asset/dialogue/c03.dialogue")
var dialogue_c04 = preload("res://asset/dialogue/c04.dialogue")
var dialogue_c05 = preload("res://asset/dialogue/c05.dialogue")
var dialogue_res = dialogue_items var dialogue_res = dialogue_items
var interacting = false var interacting = false

View File

@ -5,7 +5,6 @@ class_name CameraFocusMarker extends Camera2D
@export_group("Status") @export_group("Status")
@export var lock_horizontal = true @export var lock_horizontal = true
@export_group("Config") @export_group("Config")
@export var speed := 5.0
@export var half_screen_size := Vector2(564, 240) / 2.0 @export var half_screen_size := Vector2(564, 240) / 2.0
@export var shaded_height := 38 @export var shaded_height := 38
@export_group("Shake", "shake_") @export_group("Shake", "shake_")
@ -18,13 +17,14 @@ class_name CameraFocusMarker extends Camera2D
# @export var limit_top := 0 # @export var limit_top := 0
# @export var limit_bottom := 316.0 # @export var limit_bottom := 316.0
@export var zoom_ratio := 1.0 @export var zoom_ratio := 1.0
var speed := 5.0
var _tweeked_position := Vector2.ZERO var _tweeked_position := Vector2.ZERO
var zoom_tween: Tween var zoom_tween: Tween
var zooming_and_focus_start_position: Vector2 # var zooming_and_focus_start_position: Vector2
# 0 to 1 # # 0 to 1
var zooming_and_focus_progress := 1.0 # var zooming_and_focus_progress := 1.0
func _ready() -> void: func _ready() -> void:
@ -60,18 +60,19 @@ func _physics_process(delta: float) -> void:
# set camera's position # set camera's position
var target_position = focusing_node.global_position + _tweeked_position + force_offset var target_position = focusing_node.global_position + _tweeked_position + force_offset
if focusing_node is MainPlayer: if focusing_node is MainPlayer:
# player 的焦点在脚底,所以需要加上 player 的高度 # player 的焦点在脚底,所以需要偏移 player 的高度。注意 y 轴是向下的,所以是减去 player 的高度
target_position.y -= focusing_node.current_animation_config.os_height * 0.7 target_position.y -= focusing_node.current_animation_config.os_height * 0.7
# 如果有 zooming_and_focus_progress, 将其位置加入计算 # # 如果有 zooming_and_focus_progress, 将其位置加入计算
if zooming_and_focus_progress < 1.0: # if zooming_and_focus_progress < 1.0:
target_position.x = lerpf( # target_position.x = lerpf(
zooming_and_focus_start_position.x, target_position.x, zooming_and_focus_progress # zooming_and_focus_start_position.x, target_position.x, zooming_and_focus_progress
) # )
target_position.y = lerpf( # target_position.y = lerpf(
zooming_and_focus_start_position.y, target_position.y, zooming_and_focus_progress # zooming_and_focus_start_position.y, target_position.y, zooming_and_focus_progress
) # )
# easing with speed # easing with speed
var new_position = global_position + (target_position - global_position) * speed * delta var new_position = lerp(global_position, target_position, speed * delta)
# var new_position = global_position + (target_position - global_position) * speed * delta
# clamp the position # clamp the position
var margin = half_screen_size / zoom_ratio var margin = half_screen_size / zoom_ratio
margin.y += shaded_height margin.y += shaded_height
@ -81,30 +82,31 @@ func _physics_process(delta: float) -> void:
zoom = Vector2(zoom_ratio, zoom_ratio) zoom = Vector2(zoom_ratio, zoom_ratio)
func tween_zoom(ratio: float, duration := 1.5, refocus := false): func tween_zoom(ratio: float, duration := 1.5):
if zoom_tween and zoom_tween.is_running(): if zoom_tween and zoom_tween.is_running():
zoom_tween.kill() zoom_tween.kill()
zoom_tween = create_tween() zoom_tween = create_tween()
( (
zoom_tween zoom_tween
. tween_property(self, "zoom_ratio", ratio, duration) . tween_property(self, "zoom_ratio", ratio, duration)
. set_trans(Tween.TRANS_CUBIC) . set_trans(Tween.TRANS_SINE)
. set_ease(Tween.EASE_IN_OUT) . set_ease(Tween.EASE_IN_OUT)
) )
if refocus: # if refocus:
zooming_and_focus_start_position = global_position # zooming_and_focus_start_position = global_position
( # (
zoom_tween # zoom_tween
. parallel() # . parallel()
. tween_property(self, "zooming_and_focus_progress", 1.0, duration) # . tween_property(self, "zooming_and_focus_progress", 1.0, duration)
. from(0.0) # . from(0.0)
. set_trans(Tween.TRANS_LINEAR) # . set_trans(Tween.TRANS_SINE)
. set_ease(Tween.EASE_IN_OUT) # . set_ease(Tween.EASE_IN_OUT)
) # )
func focus_node(node: Node2D) -> void: func focus_node(node: Node2D) -> void:
focusing_node = node focusing_node = node
# zooming_and_focus_start_position = global_position
# var exited := false # var exited := false
# var exit_position: Vector2 # var exit_position: Vector2

View File

@ -16,10 +16,11 @@ var default_portal := "left"
player_y = val player_y = val
if is_node_ready(): if is_node_ready():
_reset_player_y() _reset_player_y()
@export var reset_player_y := false: @export var replace_player_to_portal := false:
set(val): set(val):
reset_player_y = false replace_player_to_portal = false
if is_node_ready(): if is_node_ready():
move_player_to_portal(default_portal)
_reset_player_y() _reset_player_y()
@export_group("Sound") @export_group("Sound")
@export_enum("none", "ghost", "walking", "running", "crawling", "concrete") @export_enum("none", "ghost", "walking", "running", "crawling", "concrete")

View File

@ -5,6 +5,9 @@ signal oneshot_animation_finished
# 在继承 AnimationRoot 的各场景内的脚本中,可以直接调用 DialogueResource # 在继承 AnimationRoot 的各场景内的脚本中,可以直接调用 DialogueResource
var dialogue_c01 := preload("res://asset/dialogue/c01.dialogue") as DialogueResource var dialogue_c01 := preload("res://asset/dialogue/c01.dialogue") as DialogueResource
var dialogue_c02 := preload("res://asset/dialogue/c02.dialogue") as DialogueResource var dialogue_c02 := preload("res://asset/dialogue/c02.dialogue") as DialogueResource
var dialogue_c03 := preload("res://asset/dialogue/c03.dialogue") as DialogueResource
var dialogue_c04 := preload("res://asset/dialogue/c04.dialogue") as DialogueResource
var dialogue_c05 := preload("res://asset/dialogue/c05.dialogue") as DialogueResource
@export var data = { @export var data = {
# 首次进入场景时触发 # 首次进入场景时触发
@ -22,13 +25,13 @@ func _default_data() -> Dictionary:
func _ready() -> void: func _ready() -> void:
data.merge(_default_data(), true)
if Engine.is_editor_hint(): if Engine.is_editor_hint():
# notify_property_list_changed() # notify_property_list_changed()
# 更新 oneshot_animation 的可选项 # 更新 oneshot_animation 的可选项
animation_libraries_updated.connect(notify_property_list_changed) animation_libraries_updated.connect(notify_property_list_changed)
return return
ground_archive = ArchiveManager.archive.ground_archive() as GroundArchive ground_archive = ArchiveManager.archive.ground_archive() as GroundArchive
data.merge(_default_data(), true)
var archive_data = ground_archive.get_data(name) var archive_data = ground_archive.get_data(name)
# merge data # merge data
for key in archive_data.keys(): for key in archive_data.keys():
@ -41,24 +44,24 @@ func _ready() -> void:
ground.ready.connect(_on_ground_ready) ground.ready.connect(_on_ground_ready)
else: else:
_on_ground_ready() _on_ground_ready()
ready.connect(_on_ready)
func _on_ground_ready() -> void: func _on_ground_ready() -> void:
pass pass
func _notification(what: int) -> void: func _on_ready() -> void:
if Engine.is_editor_hint(): if Engine.is_editor_hint():
return return
# 仅在首次进入场景时触发 # 仅在首次进入场景时触发
if what == NOTIFICATION_READY: if oneshot_animation:
if oneshot_animation: if not data["oneshot_animation_played"]:
if not data["oneshot_animation_played"]: play(oneshot_animation)
play(oneshot_animation) animation_finished.connect(_oneshot_animation_finished, CONNECT_ONE_SHOT)
animation_finished.connect(_oneshot_animation_finished, CONNECT_ONE_SHOT) else:
else: if GlobalConfig.DEBUG:
if GlobalConfig.DEBUG: print("oneshot_animation_played:", oneshot_animation)
print("oneshot_animation_played:", oneshot_animation)
func _oneshot_animation_finished(animation_name) -> void: func _oneshot_animation_finished(animation_name) -> void:

View File

@ -1,7 +1,6 @@
@tool @tool
extends AnimationRoot extends AnimationRoot
var frame_relocated = false
var ambush: Ambush2D var ambush: Ambush2D
var frame: Note2D var frame: Note2D
var paper: Interactable2D var paper: Interactable2D
@ -11,7 +10,9 @@ var piano: Interactable2D
# 覆盖该方法 # 覆盖该方法
func _default_data() -> Dictionary: func _default_data() -> Dictionary:
return {} return {
"frame_relocated": false
}
func _ready() -> void: func _ready() -> void:
@ -31,11 +32,11 @@ func _on_ground_ready() -> void:
right_door = $"../DeployLayer/portal_right" right_door = $"../DeployLayer/portal_right"
piano = $"../DeployLayer/钢琴" piano = $"../DeployLayer/钢琴"
# 画框是否已经正位 # 画框是否已经正位
frame_relocated = ambush.played and ambush.one_shot data.frame_relocated = ambush.played and ambush.one_shot
# 禁用鸡毛掸子 # 禁用鸡毛掸子
ambush.enabled = false ambush.enabled = false
# 画框已经正位时,重制画框状态 # 画框已经正位时,重制画框状态
if frame_relocated: if data.frame_relocated:
frame.rotation_degrees = 0.0 frame.rotation_degrees = 0.0
frame.note_key = "c01_摆正的洋相片" frame.note_key = "c01_摆正的洋相片"
if GlobalConfig.DEBUG: if GlobalConfig.DEBUG:
@ -46,7 +47,7 @@ func _on_ground_ready() -> void:
ambush.triggered.connect(_on_ambush_triggered) ambush.triggered.connect(_on_ambush_triggered)
# 纸片状态 # 纸片状态
if frame_relocated: if data.frame_relocated:
# 画框已经正位,纸片已经被拾取 # 画框已经正位,纸片已经被拾取
if paper.interacted_times > 0: if paper.interacted_times > 0:
paper.visible = false paper.visible = false

View File

@ -578,6 +578,10 @@ libraries = {
"": SubResource("AnimationLibrary_ifimj") "": SubResource("AnimationLibrary_ifimj")
} }
script = ExtResource("2_j5oim") script = ExtResource("2_j5oim")
data = {
"frame_relocated": false,
"oneshot_animation_played": false
}
oneshot_animation = "intro" oneshot_animation = "intro"
[node name="BGSprite2D" parent="Ground" index="2"] [node name="BGSprite2D" parent="Ground" index="2"]

View File

@ -58,6 +58,7 @@ func _on_ground_ready() -> void:
game_kid_limp = $"../DeployLayer/【胖小孩背着残疾小孩】/【单残疾小孩】" game_kid_limp = $"../DeployLayer/【胖小孩背着残疾小孩】/【单残疾小孩】"
cat_shadow = $"../DeployLayer/【胖小孩背着残疾小孩】/【单残疾小孩】/【墙上小孩猫影子】" cat_shadow = $"../DeployLayer/【胖小孩背着残疾小孩】/【单残疾小孩】/【墙上小孩猫影子】"
cat = $"../DeployLayer/【墙上黑猫】" cat = $"../DeployLayer/【墙上黑猫】"
cat.visible = false
game_kid_limp.modulate.a = 0.0 game_kid_limp.modulate.a = 0.0
# 院长翻书 # 院长翻书
@ -91,7 +92,7 @@ func _game_counting_down(_res = null):
# 重置镜头 # 重置镜头
SceneManager.focus_player_and_reset_zoom() SceneManager.focus_player_and_reset_zoom()
DialogueManager.show_dialogue_balloon( DialogueManager.show_dialogue_balloon(
preload("res://asset/dialogue/c01.dialogue"), dialogue_c01,
"c01_s06_猫鼠游戏", "c01_s06_猫鼠游戏",
[GlobalConfig.DIALOG_IGNORE_INPUT] [GlobalConfig.DIALOG_IGNORE_INPUT]
) )

View File

@ -121,7 +121,6 @@ position = Vector2(299, 42)
one_shot = false one_shot = false
freeze_time = 3.0 freeze_time = 3.0
hook_animation = "门口_观望" hook_animation = "门口_观望"
hook_method = null
[node name="踢球男孩" parent="Ground/DeployLayer" index="5" instance=ExtResource("5_erliv")] [node name="踢球男孩" parent="Ground/DeployLayer" index="5" instance=ExtResource("5_erliv")]
position = Vector2(535, -3) position = Vector2(535, -3)
@ -278,10 +277,11 @@ move_configs = Array[Dictionary]([{
position = Vector2(123, 43) position = Vector2(123, 43)
[node name="【墙上黑猫】" parent="Ground/DeployLayer" index="15" instance=ExtResource("8_ouldg")] [node name="【墙上黑猫】" parent="Ground/DeployLayer" index="15" instance=ExtResource("8_ouldg")]
position = Vector2(1394, -1) position = Vector2(1453, -14)
scale = Vector2(0.8, 0.8)
sprite_frames = ExtResource("7_dsj2r") sprite_frames = ExtResource("7_dsj2r")
animation = &"【墙上黑猫】跑步" animation = &"【墙上黑猫】跑步"
frame_progress = 0.142437 frame = 3
autostart = false autostart = false
move_configs = Array[Dictionary]([{ move_configs = Array[Dictionary]([{
"animation": &"【墙上黑猫】跑步", "animation": &"【墙上黑猫】跑步",

View File

@ -0,0 +1,28 @@
[gd_scene load_steps=3 format=3 uid="uid://cwu4dhayra8pg"]
[ext_resource type="PackedScene" uid="uid://dayyx4jerj7io" path="res://scene/ground/ground.tscn" id="1_b3cca"]
[sub_resource type="LabelSettings" id="LabelSettings_7adaf"]
font_size = 20
[node name="S08" type="Node2D"]
[node name="Ground" parent="." instance=ExtResource("1_b3cca")]
scene_name = "c01_s08"
[node name="portal_right" parent="Ground/DeployLayer" index="1"]
immediately = false
target_scene = "c02_s08"
[node name="Label" type="Label" parent="Ground/DeployLayer" index="2"]
offset_left = 132.0
offset_top = -9.0
offset_right = 212.0
offset_bottom = 16.0
text = "书店"
label_settings = SubResource("LabelSettings_7adaf")
[node name="MainPlayer" parent="Ground" index="5"]
character = "小小蝶"
[editable path="Ground"]

View File

@ -0,0 +1,36 @@
[gd_scene load_steps=4 format=3 uid="uid://c777lv8mjojcw"]
[ext_resource type="PackedScene" uid="uid://dayyx4jerj7io" path="res://scene/ground/ground.tscn" id="1_mrwu5"]
[ext_resource type="PackedScene" uid="uid://ci34db7xool2n" path="res://scene/ground/script/c01/s01_自动枯萎的花朵.tscn" id="2_shnte"]
[sub_resource type="LabelSettings" id="LabelSettings_7adaf"]
font_size = 20
[node name="S09" type="Node2D"]
[node name="Ground" parent="." instance=ExtResource("1_mrwu5")]
scene_name = "c01_s09"
[node name="portal_right" parent="Ground/DeployLayer" index="1"]
immediately = false
target_scene = "c02_s08"
[node name="Label" type="Label" parent="Ground/DeployLayer" index="2"]
offset_left = 132.0
offset_top = -9.0
offset_right = 212.0
offset_bottom = 16.0
text = "公寓楼外"
label_settings = SubResource("LabelSettings_7adaf")
[node name="S01自动枯萎的花朵" parent="Ground/DeployLayer" index="3" node_paths=PackedStringArray("focus_node") instance=ExtResource("2_shnte")]
position = Vector2(42, 70)
focus_node = NodePath("../../MainPlayer")
[node name="MainPlayer" parent="Ground" index="5"]
character = "小小蝶"
[node name="FGSprite2D" parent="Ground/ParallaxForeground/FGParallaxLayer" index="0"]
texture = null
[editable path="Ground"]

View File

@ -0,0 +1,28 @@
[gd_scene load_steps=3 format=3 uid="uid://be57l2o3vxxtm"]
[ext_resource type="PackedScene" uid="uid://dayyx4jerj7io" path="res://scene/ground/ground.tscn" id="1_hhs2q"]
[sub_resource type="LabelSettings" id="LabelSettings_7adaf"]
font_size = 20
[node name="S10" type="Node2D"]
[node name="Ground" parent="." instance=ExtResource("1_hhs2q")]
scene_name = "c01_s10"
[node name="portal_right" parent="Ground/DeployLayer" index="1"]
immediately = false
target_scene = "c02_s08"
[node name="Label" type="Label" parent="Ground/DeployLayer" index="2"]
offset_left = 132.0
offset_top = -9.0
offset_right = 212.0
offset_bottom = 16.0
text = "公寓楼道"
label_settings = SubResource("LabelSettings_7adaf")
[node name="MainPlayer" parent="Ground" index="5"]
character = "小小蝶"
[editable path="Ground"]

View File

@ -13,6 +13,10 @@ scene_name = "c02_s01"
[node name="AnimationPlayer" parent="Ground" index="0"] [node name="AnimationPlayer" parent="Ground" index="0"]
script = ExtResource("2_uuwn3") script = ExtResource("2_uuwn3")
data = {
"oneshot_animation_played": false,
"received_letter": false
}
oneshot_animation = "" oneshot_animation = ""
[node name="BGSprite2D" parent="Ground" index="2"] [node name="BGSprite2D" parent="Ground" index="2"]

View File

@ -1,12 +1,13 @@
@tool @tool
extends AnimationRoot extends AnimationRoot
@onready var wind_blows = $"../DeployLayer/WindBlows" as AnimatedSprite2D var wind_blows: AnimatedSprite2D
var paper_man: Ambush2D
# 覆盖该方法 # 覆盖该方法
func _default_data() -> Dictionary: func _default_data() -> Dictionary:
return {} return {"display_paper_man": false}
func _ready() -> void: func _ready() -> void:
@ -16,8 +17,13 @@ func _ready() -> void:
func _on_ground_ready() -> void: func _on_ground_ready() -> void:
pass wind_blows = $"../DeployLayer/WindBlows"
wind_blows.visible = false
paper_man = $"../DeployLayer/Ambush纸人"
paper_man.enabled = data.display_paper_man
paper_man.visible = data.display_paper_man
func _oneshot_wind(): func _oneshot_wind():
SceneManager.freeze_player(0) SceneManager.freeze_player(0)
%MainPlayer.visible = false %MainPlayer.visible = false
@ -29,12 +35,25 @@ func _oneshot_wind():
func _on_wind_finished(): func _on_wind_finished():
%MainPlayer.visible = true %MainPlayer.visible = true
wind_blows.visible = false wind_blows.visible = false
func _oneshot_dialog():
DialogueManager.show_dialogue_balloon(dialogue_c02, "c02_s02_天冷") DialogueManager.show_dialogue_balloon(dialogue_c02, "c02_s02_天冷")
DialogueManager.dialogue_ended.connect(_on_dialogue_ended, CONNECT_ONE_SHOT) DialogueManager.dialogue_ended.connect(_on_dialogue_ended, CONNECT_ONE_SHOT)
func _on_dialogue_ended(_res): func _on_dialogue_ended(_res):
SceneManager.release_player() SceneManager.release_player()
func _display_paper_man():
data.display_paper_man = true
paper_man.enabled = true
paper_man.visible = true
paper_man.get_node("Sfx").play()
func paper_man_interacted():
SceneManager.enable_prop_item("prop_1012钥匙")
func lumber_interacted():
SceneManager.pop_debug_dialog_info("美术", "杂物堆⾥有眼睛瞟向玩家/眨动,然后消失(动画)")
_display_paper_man()

View File

@ -1,13 +1,16 @@
[gd_scene load_steps=13 format=3 uid="uid://brck77w81fhvc"] [gd_scene load_steps=17 format=3 uid="uid://brck77w81fhvc"]
[ext_resource type="PackedScene" uid="uid://dayyx4jerj7io" path="res://scene/ground/ground.tscn" id="1_wrr6r"] [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"] [ext_resource type="Script" path="res://scene/ground/scene/c02/s02_animation.gd" id="2_5p8ev"]
[ext_resource type="Texture2D" uid="uid://tqkhrogci71d" path="res://asset/art/scene/c02/s02_走道/bg_过道.png" id="2_cn1s8"] [ext_resource type="Texture2D" uid="uid://tqkhrogci71d" path="res://asset/art/scene/c02/s02_走道/bg_过道.png" id="2_cn1s8"]
[ext_resource type="PackedScene" uid="uid://jr1yd46wm5je" path="res://scene/entity/note.tscn" id="3_fy0o1"] [ext_resource type="PackedScene" uid="uid://jr1yd46wm5je" path="res://scene/entity/note.tscn" id="3_fy0o1"]
[ext_resource type="SpriteFrames" uid="uid://b7fhheih1hbvf" path="res://config/animation/entity_sprite_frames.tres" id="4_wbif8"] [ext_resource type="SpriteFrames" uid="uid://b7fhheih1hbvf" path="res://config/animation/entity_sprite_frames.tres" id="4_wbif8"]
[ext_resource type="PackedScene" uid="uid://wyj4qdjyn4ql" path="res://scene/entity/old/inspectable.tscn" id="5_nhtbp"]
[ext_resource type="Texture2D" uid="uid://cvgw2mxrlr6io" path="res://asset/art/scene/c02/s02_走道/ux_进门鼠疫海报yz.png" id="7_wdwbi"] [ext_resource type="Texture2D" uid="uid://cvgw2mxrlr6io" path="res://asset/art/scene/c02/s02_走道/ux_进门鼠疫海报yz.png" id="7_wdwbi"]
[ext_resource type="Texture2D" uid="uid://5pl1b7cor715" path="res://asset/art/scene/c02/s02_走道/e_纸人.png" id="7_xsghn"] [ext_resource type="Texture2D" uid="uid://5pl1b7cor715" path="res://asset/art/scene/c02/s02_走道/e_纸人.png" id="7_xsghn"]
[ext_resource type="PackedScene" uid="uid://bnf3lkcbpx1ar" path="res://scene/entity/ambush.tscn" id="8_52as8"]
[ext_resource type="PackedScene" uid="uid://beleib3mmu0af" path="res://scene/little_game/八音盒.tscn" id="10_ifae7"]
[ext_resource type="PackedScene" uid="uid://c85t6stvytvjn" path="res://scene/entity/general/sfx.tscn" id="10_pelha"]
[ext_resource type="AudioStream" uid="uid://dq2ndg5yd3rps" path="res://asset/audio/sfx/c02/出现.mp3" id="11_u68d7"]
[ext_resource type="PackedScene" uid="uid://ci5anaxsa1apl" path="res://scene/entity/local_inspectable.tscn" id="12_0fckv"] [ext_resource type="PackedScene" uid="uid://ci5anaxsa1apl" path="res://scene/entity/local_inspectable.tscn" id="12_0fckv"]
[sub_resource type="Animation" id="Animation_abofy"] [sub_resource type="Animation" id="Animation_abofy"]
@ -20,14 +23,11 @@ tracks/0/path = NodePath("AnimationPlayer")
tracks/0/interp = 1 tracks/0/interp = 1
tracks/0/loop_wrap = true tracks/0/loop_wrap = true
tracks/0/keys = { tracks/0/keys = {
"times": PackedFloat32Array(0, 1.6), "times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1, 1), "transitions": PackedFloat32Array(1),
"values": [{ "values": [{
"args": [], "args": [],
"method": &"_oneshot_wind" "method": &"_oneshot_wind"
}, {
"args": [],
"method": &"_oneshot_dialog"
}] }]
} }
@ -36,11 +36,15 @@ _data = {
"oneshot_天冷": SubResource("Animation_abofy") "oneshot_天冷": SubResource("Animation_abofy")
} }
[sub_resource type="RectangleShape2D" id="RectangleShape2D_vc6i4"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_dwg0o"]
resource_local_to_scene = true resource_local_to_scene = true
size = Vector2(35, 70) size = Vector2(10, 70)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_mjnwv"]
size = Vector2(17, 91)
[node name="S02" type="Node2D"] [node name="S02" type="Node2D"]
metadata/_edit_horizontal_guides_ = [98.0]
[node name="Ground" parent="." instance=ExtResource("1_wrr6r")] [node name="Ground" parent="." instance=ExtResource("1_wrr6r")]
scene_name = "c02_s02" scene_name = "c02_s02"
@ -51,11 +55,18 @@ libraries = {
"": SubResource("AnimationLibrary_fjkfm") "": SubResource("AnimationLibrary_fjkfm")
} }
script = ExtResource("2_5p8ev") script = ExtResource("2_5p8ev")
data = {
"display_paper_man": false,
"oneshot_animation_played": false
}
oneshot_animation = "oneshot_天冷" oneshot_animation = "oneshot_天冷"
[node name="BGSprite2D" parent="Ground" index="2"] [node name="BGSprite2D" parent="Ground" index="2"]
texture = ExtResource("2_cn1s8") texture = ExtResource("2_cn1s8")
[node name="portal_left" parent="Ground/DeployLayer" index="0"]
position = Vector2(53, 15)
[node name="portal_right" parent="Ground/DeployLayer" index="1"] [node name="portal_right" parent="Ground/DeployLayer" index="1"]
position = Vector2(678, 6) position = Vector2(678, 6)
target_scene = "c02_s03" target_scene = "c02_s03"
@ -63,8 +74,7 @@ target_portal = "left"
[node name="WindBlows" type="AnimatedSprite2D" parent="Ground/DeployLayer" index="2"] [node name="WindBlows" type="AnimatedSprite2D" parent="Ground/DeployLayer" index="2"]
unique_name_in_owner = true unique_name_in_owner = true
visible = false position = Vector2(462, 9)
position = Vector2(435, 9)
scale = Vector2(1.2, 1.2) scale = Vector2(1.2, 1.2)
sprite_frames = ExtResource("4_wbif8") sprite_frames = ExtResource("4_wbif8")
animation = &"c02_吕萍_风吹过" animation = &"c02_吕萍_风吹过"
@ -79,36 +89,60 @@ position = Vector2(439, -18)
texture_cover = ExtResource("7_wdwbi") texture_cover = ExtResource("7_wdwbi")
content_key = "c02_鼠疫海报" content_key = "c02_鼠疫海报"
[node name="纸人" parent="Ground/DeployLayer" index="5" instance=ExtResource("5_nhtbp")] [node name="Ambush纸人" parent="Ground/DeployLayer" index="5" instance=ExtResource("8_52as8")]
position = Vector2(599, 44) position = Vector2(198, 48)
texture = ExtResource("7_xsghn") texture = ExtResource("7_xsghn")
flip_h = true flip_h = true
trigger_mode = "interact"
freeze_time = 1.0
hook_method = "paper_man_interacted"
[node name="Sign" parent="Ground/DeployLayer/纸人" index="1"] [node name="Sign" parent="Ground/DeployLayer/Ambush纸人" index="0"]
offset_left = 0.0 offset_left = -1.0
offset_top = -44.0 offset_top = -2.0
offset_right = 0.0 offset_right = -1.0
offset_bottom = 36.0 offset_bottom = -2.0
display_sign = true
[node name="CollisionShape2D" parent="Ground/DeployLayer/纸人/Area2D" index="0"] [node name="CollisionShape2D" parent="Ground/DeployLayer/Ambush纸人/Area2D" index="0"]
shape = SubResource("RectangleShape2D_vc6i4") shape = SubResource("RectangleShape2D_dwg0o")
[node name="wall" type="StaticBody2D" parent="Ground/DeployLayer/Ambush纸人"]
position = Vector2(-11, 6)
collision_layer = 2
collision_mask = 0
[node name="CollisionShape2D" type="CollisionShape2D" parent="Ground/DeployLayer/Ambush纸人/wall"]
position = Vector2(-14, -1)
shape = SubResource("RectangleShape2D_mjnwv")
[node name="Sfx" parent="Ground/DeployLayer/Ambush纸人" instance=ExtResource("10_pelha")]
stream = ExtResource("11_u68d7")
dir = "c02"
file = "出现.mp3"
[node name="八音盒" parent="Ground/DeployLayer" index="6" instance=ExtResource("10_ifae7")]
visible = false
[node name="Ambush杂物堆" parent="Ground/DeployLayer" index="7" instance=ExtResource("8_52as8")]
position = Vector2(387, 66)
trigger_mode = "interact"
freeze_time = 1.0
hook_method = "lumber_interacted"
[node name="Label" type="Label" parent="Ground/DeployLayer/Ambush杂物堆"]
offset_left = -16.0
offset_top = 7.0
offset_right = 24.0
offset_bottom = 22.0
text = "杂物堆
"
[node name="MainPlayer" parent="Ground" index="5"] [node name="MainPlayer" parent="Ground" index="5"]
position = Vector2(26, 98) position = Vector2(53, 98)
[node name="CameraFocusMarker" parent="Ground" index="6"]
force_offset = Vector2(0, 0)
lock_horizontal = true
speed = 5.0
half_screen_size = Vector2(282, 120)
shaded_height = 38
shake_enabled = false
shake_strength = 2.0
shake_recovery_speed = 8.0
zoom_ratio = 1.0
[node name="FGSprite2D" parent="Ground/ParallaxForeground/FGParallaxLayer" index="0"] [node name="FGSprite2D" parent="Ground/ParallaxForeground/FGParallaxLayer" index="0"]
texture = null texture = null
[editable path="Ground"] [editable path="Ground"]
[editable path="Ground/DeployLayer/纸人"] [editable path="Ground/DeployLayer/Ambush纸人"]

View File

@ -0,0 +1,94 @@
@tool
extends Node2D
@export var flower_area := Vector2(400, 50):
set(val):
flower_area = val
queue_redraw()
@export var gizmo_outline_color := Color(0.4, 0.4, 0.2, 0.8):
set(val):
gizmo_outline_color = val
queue_redraw()
@export var scatter_on_start := false
@export var debug_scatter := false:
set(val):
debug_scatter = false
if Engine.is_editor_hint():
_init_flowers(true)
@export var auto_fade_distance := 50.0
@export var focus_node: Node2D
var flowers = [] as Array[AnimatedSprite2D]
var faded_flowers = [] as Array[String]
var fade_animation_dict = {
"flower1_开放": "flower1_枯萎",
"flower2_开放": "flower2_枯萎",
}
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
_init_flowers()
if Engine.is_editor_hint():
queue_redraw()
func _enter_tree() -> void:
if is_node_ready():
_init_flowers()
func _init_flowers(scatter := scatter_on_start) -> void:
flowers.clear()
for f in get_children():
if f is AnimatedSprite2D:
flowers.append(f)
for i in range(flowers.size()):
var f = flowers[i]
# clamp to action area
if scatter:
var pos = Vector2(randf() * flower_area.x, randf() * flower_area.y)
f.position = pos
if (
not Engine.is_editor_hint()
and ArchiveManager.archive.global_data_dict.has("faded_flowers")
):
faded_flowers = ArchiveManager.archive.global_data_dict["faded_flowers"]
for f in flowers:
if faded_flowers.has(f.name):
var animation_name = fade_animation_dict.get(f.animation, "")
if animation_name:
f.play(animation_name)
func _draw() -> void:
if Engine.is_editor_hint():
# draw gizmo
var area_rect = Rect2(Vector2.ZERO, flower_area)
# fill
var fill_color = gizmo_outline_color
fill_color.a = 0.4
draw_rect(area_rect, fill_color)
# outline
draw_rect(area_rect, gizmo_outline_color, false, 1.0)
func _physics_process(_delta: float) -> void:
if Engine.is_editor_hint():
return
if not focus_node or not focus_node.is_visible_in_tree():
return
var focus_pos_x = focus_node.global_position.x
var faded := false
for f in flowers:
var f_pos_x = f.global_position.x
var distance = abs(focus_pos_x - f_pos_x)
if distance < auto_fade_distance:
var animation_name = fade_animation_dict.get(f.animation, "")
if animation_name:
f.play(animation_name)
faded_flowers.append(f.name)
faded = true
if faded and not Engine.is_editor_hint():
ArchiveManager.archive.global_data_dict["faded_flowers"] = faded_flowers

View File

@ -0,0 +1,130 @@
[gd_scene load_steps=8 format=3 uid="uid://ci34db7xool2n"]
[ext_resource type="Script" path="res://scene/ground/script/c01/s01_自动枯萎的花朵.gd" id="1_l00w7"]
[ext_resource type="Texture2D" uid="uid://crdphnglw5tv8" path="res://asset/art/little_game/自动枯萎的花/花.png" id="2_h4yj5"]
[sub_resource type="AtlasTexture" id="AtlasTexture_p73pf"]
atlas = ExtResource("2_h4yj5")
region = Rect2(0, 0, 32, 32)
[sub_resource type="AtlasTexture" id="AtlasTexture_2mqji"]
atlas = ExtResource("2_h4yj5")
region = Rect2(0, 32, 32, 32)
[sub_resource type="AtlasTexture" id="AtlasTexture_hm6ef"]
atlas = ExtResource("2_h4yj5")
region = Rect2(32, 0, 32, 32)
[sub_resource type="AtlasTexture" id="AtlasTexture_tkwcu"]
atlas = ExtResource("2_h4yj5")
region = Rect2(32, 32, 32, 32)
[sub_resource type="SpriteFrames" id="SpriteFrames_hq611"]
animations = [{
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_p73pf")
}],
"loop": true,
"name": &"flower1_开放",
"speed": 5.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_2mqji")
}],
"loop": true,
"name": &"flower1_枯萎",
"speed": 5.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_hm6ef")
}],
"loop": true,
"name": &"flower2_开放",
"speed": 5.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_tkwcu")
}],
"loop": true,
"name": &"flower2_枯萎",
"speed": 5.0
}]
[node name="S01自动枯萎的花朵" type="Node2D"]
script = ExtResource("1_l00w7")
[node name="flower1" type="AnimatedSprite2D" parent="."]
position = Vector2(361.267, 37.2719)
sprite_frames = SubResource("SpriteFrames_hq611")
animation = &"flower1_开放"
autoplay = "flower1_开放"
[node name="flower2" type="AnimatedSprite2D" parent="."]
position = Vector2(130.105, 48.4146)
sprite_frames = SubResource("SpriteFrames_hq611")
animation = &"flower2_开放"
autoplay = "flower2_开放"
[node name="flower3" type="AnimatedSprite2D" parent="."]
position = Vector2(90.0357, 29.8311)
sprite_frames = SubResource("SpriteFrames_hq611")
animation = &"flower1_开放"
autoplay = "flower1_开放"
[node name="flower4" type="AnimatedSprite2D" parent="."]
position = Vector2(61.5162, 18.0411)
sprite_frames = SubResource("SpriteFrames_hq611")
animation = &"flower2_开放"
autoplay = "flower2_开放"
[node name="flower5" type="AnimatedSprite2D" parent="."]
position = Vector2(146.966, 14.3762)
sprite_frames = SubResource("SpriteFrames_hq611")
animation = &"flower1_开放"
autoplay = "flower1_开放"
[node name="flower6" type="AnimatedSprite2D" parent="."]
position = Vector2(320.474, 10.6263)
sprite_frames = SubResource("SpriteFrames_hq611")
animation = &"flower2_开放"
autoplay = "flower2_开放"
[node name="flower7" type="AnimatedSprite2D" parent="."]
position = Vector2(341.667, 41.5392)
sprite_frames = SubResource("SpriteFrames_hq611")
animation = &"flower2_枯萎"
autoplay = "flower1_开放"
[node name="flower8" type="AnimatedSprite2D" parent="."]
position = Vector2(287.04, 47.0337)
sprite_frames = SubResource("SpriteFrames_hq611")
animation = &"flower2_开放"
autoplay = "flower2_开放"
[node name="flower9" type="AnimatedSprite2D" parent="."]
position = Vector2(190.428, 2.00511)
sprite_frames = SubResource("SpriteFrames_hq611")
animation = &"flower1_开放"
autoplay = "flower1_开放"
[node name="flower10" type="AnimatedSprite2D" parent="."]
position = Vector2(128.674, 24.4653)
sprite_frames = SubResource("SpriteFrames_hq611")
animation = &"flower2_开放"
autoplay = "flower2_开放"
[node name="flower11" type="AnimatedSprite2D" parent="."]
position = Vector2(73.9961, 8.11343)
sprite_frames = SubResource("SpriteFrames_hq611")
animation = &"flower1_开放"
autoplay = "flower1_开放"
[node name="flower12" type="AnimatedSprite2D" parent="."]
position = Vector2(309.109, 21.3757)
sprite_frames = SubResource("SpriteFrames_hq611")
animation = &"flower2_开放"
autoplay = "flower2_开放"

View File

@ -1,4 +1,4 @@
extends Control extends CanvasLayer
signal exit(passed: bool) signal exit(passed: bool)
@ -51,14 +51,17 @@ var playing_step_sec := 0.5
func _ready() -> void: func _ready() -> void:
layer = GlobalConfig.LAYER_LITTLE_GAME
# debug mode: reset # debug mode: reset
if GlobalConfig.DEBUG: if GlobalConfig.DEBUG:
ArchiveManager.archive.bayinhe_mode = "closed" ArchiveManager.archive.bayinhe_mode = "closed"
ArchiveManager.archive.bayinhe_current_answer = [0, 0, 0, 0, 0, 0, 0, 0, 0] ArchiveManager.archive.bayinhe_current_answer = [0, 0, 0, 0, 0, 0, 0, 0, 0]
playing_step_sec = audio_manual.get_length() / playing_steps playing_step_sec = audio_manual.get_length() / playing_steps
_chechout_mode() if visible:
_chechout_mode()
inside_handle.pressed.connect(_on_handle_pressed) inside_handle.pressed.connect(_on_handle_pressed)
handle_wheel.rotated.connect(_on_wheel_rotated) handle_wheel.rotated.connect(_on_wheel_rotated)
visibility_changed.connect(_on_visibility_changed)
# # test close shaking effect # # test close shaking effect
# ArchiveManager.archive.bayinhe_mode = "playing" # ArchiveManager.archive.bayinhe_mode = "playing"
@ -66,6 +69,13 @@ func _ready() -> void:
# get_tree().create_timer(1.0).timeout.connect(_on_auto_play_finished) # get_tree().create_timer(1.0).timeout.connect(_on_auto_play_finished)
func _on_visibility_changed() -> void:
if visible:
_chechout_mode()
else:
audio_player.stop()
func _chechout_mode(play_sfx := false) -> void: func _chechout_mode(play_sfx := false) -> void:
var mode = ArchiveManager.archive.bayinhe_mode var mode = ArchiveManager.archive.bayinhe_mode
inside_handle.visible = mode == "opened" inside_handle.visible = mode == "opened"
@ -249,7 +259,7 @@ func _on_auto_play_finished():
var count = int(duration * fps) var count = int(duration * fps)
var delta_t = 1.0 / fps var delta_t = 1.0 / fps
for i in range(count): for i in range(count):
var offset = Vector2(randf_range(-delta, delta), randf_range(-delta, delta)) * exp(-i) var _offset = Vector2(randf_range(-delta, delta), randf_range(-delta, delta)) * exp(-i)
tween.tween_property(box, "position", origin_pos + offset, delta_t).set_trans( tween.tween_property(box, "position", origin_pos + _offset, delta_t).set_trans(
Tween.TRANS_CUBIC Tween.TRANS_CUBIC
) )

View File

@ -119,14 +119,8 @@ animations = [{
atlas = ExtResource("4_a11wt") atlas = ExtResource("4_a11wt")
region = Rect2(272, 127, 110, 41) region = Rect2(272, 127, 110, 41)
[node name="八音盒" type="Control"] [node name="八音盒" type="CanvasLayer"]
layout_mode = 3 layer = 5
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 1
script = ExtResource("2_opptd") script = ExtResource("2_opptd")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."] [node name="AnimationPlayer" type="AnimationPlayer" parent="."]
@ -135,7 +129,6 @@ libraries = {
} }
[node name="BG" type="TextureRect" parent="."] [node name="BG" type="TextureRect" parent="."]
layout_mode = 1
anchors_preset = 8 anchors_preset = 8
anchor_left = 0.5 anchor_left = 0.5
anchor_top = 0.5 anchor_top = 0.5
@ -156,7 +149,6 @@ stream = ExtResource("19_7mlnq")
bus = &"game_sfx" bus = &"game_sfx"
[node name="Box" type="TextureRect" parent="."] [node name="Box" type="TextureRect" parent="."]
layout_mode = 1
anchors_preset = 8 anchors_preset = 8
anchor_left = 0.5 anchor_left = 0.5
anchor_top = 0.5 anchor_top = 0.5
@ -177,7 +169,6 @@ sprite_frames = SubResource("SpriteFrames_t7gu7")
centered = false centered = false
[node name="InsideHandle" type="TextureButton" parent="."] [node name="InsideHandle" type="TextureButton" parent="."]
layout_mode = 0
offset_left = 244.0 offset_left = 244.0
offset_top = 157.0 offset_top = 157.0
offset_right = 354.0 offset_right = 354.0
@ -198,7 +189,7 @@ offset_right = 426.0
offset_bottom = 188.0 offset_bottom = 188.0
[node name="LidHint" type="Control" parent="."] [node name="LidHint" type="Control" parent="."]
layout_mode = 1 layout_mode = 3
anchors_preset = 15 anchors_preset = 15
anchor_right = 1.0 anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0

View File

@ -0,0 +1,109 @@
extends CanvasLayer
@onready var container = %PartsContainer as GridContainer
@onready var whole = %Whole as Sprite2D
# from part 0 to 3, rotated by 0, 90, 180, 270 degrees
var rotations = [0, 0, 0, 0]
var selected := 0:
set(value):
selected = value
_display_selected()
func _ready() -> void:
layer = GlobalConfig.LAYER_LITTLE_GAME
for i in range(4):
var part = container.get_child(i)
part.pressed.connect(_select_part.bind(part))
_shuffle()
_display_selected()
whole.visible = false
func _select_part(part) -> void:
selected = part.get_index()
_display_selected()
func _exchange_parts(a: int, b: int) -> void:
var part_a = container.get_child(a)
var part_b = container.get_child(b)
container.move_child(part_a, b)
container.move_child(part_b, a)
# reassign answer
container.move_child(part_a, b)
func _rotate_part(direction := 1) -> void:
var part = container.get_child(selected) as TextureButton
var id = int(str(part.name))
rotations[id] = wrapi(rotations[id] + direction, 0, 4)
var image = part.texture_normal.get_image()
image.rotate_90(direction)
part.texture_normal = ImageTexture.create_from_image(image)
func _shuffle() -> void:
# shuffle answer
for i in range(30):
var a = randi() % 4
var b = randi() % 4
_exchange_parts(a, b)
# shuffle rotations
for i in range(4):
selected = i
for j in range(randi() % 4):
_rotate_part(1)
selected = 0
func _display_selected() -> void:
for i in range(4):
if i == selected:
container.get_child(i).modulate = Color(1, 1, 1)
else:
container.get_child(i).modulate = Color(0.7, 0.7, 0.7)
func _check_answer() -> void:
var success = true
for i in range(4):
var part = container.get_child(i)
var id = int(str(part.name))
if rotations[id] != 0 or id != i:
success = false
if success:
whole.visible = true
container.visible = false
func _unhandled_input(event: InputEvent) -> void:
var handled = false
if event.is_action_pressed("up"):
if selected > 1:
_exchange_parts(selected, selected - 2)
selected -= 2
handled = true
elif event.is_action_pressed("down"):
if selected < 2:
_exchange_parts(selected, selected + 2)
selected += 2
handled = true
elif event.is_action_pressed("left"):
if selected % 2 == 1:
_exchange_parts(selected, selected - 1)
selected -= 1
handled = true
elif event.is_action_pressed("right"):
if selected % 2 == 0:
_exchange_parts(selected, selected + 1)
selected += 1
handled = true
elif event.is_action_pressed("interact"):
_rotate_part()
handled = true
if handled:
_display_selected()
_check_answer()
get_viewport().set_input_as_handled()

View File

@ -0,0 +1,75 @@
[gd_scene load_steps=8 format=3 uid="uid://bp3tkos1ufjcl"]
[ext_resource type="Script" path="res://scene/little_game/拼凑信件.gd" id="1_cifku"]
[ext_resource type="Texture2D" uid="uid://dnjrdh1qnpony" path="res://asset/art/little_game/拼凑信件/完整信件.png" id="3_uenrm"]
[sub_resource type="CompressedTexture2D" id="CompressedTexture2D_5u07c"]
load_path = "res://.godot/imported/信件碎片.png-c35bdb7240fb280003e7b3bca88b316c.ctex"
[sub_resource type="AtlasTexture" id="AtlasTexture_4e0jv"]
atlas = SubResource("CompressedTexture2D_5u07c")
region = Rect2(29, 16, 75, 80)
[sub_resource type="AtlasTexture" id="AtlasTexture_qxu7b"]
atlas = SubResource("CompressedTexture2D_5u07c")
region = Rect2(104, 16, 72, 80)
[sub_resource type="AtlasTexture" id="AtlasTexture_mbck6"]
atlas = SubResource("CompressedTexture2D_5u07c")
region = Rect2(24, 120, 72, 72)
[sub_resource type="AtlasTexture" id="AtlasTexture_5dpsb"]
atlas = SubResource("CompressedTexture2D_5u07c")
region = Rect2(104, 104, 80, 88)
[node name="拼凑信件" type="CanvasLayer"]
layer = 5
script = ExtResource("1_cifku")
[node name="Control" type="Control" parent="."]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="BGTexture" type="TextureRect" parent="Control"]
layout_mode = 1
anchors_preset = 14
anchor_top = 0.5
anchor_right = 1.0
anchor_bottom = 0.5
grow_horizontal = 2
grow_vertical = 2
[node name="Whole" type="Sprite2D" parent="Control"]
unique_name_in_owner = true
visible = false
position = Vector2(263, 161)
texture = ExtResource("3_uenrm")
[node name="PartsContainer" type="GridContainer" parent="Control"]
unique_name_in_owner = true
layout_mode = 0
offset_left = 206.0
offset_top = 72.0
offset_right = 365.0
offset_bottom = 244.0
columns = 2
[node name="0" type="TextureButton" parent="Control/PartsContainer"]
layout_mode = 2
texture_normal = SubResource("AtlasTexture_4e0jv")
[node name="1" type="TextureButton" parent="Control/PartsContainer"]
layout_mode = 2
texture_normal = SubResource("AtlasTexture_qxu7b")
[node name="2" type="TextureButton" parent="Control/PartsContainer"]
layout_mode = 2
texture_normal = SubResource("AtlasTexture_mbck6")
[node name="3" type="TextureButton" parent="Control/PartsContainer"]
layout_mode = 2
texture_normal = SubResource("AtlasTexture_5dpsb")