实现 ReenterLock;更新猫鼠追逐 bgm

This commit is contained in:
cakipaul 2025-06-26 17:38:51 +08:00
parent 5b5af89683
commit 61a4221e3f
44 changed files with 432 additions and 249 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

View File

@ -0,0 +1,24 @@
[remap]
importer="wav"
type="AudioStreamWAV"
uid="uid://nvnoy6pb1ogy"
path="res://.godot/imported/mx_追逐part1.wav-783996c8bca80652b51d8b780783db55.sample"
[deps]
source_file="res://asset/audio/sfx/bgm/猫鼠游戏/mx_追逐part1.wav"
dest_files=["res://.godot/imported/mx_追逐part1.wav-783996c8bca80652b51d8b780783db55.sample"]
[params]
force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=0
edit/loop_begin=0
edit/loop_end=-1
compress/mode=2

Binary file not shown.

View File

@ -0,0 +1,24 @@
[remap]
importer="wav"
type="AudioStreamWAV"
uid="uid://blrlxkkkf5w84"
path="res://.godot/imported/mx_追逐part2.wav-4442ef0529a748eed651332699b745b7.sample"
[deps]
source_file="res://asset/audio/sfx/bgm/猫鼠游戏/mx_追逐part2.wav"
dest_files=["res://.godot/imported/mx_追逐part2.wav-4442ef0529a748eed651332699b745b7.sample"]
[params]
force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=0
edit/loop_begin=0
edit/loop_end=-1
compress/mode=2

View File

@ -24,11 +24,11 @@ c01_5残疾小孩_1,我们玩游戏还差个人,就你了,吕萍。,孩子
c01_5围观A_1,这次咱们又玩什么好玩的游戏?,小肉圆,,,, c01_5围观A_1,这次咱们又玩什么好玩的游戏?,小肉圆,,,,
c01_5胖小孩_3,我们俩说话的时候,你把嘴闭上,听见没有?,大胖,,,, c01_5胖小孩_3,我们俩说话的时候,你把嘴闭上,听见没有?,大胖,,,,
c01_5围观A_2,知道了胖哥,也带我一个,嘿嘿。,小肉圆,,,, c01_5围观A_2,知道了胖哥,也带我一个,嘿嘿。,小肉圆,,,,
c01_5残疾小孩_2,猫捉老鼠,我们四个当猫,你当老鼠。,孩子王,,,, c01_5残疾小孩_2,猫捉老鼠,我们四个当猫,你当老鼠。,孩子王,,[#ban_skip],,
c01_5残疾小孩_3,倒数三个数,你要是被抓到了,我们就请你吃西瓜虫。,孩子王,,,, c01_5残疾小孩_3,倒数三个数,你要是被抓到了,我们就请你吃西瓜虫。,孩子王,,[#ban_skip],,
c01_5胖小孩倒数_3,三!,小胖孩,,[#wait=0.5],, c01_5胖小孩倒数_3,三!,大胖,,[#ban_skip][#wait=0.5],,
c01_5胖小孩倒数_2,二!,小胖孩,,[#wait=0.5],, c01_5胖小孩倒数_2,二!,大胖,,[#ban_skip][#wait=0.5],,
c01_5胖小孩倒数_1,一!,小胖孩,,[#wait=2],, c01_5胖小孩倒数_1,一!,大胖,,[#ban_skip][#wait=2],,
c01_6监督小孩_1,瞧一瞧,看一看,动动各位的发财手,老爷夫人别急走,什么把戏咱都有...,监督小孩,,,, c01_6监督小孩_1,瞧一瞧,看一看,动动各位的发财手,老爷夫人别急走,什么把戏咱都有...,监督小孩,,,,
c01_6监督小孩_2,不要千、不要万,只求一顿温饱饭,又集福、又集善,亲戚儿孙中状元!,监督小孩,,,, c01_6监督小孩_2,不要千、不要万,只求一顿温饱饭,又集福、又集善,亲戚儿孙中状元!,监督小孩,,,,
c01_6监督小孩_3,儿孙坐在那金銮殿,荣华富贵顶上天!,监督小孩,,,, c01_6监督小孩_3,儿孙坐在那金銮殿,荣华富贵顶上天!,监督小孩,,,,

1 keys zh_CN _character _notes _tags zh_SH en
24 c01_5围观A_1 这次咱们又玩什么好玩的游戏? 小肉圆
25 c01_5胖小孩_3 我们俩说话的时候,你把嘴闭上,听见没有? 大胖
26 c01_5围观A_2 知道了胖哥,也带我一个,嘿嘿。 小肉圆
27 c01_5残疾小孩_2 猫捉老鼠,我们四个当猫,你当老鼠。 孩子王 [#ban_skip]
28 c01_5残疾小孩_3 倒数三个数,你要是被抓到了,我们就请你吃西瓜虫。 孩子王 [#ban_skip]
29 c01_5胖小孩倒数_3 三! 小胖孩 大胖 [#wait=0.5] [#ban_skip][#wait=0.5]
30 c01_5胖小孩倒数_2 二! 小胖孩 大胖 [#wait=0.5] [#ban_skip][#wait=0.5]
31 c01_5胖小孩倒数_1 一! 小胖孩 大胖 [#wait=2] [#ban_skip][#wait=2]
32 c01_6监督小孩_1 瞧一瞧,看一看,动动各位的发财手,老爷夫人别急走,什么把戏咱都有... 监督小孩
33 c01_6监督小孩_2 不要千、不要万,只求一顿温饱饭,又集福、又集善,亲戚儿孙中状元! 监督小孩
34 c01_6监督小孩_3 儿孙坐在那金銮殿,荣华富贵顶上天! 监督小孩

View File

@ -39,14 +39,17 @@
小肉圆: 这次咱们又玩什么好玩的游戏? [ID:c01_5围观A_1] 小肉圆: 这次咱们又玩什么好玩的游戏? [ID:c01_5围观A_1]
大胖: 我们俩说话的时候,你把嘴闭上,听见没有? [ID:c01_5胖小孩_3] 大胖: 我们俩说话的时候,你把嘴闭上,听见没有? [ID:c01_5胖小孩_3]
小肉圆: 知道了胖哥,也带我一个,嘿嘿。 [ID:c01_5围观A_2] 小肉圆: 知道了胖哥,也带我一个,嘿嘿。 [ID:c01_5围观A_2]
孩子王: 猫捉老鼠,我们四个当猫,你当老鼠。 [ID:c01_5残疾小孩_2]
孩子王: 倒数三个数,你要是被抓到了,我们就请你吃西瓜虫。 [ID:c01_5残疾小孩_3]
=> END => END
~ c01_s06_猫鼠游戏 ~ c01_s06_猫鼠游戏BGM开始
小胖孩: 三! [#wait=0.5] [ID:c01_5胖小孩倒数_3] 孩子王: 猫捉老鼠,我们四个当猫,你当老鼠。[#ban_skip] [ID:c01_5残疾小孩_2]
小胖孩: 二! [#wait=0.5] [ID:c01_5胖小孩倒数_2] 孩子王: 倒数三个数,你要是被抓到了,我们就请你吃西瓜虫。[#ban_skip] [ID:c01_5残疾小孩_3]
小胖孩: 一! [#wait=2] [ID:c01_5胖小孩倒数_1] => END
~ c01_s06_猫鼠游戏倒计时
大胖: 三![#ban_skip] [#wait=0.5] [ID:c01_5胖小孩倒数_3]
大胖: 二![#ban_skip] [#wait=0.5] [ID:c01_5胖小孩倒数_2]
大胖: 一![#ban_skip] [#wait=2] [ID:c01_5胖小孩倒数_1]
=> END => END

View File

@ -67,31 +67,39 @@ func focus_player_and_reset_zoom(duration := 1.2) -> void:
marker.focus_node(get_player(), duration + .3) marker.focus_node(get_player(), duration + .3)
# action_locked 用于设置界面等强制锁定action_freezed 用于查看物品等锁定 func get_lock() -> PlayerReenterLock:
# action_locked 优先级高于 action_freezed var ground = get_ground()
# action_locked 对应 lock 与 unlock 方法 if ground:
func lock_player(): return ground.reenter_lock
var player = get_player() printerr("get_lock: Ground node not found. return new detached lock")
if player: # 允许访问 lock
player.action_locked = true return PlayerReenterLock.new()
func lock_player(duration := 0):
get_lock().lock_all(duration)
func unlock_player(): func unlock_player():
var player = get_player() get_lock().unlock_all()
if player:
player.action_locked = false
# func is_palyer_operational() -> bool: func hold_player(duration := 0):
# var player = get_player() as MainPlayer get_lock().hold(duration)
# if not player:
# return true
# return player.operational
# func set_player_operational(val := true):
# var player = get_player() as MainPlayer func unhold_player():
# if player: get_lock().unhold()
# player.operational = val
# lock_time: the time to lock the player action. 0 means lock forever, thus the player will be locked until release_player is called.
func freeze_player(lock_time: float, action := 3, auto_quit := false) -> void:
player_action(action, auto_quit)
get_lock().freeze(lock_time)
func release_player():
get_lock().release()
func player_action(action_code: int, auto_quit := false): func player_action(action_code: int, auto_quit := false):
@ -102,32 +110,6 @@ func player_action(action_code: int, auto_quit := false):
printerr("player_action: Player node not found") printerr("player_action: Player node not found")
# action_freezed 对应 freeze 与 release 方法
# lock_time: the time to lock the player action. 0 means lock forever, thus the player will be locked until release_player is called.
func freeze_player(lock_time: float, action := 3, auto_quit := false) -> void:
var player = get_player()
if player:
player.freeze_player(lock_time, action, auto_quit)
else:
printerr("Player node not found")
func freeze_and_play(lock_time: float, animation := "", auto_quit := false) -> void:
var player = get_player()
if player:
player.freeze_and_play(lock_time, animation, auto_quit)
else:
printerr("Player node not found")
func release_player(force_clear:=false):
var player = get_player()
if player:
player.release_player(force_clear)
else:
printerr("Player node not found")
func set_camera_boundary(rect: Rect2) -> void: func set_camera_boundary(rect: Rect2) -> void:
var camera_marker = get_camera_marker() var camera_marker = get_camera_marker()
camera_marker.limit_left = rect.position.x camera_marker.limit_left = rect.position.x
@ -236,15 +218,14 @@ func disable_prop_item(prop_key: String) -> void:
printerr("disable_prop_item PropHud node not found") printerr("disable_prop_item PropHud node not found")
func pop_os_with_str(translation_key: String, auto_freeze := true, auto_release := true) -> Tween: func pop_os_with_str(translation_key: String, auto_freeze := true, auto_release := true) -> void:
var player = get_player() as MainPlayer var player = get_player() as MainPlayer
if player: if player:
var msg = tr(translation_key).replace("<br>", "\n") var msg = tr(translation_key).replace("<br>", "\n")
var lines = await DialogueUtil.generate_lines(msg) var lines = await DialogueUtil.generate_lines(msg)
return player.pop_os(lines, auto_freeze, auto_release) player.pop_os(lines, auto_freeze, auto_release)
else: else:
printerr("Player node not found") printerr("Player node not found")
return create_tween()
func pop_notification(msg: String, number := 1) -> void: func pop_notification(msg: String, number := 1) -> void:

View File

@ -4,6 +4,7 @@ extends CharacterBody2D
class_name MainPlayer class_name MainPlayer
signal position_updated(global_pos: Vector2) signal position_updated(global_pos: Vector2)
# 保证每次 pop_os 后都会有一次 os_finished 信号
signal os_finished signal os_finished
signal animation_finished signal animation_finished
@ -20,6 +21,7 @@ signal animation_finished
@export var catty_light_energy := 0.7 @export var catty_light_energy := 0.7
@export var lock_move_left := false @export var lock_move_left := false
@export var lock_move_right := false @export var lock_move_right := false
@export var reenter_lock: PlayerReenterLock
@export var camera_marker: CameraFocusMarker @export var camera_marker: CameraFocusMarker
@export_enum("吕萍", "吕萍爬行", "吕萍带小猫", "吕萍推柜子", "小小蝶", "盒子猫", "小小小蝶") var character := "吕萍": @export_enum("吕萍", "吕萍爬行", "吕萍带小猫", "吕萍推柜子", "小小蝶", "盒子猫", "小小小蝶") var character := "吕萍":
set(val): set(val):
@ -32,19 +34,6 @@ signal animation_finished
@export var player_movement_rect := Rect2(50, -500, 1400, 1000) @export var player_movement_rect := Rect2(50, -500, 1400, 1000)
@export var velocity_ratio := 1.0 @export var velocity_ratio := 1.0
@export var running_locked := false @export var running_locked := false
# action_locked 用于设置界面等强制锁定禁止游戏场景内的任何操作action_freezed 用于查看物品等锁定(主要用于禁止在场景中移动)
# action_locked 优先级高于 action_freezed
# action_locked 对应 lock 与 unlock 方法
@export var action_locked := false:
set(val):
action_locked = val
_process_action_lock()
# action_freezed 对应 freeze 与 release 方法
@export var action_freezed := false:
set(val):
action_freezed = val
_process_action_lock()
@export_enum("idle", "walking", "running") var current_status := 0: @export_enum("idle", "walking", "running") var current_status := 0:
set(val): set(val):
current_status = val current_status = val
@ -88,6 +77,9 @@ func _ready() -> void:
footstep_timer.timeout.connect(_on_footstep_timer_timeout) footstep_timer.timeout.connect(_on_footstep_timer_timeout)
footstep_timer.stop() footstep_timer.stop()
sprite.animation_finished.connect(animation_finished.emit) sprite.animation_finished.connect(animation_finished.emit)
if not reenter_lock:
push_error("reenter_lock is not set.")
reenter_lock.freeze_changed.connect(_on_freeze_changed)
func reparent_light(node: Node): func reparent_light(node: Node):
@ -131,17 +123,6 @@ func _on_footstep_timer_timeout():
ground.play_footstep_sound() ground.play_footstep_sound()
func _process_action_lock() -> void:
# reset status to idle or stay
if action_locked or action_freezed:
velocity = Vector2.ZERO
if (
current_status == PlayerAnimationConfig.MOVEMENT_WALKING
or current_status == PlayerAnimationConfig.MOVEMENT_RUNNING
):
current_status = PlayerAnimationConfig.MOVEMENT_IDLE
# return whether the player status or facing direction has changed. # return whether the player status or facing direction has changed.
func _check_status(direction) -> bool: func _check_status(direction) -> bool:
var tmp_status = current_status var tmp_status = current_status
@ -234,7 +215,8 @@ func _get_speed(direction: Vector2) -> Vector2:
func _physics_process(_delta: float) -> void: func _physics_process(_delta: float) -> void:
if action_locked or action_freezed or Engine.is_editor_hint() or not is_visible_in_tree(): if Engine.is_editor_hint() or (reenter_lock and reenter_lock.is_frozen()):
# or not is_visible_in_tree()
velocity = Vector2.ZERO velocity = Vector2.ZERO
return return
var x_direction := Input.get_axis("left", "right") var x_direction := Input.get_axis("left", "right")
@ -297,39 +279,32 @@ func player_action(action_code: int, auto_quit: bool):
sprite.animation_finished.connect(_play_animation, CONNECT_ONE_SHOT) sprite.animation_finished.connect(_play_animation, CONNECT_ONE_SHOT)
var freeze_counter := 0 func _on_freeze_changed(count: int, is_add: bool):
var release_timer: SceneTreeTimer if count == 1 and is_add:
_on_first_frozen()
# 自动解除对应 animation 的 loop 状态 # 非首次 freeze 不改变动画状态,因为在动画演出中可能多次 freeze 与 release
# lock_time: the time to lock the player action. 0 means lock forever, thus the player will be locked until release_player is called. func _on_first_frozen() -> void:
func freeze_player(lock_time: float, action_code: int, auto_quit: bool) -> void: # reset status to idle or stay
freeze_counter += 1 velocity = Vector2.ZERO
action_freezed = true if (
current_status == PlayerAnimationConfig.MOVEMENT_WALKING
or current_status == PlayerAnimationConfig.MOVEMENT_RUNNING
):
current_status = PlayerAnimationConfig.MOVEMENT_IDLE
# duration: the time to lock the player action. 0 means lock forever, thus the player will be locked until release_player is called.
func freeze_player(duration: float, action_code: int, auto_quit: bool) -> void:
player_action(action_code, auto_quit) player_action(action_code, auto_quit)
if lock_time: if reenter_lock:
if release_timer and release_timer.time_left > 0: reenter_lock.freeze(duration)
release_timer.time_left = max(lock_time, release_timer.time_left)
else:
release_timer = get_tree().create_timer(lock_time)
release_timer.timeout.connect(release_player)
# force_clear 强制清零计数器 func release_player():
func release_player(force_clear := false): if reenter_lock:
release_timer = null reenter_lock.release()
freeze_counter -= 1
if force_clear:
if freeze_counter != 0 and GlobalConfig.DEBUG:
printerr(
"release_player force_clear=True worked. freeze_counter before: %s" % freeze_counter
)
freeze_counter = 0
if freeze_counter == 0:
action_freezed = false
elif freeze_counter < 0:
action_freezed = false
printerr("release_player called with freeze_counter < 0, this should not happen.")
# velocity_ratio = 1.0 # velocity_ratio = 1.0
# _play_animation() # _play_animation()
@ -405,12 +380,20 @@ func _reset_os_and_light_position():
var os_tween: Tween var os_tween: Tween
# 保证每次 pop_os 后都会有一次 os_finished 信号
var os_finish_emit_lock := Mutex.new()
var os_finished_not_emitted := false
var os_pausing_timer: SceneTreeTimer var os_pausing_timer: SceneTreeTimer
func pop_os(lines := [], auto_freeze := true, auto_release := true) -> Tween: func pop_os(lines := [], auto_freeze := true, auto_release := true) -> void:
if os_tween: if os_tween:
os_tween.kill() os_tween.kill()
os_finish_emit_lock.lock()
if os_finished_not_emitted:
os_finished.emit()
os_finished_not_emitted = true
os_finish_emit_lock.unlock()
if auto_freeze: if auto_freeze:
freeze_player(0, 3, false) freeze_player(0, 3, false)
os_tween = create_tween() os_tween = create_tween()
@ -421,11 +404,15 @@ func pop_os(lines := [], auto_freeze := true, auto_release := true) -> Tween:
# var duration = max(min(4.0, line.text.length() * 0.2), 2.0) - 0.4 # var duration = max(min(4.0, line.text.length() * 0.2), 2.0) - 0.4
os_tween.tween_callback(_os_load_line.bind(line, duration)) os_tween.tween_callback(_os_load_line.bind(line, duration))
os_tween.tween_interval(0.1) os_tween.tween_interval(0.1)
os_tween.tween_callback(os_finished.emit)
os_tween.tween_property(os_contaner, "modulate:a", 0.0, 0.2) os_tween.tween_property(os_contaner, "modulate:a", 0.0, 0.2)
if auto_release: if auto_release:
os_tween.tween_callback(release_player) os_tween.tween_callback(release_player)
return os_tween os_tween.tween_callback(func():
os_finished.emit()
os_finish_emit_lock.lock()
os_finished_not_emitted = false
os_finish_emit_lock.unlock()
)
func _os_load_line(line, duration): func _os_load_line(line, duration):
@ -491,11 +478,12 @@ func set_y_from_ground(player_y: float) -> void:
global_position.y = player_y global_position.y = player_y
func walk_to_x(global_pos_x: float, release_on_arrived := true) -> Tween: func walk_to_x(global_pos_x: float) -> Tween:
return walk_to(Vector2(global_pos_x, global_position.y), release_on_arrived) return walk_to(Vector2(global_pos_x, global_position.y))
func walk_to(global_pos: Vector2, release_on_arrived := true) -> Tween: # auto freeze and release
func walk_to(global_pos: Vector2) -> Tween:
var tween = create_tween() var tween = create_tween()
velocity = Vector2.ZERO velocity = Vector2.ZERO
if GlobalConfig.DEBUG: if GlobalConfig.DEBUG:
@ -511,13 +499,12 @@ func walk_to(global_pos: Vector2, release_on_arrived := true) -> Tween:
_check_status(facing_direction) _check_status(facing_direction)
_play_animation() _play_animation()
tween.tween_property(self, "global_position", global_pos, time_cost) tween.tween_property(self, "global_position", global_pos, time_cost)
tween.tween_callback(_after_walk_to.bind(release_on_arrived)) tween.tween_callback(_after_walk_to)
return tween return tween
func _after_walk_to(release_on_arrived: bool) -> void: func _after_walk_to() -> void:
velocity = Vector2.ZERO velocity = Vector2.ZERO
current_status = PlayerAnimationConfig.MOVEMENT_IDLE current_status = PlayerAnimationConfig.MOVEMENT_IDLE
_play_animation() _play_animation()
if release_on_arrived: release_player()
release_player()

View File

@ -0,0 +1,134 @@
# ReenterLock.gd
extends Node
class_name PlayerReenterLock
#### 目前无需全局,仅需跟随 ground
#### 因此无需在 exit 时重置锁,也无需推迟计数
#### 因为 PlayerReenterLock 生命周期与 ground 一致
####### PlayerReenterLock 系统提供了以下特性 #############
# 可重入性:每个事件可以多次锁定/解锁,通过计数器管理
# 全局状态追踪:使用静态变量追踪整体锁定状态 [无需启用]
# 生命周期管理:自动处理节点进入/退出场景树的情况 [无需启用]
# 错误保护:防止过度释放,并在出现问题时发出警告
# 调试支持:可选的调试模式输出详细信息
# 便捷方法:提供同时锁定/解锁两种状态的方法
#################################################
signal freeze_changed(count: int, is_add: bool)
signal hold_changed(count: int, is_add: bool)
# 实例级别的锁定请求追踪
var _freeze_requests: int = 0
var _hold_requests: int = 0
# 调试模式
var debug_mode := GlobalConfig.DEBUG
func _exit_tree() -> void:
if _freeze_requests > 0:
if debug_mode:
push_warning(
"[ReenterLock] Remains %d freeze requests on exit_tree. parent=" % _freeze_requests,
get_parent()
)
if _hold_requests > 0:
if debug_mode:
print(
"[ReenterLock] Remains %d hold requests on exit_tree. parent=" % _hold_requests,
get_parent()
)
func _create_timer(duration: float, callable: Callable):
if duration > 0 and callable:
get_tree().create_timer(duration).timeout.connect(callable)
# Freeze 相关方法
func freeze(duration := 0.0) -> void:
if duration > 0:
_create_timer(duration, release)
_freeze_requests += 1
if debug_mode:
print("[ReenterLock] Freeze applied: ", _freeze_requests)
freeze_changed.emit(_freeze_requests, true)
func release() -> void:
if _freeze_requests <= 0:
push_warning(
(
"[ReenterLock] Attempting to release more times than frozen! Current local count: %d"
% _freeze_requests
)
)
return
_freeze_requests -= 1
if debug_mode:
print("[ReenterLock] Release applied: ", _freeze_requests)
freeze_changed.emit(_freeze_requests, false)
# Hold 相关方法
func hold(duration := 0.0) -> void:
if duration > 0:
_create_timer(duration, unhold)
_hold_requests += 1
if debug_mode:
print("[ReenterLock] Hold applied: ", _hold_requests)
hold_changed.emit(_hold_requests, true)
func unhold() -> void:
if _hold_requests <= 0:
push_warning(
(
"[ReenterLock] Attempting to unhold more times than held! Current local count: %d"
% _hold_requests
)
)
return
_hold_requests -= 1
if debug_mode:
print("[ReenterLock] Unhold applied: ", _hold_requests)
hold_changed.emit(_hold_requests, false)
# 静态方法:查询当前状态
func is_frozen() -> bool:
return _freeze_requests > 0
func is_held() -> bool:
return _hold_requests > 0
func get_freeze_count() -> int:
return _freeze_requests
func get_hold_count() -> int:
return _hold_requests
# 便捷方法:同时锁定移动和输入
func lock_all(duration := 0.0) -> void:
if duration > 0:
_create_timer(duration, unlock_all)
_hold_requests += 1
_freeze_requests += 1
if debug_mode:
prints("[ReenterLock] LockAll applied (hold, freeze): ", _hold_requests, _freeze_requests)
hold_changed.emit(_hold_requests, true)
freeze_changed.emit(_freeze_requests, true)
func unlock_all() -> void:
release()
unhold()
func _to_string() -> String:
return "[ReenterLock] Freeze: %d, Hold: %d" % [_freeze_requests, _hold_requests]

View File

@ -0,0 +1 @@
uid://diyjjsqnaqm48

View File

@ -46,7 +46,5 @@ shape = SubResource("RectangleShape2D_ogin7")
unique_name_in_owner = true unique_name_in_owner = true
script = ExtResource("7_dnubm") script = ExtResource("7_dnubm")
radius = 3.0 radius = 3.0
delay_arrived = 0.1
action_on_arrived = 4 action_on_arrived = 4
delay_after_action = 0.4
metadata/_custom_type_script = "uid://cnt01hiw52bmn" metadata/_custom_type_script = "uid://cnt01hiw52bmn"

View File

@ -93,6 +93,7 @@ func _ready() -> void:
if content_centered: if content_centered:
content_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER content_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
# sign_mark.interacted.connect(_on_interacted) # sign_mark.interacted.connect(_on_interacted)
sign_snapper.action_on_arrived = action_key
sign_snapper.arrived.connect(_on_interacted) sign_snapper.arrived.connect(_on_interacted)
sign_mark.cancel.connect(_on_cancel) sign_mark.cancel.connect(_on_cancel)
@ -115,25 +116,21 @@ func _on_interacted() -> void:
if STATUS_TRANSITIONING == status: if STATUS_TRANSITIONING == status:
return return
if tried_times == 0 and first_interact_os_key: if tried_times == 0 and first_interact_os_key:
SceneManager.freeze_player(0, action_key)
sign_mark.display_sign = false sign_mark.display_sign = false
var tween = await SceneManager.pop_os_with_str(first_interact_os_key) SceneManager.pop_os_with_str(first_interact_os_key)
tween.tween_callback(_do_action) await SceneManager.get_player().os_finished
tween.tween_callback(func(): sign_mark.display_sign = true) sign_mark.display_sign = true
else: _do_action()
SceneManager.freeze_player(0, action_key)
_do_action()
func _do_action() -> void: func _do_action() -> void:
if STATUS_TRANSITIONING == status:
return
if status == STATUS_NORAML: if status == STATUS_NORAML:
SceneManager.freeze_player(0, action_key)
status = STATUS_TRANSITIONING
tried_times += 1 tried_times += 1
sfx.play() sfx.play()
SceneManager.focus_node(self) SceneManager.focus_node(self)
SceneManager.get_camera_marker().tween_zoom(2.0) SceneManager.get_camera_marker().tween_zoom(2.0)
status = STATUS_TRANSITIONING
var tween = create_tween() var tween = create_tween()
tween.tween_interval(0.8) tween.tween_interval(0.8)
tween.tween_property(container, "modulate:a", 1.0, 0.7) tween.tween_property(container, "modulate:a", 1.0, 0.7)
@ -142,8 +139,6 @@ func _do_action() -> void:
sign_mark.interacted.connect(_on_interacted) sign_mark.interacted.connect(_on_interacted)
sign_snapper.arrived.disconnect(_on_interacted) sign_snapper.arrived.disconnect(_on_interacted)
sign_mark.display_sign = false sign_mark.display_sign = false
SceneManager.freeze_player(0.0, action_key)
cover_rect.texture = texture_cover cover_rect.texture = texture_cover
if content_key == "": if content_key == "":
tip_label.text = tip_cover_without_notes tip_label.text = tip_cover_without_notes

View File

@ -129,9 +129,6 @@ vertical_alignment = 1
[node name="SignSnapper" type="Marker2D" parent="."] [node name="SignSnapper" type="Marker2D" parent="."]
unique_name_in_owner = true unique_name_in_owner = true
script = ExtResource("10_mtbvd") script = ExtResource("10_mtbvd")
release_player_on_arrived = false
radius = 3.0 radius = 3.0
delay_arrived = 0.1
action_on_arrived = 4 action_on_arrived = 4
delay_after_action = 0.4
metadata/_custom_type_script = "uid://cnt01hiw52bmn" metadata/_custom_type_script = "uid://cnt01hiw52bmn"

View File

@ -73,9 +73,9 @@ func _ready() -> void:
return return
area2d.body_entered.connect(_reset) area2d.body_entered.connect(_reset)
area2d.body_exited.connect(_on_cancel) area2d.body_exited.connect(_on_cancel)
sign_snapper.action_on_arrived = action_key
if enable_snapper: if enable_snapper:
sign_snapper.arrived.connect(_pre_interacted) sign_snapper.arrived.connect(_pre_interacted)
sign_snapper.action_on_arrived = action_key
else: else:
sign_snapper.enabled = false sign_snapper.enabled = false
sign_mark.interacted.connect(_pre_interacted) sign_mark.interacted.connect(_pre_interacted)
@ -146,11 +146,10 @@ func _pre_interacted() -> void:
SceneManager.player_action(action_key) SceneManager.player_action(action_key)
if tried_times == 0 and first_interact_os_key: if tried_times == 0 and first_interact_os_key:
sign_mark.display_sign = false sign_mark.display_sign = false
var tween = await SceneManager.pop_os_with_str(first_interact_os_key) SceneManager.pop_os_with_str(first_interact_os_key)
tween.tween_callback(_on_interacted) await SceneManager.get_player().os_finished
tween.tween_callback(func(): sign_mark.display_sign = true) sign_mark.display_sign = true
else: _on_interacted()
_on_interacted()
func _on_interacted() -> void: func _on_interacted() -> void:

View File

@ -50,7 +50,5 @@ shape = SubResource("RectangleShape2D_8d3b4")
unique_name_in_owner = true unique_name_in_owner = true
script = ExtResource("9_03eog") script = ExtResource("9_03eog")
radius = 4.0 radius = 4.0
delay_arrived = 0.1
action_on_arrived = 4 action_on_arrived = 4
delay_after_action = 0.4
metadata/_custom_type_script = "uid://cnt01hiw52bmn" metadata/_custom_type_script = "uid://cnt01hiw52bmn"

View File

@ -120,16 +120,13 @@ func _on_interacted() -> void:
func _show_os(): func _show_os():
interacting = true interacting = true
SceneManager.freeze_player(0.0, action)
create_tween().tween_property(sign_mark, "modulate:a", 0.0, 0.3) create_tween().tween_property(sign_mark, "modulate:a", 0.0, 0.3)
var tween = await SceneManager.pop_os_with_str(note_key, false, true) SceneManager.pop_os_with_str(note_key)
SceneManager.player_action(action)
await SceneManager.get_player().os_finished
var tween = create_tween()
tween.tween_property(sign_mark, "modulate:a", 1.0, 0.3) tween.tween_property(sign_mark, "modulate:a", 1.0, 0.3)
tween.tween_callback(_on_os_finished)
func _on_os_finished():
interacting = false interacting = false
SceneManager.release_player()
func _show_balloon(res, title): func _show_balloon(res, title):

View File

@ -4,6 +4,7 @@ class_name Npc2D extends AnimatedSprite2D
signal interacted signal interacted
# <0 means no walk to edge # <0 means no walk to edge
@export var snap_to_edge := true
@export var walk_to_edge_width := 25.0 @export var walk_to_edge_width := 25.0
@export var action_key := 4 @export var action_key := 4
@export var enabled := true: @export var enabled := true:
@ -42,6 +43,8 @@ func _ready() -> void:
shape.size.x = collision_width_and_x.x shape.size.x = collision_width_and_x.x
area2d.position.x = collision_width_and_x.y area2d.position.x = collision_width_and_x.y
sign_snapper.action_on_arrived = action_key sign_snapper.action_on_arrived = action_key
sign_snapper.radius = walk_to_edge_width
sign_snapper.enabled = snap_to_edge
if Engine.is_editor_hint(): if Engine.is_editor_hint():
# editor 直接展示 # editor 直接展示
speaking_sign.visible = true speaking_sign.visible = true
@ -53,11 +56,9 @@ func _ready() -> void:
base_mod = speaking_sign.modulate base_mod = speaking_sign.modulate
area2d.body_entered.connect(_on_entered) area2d.body_entered.connect(_on_entered)
area2d.body_exited.connect(_on_exited) area2d.body_exited.connect(_on_exited)
if walk_to_edge_width >= 0: if snap_to_edge:
sign_snapper.radius = walk_to_edge_width
sign_snapper.arrived.connect(_on_interacted) sign_snapper.arrived.connect(_on_interacted)
else: else:
sign_snapper.enabled = false
sign_mark.interacted.connect(_on_interacted) sign_mark.interacted.connect(_on_interacted)
# sign_mark.cancel.connect(_stop_speaking) # sign_mark.cancel.connect(_stop_speaking)
sign_mark.toggle_active.connect(_on_toggle_active) sign_mark.toggle_active.connect(_on_toggle_active)
@ -104,7 +105,7 @@ func _on_interacted() -> void:
interacted.emit() interacted.emit()
DialogueManager.show_dialogue_balloon(dialogue_res, dialogue_title) DialogueManager.show_dialogue_balloon(dialogue_res, dialogue_title)
speaking = true speaking = true
SceneManager.freeze_player(0) SceneManager.freeze_player(0, action_key)
DialogueManager.dialogue_ended.connect(_dialog_end, CONNECT_ONE_SHOT) DialogueManager.dialogue_ended.connect(_dialog_end, CONNECT_ONE_SHOT)
var tween = create_tween() var tween = create_tween()
tween.tween_property(speaking_sign, "modulate", Color.WHITE, 0.5) tween.tween_property(speaking_sign, "modulate", Color.WHITE, 0.5)

View File

@ -123,12 +123,13 @@ animations = [{
[sub_resource type="RectangleShape2D" id="RectangleShape2D_4fuic"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_4fuic"]
resource_local_to_scene = true resource_local_to_scene = true
size = Vector2(25, 100) size = Vector2(35, 100)
[node name="Npc" type="AnimatedSprite2D"] [node name="Npc" type="AnimatedSprite2D"]
light_mask = 5 light_mask = 5
script = ExtResource("1_jegr2") script = ExtResource("1_jegr2")
collision_width_and_x = Vector2(25, 0) snap_to_edge = null
collision_width_and_x = Vector2(35, 0)
dialogue_title = "" dialogue_title = ""
[node name="Sfx" type="AudioStreamPlayer" parent="."] [node name="Sfx" type="AudioStreamPlayer" parent="."]
@ -183,7 +184,5 @@ unique_name_in_owner = true
script = ExtResource("8_7lwt5") script = ExtResource("8_7lwt5")
radius = 20.0 radius = 20.0
walk_to_edge = true walk_to_edge = true
delay_arrived = 0.1
action_on_arrived = 4 action_on_arrived = 4
delay_after_action = 0.4
metadata/_custom_type_script = "uid://cnt01hiw52bmn" metadata/_custom_type_script = "uid://cnt01hiw52bmn"

View File

@ -15,6 +15,7 @@ signal sign_mark_offset_updated
enabled = val enabled = val
if is_node_ready(): if is_node_ready():
_check_sign_display() _check_sign_display()
@export var action_key := 4
# 除了 picked 必然隐藏,其他情况下跟随 enabled 状态 # 除了 picked 必然隐藏,其他情况下跟随 enabled 状态
@export var visible_follow_enabled := true @export var visible_follow_enabled := true
@export var collision_width_and_x := Vector2(20.0, 0): @export var collision_width_and_x := Vector2(20.0, 0):
@ -58,6 +59,7 @@ func _ready() -> void:
var shape = area2d.get_node("CollisionShape2D").shape var shape = area2d.get_node("CollisionShape2D").shape
shape.size.x = collision_width_and_x.x shape.size.x = collision_width_and_x.x
area2d.position.x = collision_width_and_x.y area2d.position.x = collision_width_and_x.y
sign_snapper.action_on_arrived = action_key
if Engine.is_editor_hint(): if Engine.is_editor_hint():
var animation_player = _get_animation_player() var animation_player = _get_animation_player()
# 更新 hook_animation 的可选项 # 更新 hook_animation 的可选项

View File

@ -13,6 +13,7 @@ size = Vector2(20, 60)
[node name="Pickable" type="Sprite2D"] [node name="Pickable" type="Sprite2D"]
script = ExtResource("1_jk1u0") script = ExtResource("1_jk1u0")
action_key = null
prop_key = "" prop_key = ""
[node name="Sfx" type="AudioStreamPlayer" parent="."] [node name="Sfx" type="AudioStreamPlayer" parent="."]
@ -43,7 +44,5 @@ shape = SubResource("RectangleShape2D_k6och")
unique_name_in_owner = true unique_name_in_owner = true
script = ExtResource("6_4qt5l") script = ExtResource("6_4qt5l")
radius = 10.0 radius = 10.0
delay_arrived = 0.1
action_on_arrived = 4 action_on_arrived = 4
delay_after_action = 0.4
metadata/_custom_type_script = "uid://cnt01hiw52bmn" metadata/_custom_type_script = "uid://cnt01hiw52bmn"

View File

@ -75,6 +75,4 @@ shape = SubResource("RectangleShape2D_munml")
unique_name_in_owner = true unique_name_in_owner = true
script = ExtResource("12_bxihn") script = ExtResource("12_bxihn")
radius = 10.0 radius = 10.0
delay_arrived = 0.1
delay_after_action = 0.4
metadata/_custom_type_script = "uid://cnt01hiw52bmn" metadata/_custom_type_script = "uid://cnt01hiw52bmn"

View File

@ -189,8 +189,7 @@ func _unhandled_input(event: InputEvent) -> void:
return return
# if lock_on_player_freezed and SceneManager.is_palyer_freezed_or_locked(): # if lock_on_player_freezed and SceneManager.is_palyer_freezed_or_locked():
# return # return
var player = SceneManager.get_player() if SceneManager.get_lock().is_held():
if not player or player.action_locked:
return return
if activated: if activated:
if event.is_action_pressed("interact"): if event.is_action_pressed("interact"):

View File

@ -5,21 +5,23 @@ class_name SignSnapper
signal arrived signal arrived
@export var enabled := true @export var enabled := true
@export var release_player_on_arrived := true
# 仅使用 x 坐标;否则也用 y 进行 walk to # 仅使用 x 坐标;否则也用 y 进行 walk to
@export var use_x_only := true @export var use_x_only := true
# 允许小幅调动0-3px 被忽视3-5px 被视作 5px
@export var auto_adjust := true
# x 左右有效范围 # x 左右有效范围
@export_range(0.0, 20.0, 0.1) var radius := 0.0 @export_range(0.0, 20.0, 0.1) var radius := 0.0
# 让玩家走到边缘,特别适用于 npc 对话等情景 # 让玩家走到边缘,特别适用于 npc 对话等情景
@export var walk_to_edge := false @export var walk_to_edge := false
# arrived 延时
@export_range(0.0, 10.0, 0.1) var delay_arrived := 0.0
@export var action_on_arrived := 3 @export var action_on_arrived := 3
@export_range(0.0, 10.0, 0.1) var delay_after_action := 0.0
@export_tool_button("debug 检查玩家触发位置") var debug_check_player_pos = _debug_check_player_pos @export_tool_button("debug 检查玩家触发位置") var debug_check_player_pos = _debug_check_player_pos
var detacted_sign: Sign var detacted_sign: Sign
# arrived 延时: delay_arrived-arrived
static var delay_arrived := 0.0
static var delay_after_action := 0.0
# 玩家在和 sign 交互时,如果读到节点中有 SignSnapper则移动到该位置(x 对齐) # 玩家在和 sign 交互时,如果读到节点中有 SignSnapper则移动到该位置(x 对齐)
func _ready(): func _ready():
@ -49,7 +51,20 @@ func _on_interacted():
target_pos.x -= radius target_pos.x -= radius
else: else:
target_pos.x += radius target_pos.x += radius
var tween = player.walk_to(target_pos, release_player_on_arrived) var diff = absf(player_x - target_pos.x)
if auto_adjust:
# 允许小幅调动0-3px 被忽视3-5px 被视作 5px
if diff < 3:
target_pos.x = player_x
diff = 0
elif diff < 5:
target_pos.x = player_x + (5 if target_pos.x > player_x else -5)
diff = 5
var tween
if diff == 0:
tween = create_tween()
else:
tween = player.walk_to(target_pos)
if delay_arrived > 0: if delay_arrived > 0:
tween.tween_interval(delay_arrived) tween.tween_interval(delay_arrived)
if action_on_arrived != 3: if action_on_arrived != 3:

View File

@ -32,6 +32,7 @@ var default_portal := "left"
# var main_scene := preload("res://scene/main.tscn") as PackedScene # var main_scene := preload("res://scene/main.tscn") as PackedScene
@onready var player_line = %PlayerLine2D as Line2D @onready var player_line = %PlayerLine2D as Line2D
@onready var reenter_lock = %PlayerReenterLock as PlayerReenterLock
@onready var player = %MainPlayer as MainPlayer @onready var player = %MainPlayer as MainPlayer
@onready var directional_light := %DirectionalLight2D as DirectionalLight2D @onready var directional_light := %DirectionalLight2D as DirectionalLight2D
@onready var bg_sprite = %BGSprite2D as Sprite2D @onready var bg_sprite = %BGSprite2D as Sprite2D

View File

@ -1,6 +1,7 @@
[gd_scene load_steps=8 format=3 uid="uid://dayyx4jerj7io"] [gd_scene load_steps=9 format=3 uid="uid://dayyx4jerj7io"]
[ext_resource type="Script" uid="uid://bee4ot74k4wg2" path="res://scene/ground/ground.gd" id="1_0vrlo"] [ext_resource type="Script" uid="uid://bee4ot74k4wg2" path="res://scene/ground/ground.gd" id="1_0vrlo"]
[ext_resource type="Script" uid="uid://diyjjsqnaqm48" path="res://scene/character/reenter_lock.gd" id="2_6ggqv"]
[ext_resource type="PackedScene" uid="uid://cjhw5ecygrqty" path="res://scene/character/main_player.tscn" id="3_atha7"] [ext_resource type="PackedScene" uid="uid://cjhw5ecygrqty" path="res://scene/character/main_player.tscn" id="3_atha7"]
[ext_resource type="PackedScene" uid="uid://61pis75a8fdq" path="res://scene/entity/portal.tscn" id="3_t73yw"] [ext_resource type="PackedScene" uid="uid://61pis75a8fdq" path="res://scene/entity/portal.tscn" id="3_t73yw"]
[ext_resource type="PackedScene" uid="uid://cqkeegrcdjyg4" path="res://scene/ground/camera/camera_focus_marker.tscn" id="4_mgk0a"] [ext_resource type="PackedScene" uid="uid://cqkeegrcdjyg4" path="res://scene/ground/camera/camera_focus_marker.tscn" id="4_mgk0a"]
@ -19,6 +20,11 @@ script = ExtResource("1_0vrlo")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."] [node name="AnimationPlayer" type="AnimationPlayer" parent="."]
[node name="PlayerReenterLock" type="Node" parent="."]
unique_name_in_owner = true
script = ExtResource("2_6ggqv")
metadata/_custom_type_script = "uid://diyjjsqnaqm48"
[node name="BGSprite2D" type="Sprite2D" parent="."] [node name="BGSprite2D" type="Sprite2D" parent="."]
unique_name_in_owner = true unique_name_in_owner = true
z_index = -5 z_index = -5
@ -37,9 +43,10 @@ portal_name = "right"
[node name="AmbientLayer" type="Node2D" parent="."] [node name="AmbientLayer" type="Node2D" parent="."]
[node name="MainPlayer" parent="." node_paths=PackedStringArray("camera_marker") instance=ExtResource("3_atha7")] [node name="MainPlayer" parent="." node_paths=PackedStringArray("reenter_lock", "camera_marker") instance=ExtResource("3_atha7")]
unique_name_in_owner = true unique_name_in_owner = true
position = Vector2(41, 88) position = Vector2(41, 88)
reenter_lock = NodePath("../PlayerReenterLock")
camera_marker = NodePath("../CameraFocusMarker") camera_marker = NodePath("../CameraFocusMarker")
[node name="CameraFocusMarker" parent="." node_paths=PackedStringArray("focusing_node") instance=ExtResource("4_mgk0a")] [node name="CameraFocusMarker" parent="." node_paths=PackedStringArray("focusing_node") instance=ExtResource("4_mgk0a")]

View File

@ -20,7 +20,6 @@ var first_entered := true
var ground: Ground2D var ground: Ground2D
var display_mask_sec = 0.0 var display_mask_sec = 0.0
# 场景名字映射到路径 # 场景名字映射到路径
static var GROUND_SCENE_PATH_DICT = { static var GROUND_SCENE_PATH_DICT = {
"c01_s05": "res://scene/ground/scene/c01/s05_院长房间.tscn", "c01_s05": "res://scene/ground/scene/c01/s05_院长房间.tscn",
@ -41,17 +40,18 @@ static var GROUND_SCENE_PATH_DICT = {
"c02_s08": "res://scene/ground/scene/c02/s08_瞎子卧室.tscn", "c02_s08": "res://scene/ground/scene/c02/s08_瞎子卧室.tscn",
"c02_s09": "res://scene/ground/scene/c02/s09_裂缝.tscn", "c02_s09": "res://scene/ground/scene/c02/s09_裂缝.tscn",
"c02_s10": "res://scene/ground/scene/c02/s10_空房间.tscn", "c02_s10": "res://scene/ground/scene/c02/s10_空房间.tscn",
"c02_s11": "res://scene/ground/scene/c02/s11_一楼火灾.tscn", # 注:该场景合并在了 c02_s03 院子中 "c02_s11": "res://scene/ground/scene/c02/s11_一楼火灾.tscn", # 注:该场景合并在了 c02_s03 院子中
"c02_s12": "res://scene/ground/scene/c02/s12_盒子猫.tscn", "c02_s12": "res://scene/ground/scene/c02/s12_盒子猫.tscn",
"c02_s13": "res://scene/ground/scene/c02/s13_盒子猫二楼.tscn", "c02_s13": "res://scene/ground/scene/c02/s13_盒子猫二楼.tscn",
"c02_s14": "res://scene/ground/scene/c02/s14_盒子猫二楼内侧.tscn", "c02_s14": "res://scene/ground/scene/c02/s14_盒子猫二楼内侧.tscn",
"c02_s15": "res://scene/ground/scene/c02/s15_盒子猫一楼内侧.tscn", "c02_s15": "res://scene/ground/scene/c02/s15_盒子猫一楼内侧.tscn",
"c02_s16": "res://scene/ground/scene/c02/s16_盒子猫三楼内侧.tscn", "c02_s16": "res://scene/ground/scene/c02/s16_盒子猫三楼内侧.tscn",
"c02_s17": "res://scene/ground/scene/c02/s17_盒子猫三楼.tscn", "c02_s17": "res://scene/ground/scene/c02/s17_盒子猫三楼.tscn",
"c02_s18": "res://scene/ground/scene/c02/s18_盒子猫一楼.tscn", "c02_s18": "res://scene/ground/scene/c02/s18_盒子猫一楼.tscn",
} }
func _ready() -> void:
func _ready() -> void:
mask_layer.layer = GlobalConfig.CANVAS_LAYER_GROUND_MASK mask_layer.layer = GlobalConfig.CANVAS_LAYER_GROUND_MASK
mask.visible = true mask.visible = true
mask.color.a = 0.0 mask.color.a = 0.0
@ -100,9 +100,16 @@ func toggle_mask(display: bool, mask_color: Color, wait_time: float) -> Tween:
tween.tween_property(mask, "color:a", 0.0, duration).set_trans(Tween.TRANS_CUBIC) tween.tween_property(mask, "color:a", 0.0, duration).set_trans(Tween.TRANS_CUBIC)
return tween return tween
func transition_to_scene( 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, mask_color := Color.BLACK
) -> void: ) -> void:
if ground:
print("GroundLoader transition_to_scene: pause prev ground.")
ground.process_mode = Node.PROCESS_MODE_DISABLED
if GlobalConfig.DEBUG:
# print reenter lock status
print("GroundLoader transition_to_scene: reenter lock status: ", ground.reenter_lock)
var scene_path = GROUND_SCENE_PATH_DICT.get(scene_name) var scene_path = GROUND_SCENE_PATH_DICT.get(scene_name)
if scene_path: if scene_path:
current_scene = scene_name current_scene = scene_name
@ -113,14 +120,39 @@ func transition_to_scene(
if wait_time > 0.0: if wait_time > 0.0:
# 转场效果,在 _load_ground_node 之前播放 # 转场效果,在 _load_ground_node 之前播放
var tween = toggle_mask(true, mask_color, wait_time) var tween = toggle_mask(true, mask_color, wait_time)
tween.tween_callback(call_deferred.bind("_do_transition", scene_name)) tween.tween_callback(_do_transition.call_deferred.bind(scene_name))
tween.tween_callback(toggle_mask.bind(false, mask_color, wait_time)) tween.tween_callback(_hide_mask_with_frozen_ground.bind(mask_color, wait_time))
else: else:
_do_transition.call_deferred(scene_name) _do_transition.call_deferred(scene_name)
else: else:
print("Scene not found: " + scene_name) print("Scene not found: " + scene_name)
var _frozen_start_time_ms: int
var _freeze_ground_required := false:
set(val):
_freeze_ground_required = val
if ground:
if val:
print("GroundLoader _freeze_ground_required: frozen")
ground.process_mode = Node.PROCESS_MODE_DISABLED
_frozen_start_time_ms = Time.get_ticks_msec()
else:
ground.process_mode = Node.PROCESS_MODE_INHERIT
print(
"GroundLoader _freeze_ground_required: unfrozen. frozen duration(ms):",
Time.get_ticks_msec() - _frozen_start_time_ms
)
func _hide_mask_with_frozen_ground(mask_color: Color, wait_time: float):
# 锁定 ground 状态
_freeze_ground_required = true
toggle_mask(false, mask_color, wait_time).tween_callback(
func(): _freeze_ground_required = false
)
func _update_archive(): func _update_archive():
ArchiveManager.archive.current_scene = current_scene ArchiveManager.archive.current_scene = current_scene
ArchiveManager.archive.entrance_portal = entrance_portal ArchiveManager.archive.entrance_portal = entrance_portal
@ -138,6 +170,10 @@ func _do_transition(scene_name: String) -> void:
# 因为 ground 在 enter_tree 时会用到 SceneManager 的方法 # 因为 ground 在 enter_tree 时会用到 SceneManager 的方法
# 其中间接用到了 GroundLoader 的 ground # 其中间接用到了 GroundLoader 的 ground
ground = _load_ground_node(scene_name) ground = _load_ground_node(scene_name)
if _freeze_ground_required:
ground.process_mode = Node.PROCESS_MODE_DISABLED
print("GroundLoader _freeze_ground_required: frozen (delayed)")
_frozen_start_time_ms = Time.get_ticks_msec()
_add_ground() _add_ground()
# 预先加载邻居场景 # 预先加载邻居场景
_post_transition() _post_transition()

View File

@ -509,7 +509,7 @@ tracks/6/keys = {
"times": PackedFloat32Array(0.08), "times": PackedFloat32Array(0.08),
"transitions": PackedFloat32Array(1), "transitions": PackedFloat32Array(1),
"values": [{ "values": [{
"args": [Vector2(261, 88), false], "args": [Vector2(261, 88)],
"method": &"walk_to" "method": &"walk_to"
}] }]
} }

View File

@ -122,17 +122,17 @@ func game_intro() -> void:
func _game_counting_down(_res = null): func _game_counting_down(_res = null):
$"Sfx猫鼠游戏".play() $"Sfx猫鼠游戏".play()
SceneManager.release_player() DialogueManager.show_dialogue_balloon(dialogue_c01, "c01_s06_猫鼠游戏BGM开始")
await DialogueManager.dialogue_ended
# 重置镜头 # 重置镜头
SceneManager.focus_player_and_reset_zoom(2.5) SceneManager.focus_player_and_reset_zoom(2.5)
DialogueManager.show_dialogue_balloon( SceneManager.release_player()
dialogue_c01, "c01_s06_猫鼠游戏", [GlobalConfig.DIALOG_IGNORE_INPUT] DialogueManager.show_dialogue_balloon(dialogue_c01, "c01_s06_猫鼠游戏倒计时")
)
# 禁止玩家向左移动,同时可以使右侧腾出空间,玩家可以继续向右移动 # 禁止玩家向左移动,同时可以使右侧腾出空间,玩家可以继续向右移动
var player = SceneManager.get_player() as MainPlayer var player = SceneManager.get_player() as MainPlayer
var left = player.global_position.x var left = player.global_position.x
player.player_movement_rect.position.x = left player.player_movement_rect.position.x = left
get_tree().create_timer(2.5).timeout.connect(_kids_start_run) get_tree().create_timer(2.0).timeout.connect(_kids_start_run)
cat.visible = true cat.visible = true
cat.play("【墙上黑猫】跑步") cat.play("【墙上黑猫】跑步")
cat.get_node("猫咪嘶吼音效").play() cat.get_node("猫咪嘶吼音效").play()
@ -273,9 +273,11 @@ func game_restart():
game_kid.global_position.x = kids_start_run_initial_x[2] game_kid.global_position.x = kids_start_run_initial_x[2]
ground_loader.toggle_mask(false, Color.BLACK, 1.0) ground_loader.toggle_mask(false, Color.BLACK, 1.0)
await get_tree().create_timer(1.0).timeout await get_tree().create_timer(1.0).timeout
# 开始跑
SceneManager.release_player() SceneManager.release_player()
$"Sfx猫鼠游戏".set("parameters/switch_to_clip", "Intro") $"Sfx猫鼠游戏".set("parameters/switch_to_clip", "Intro")
await get_tree().create_timer(2.0).timeout DialogueManager.show_dialogue_balloon(dialogue_c01, "c01_s06_猫鼠游戏倒计时")
await get_tree().create_timer(1.5).timeout
_kids_start_run() _kids_start_run()
@ -286,7 +288,6 @@ func game_succeed():
else: else:
game_kid_limp.pause() game_kid_limp.pause()
cat_shadow.pause() cat_shadow.pause()
SceneManager.freeze_player(0)
transport_player_to_next_scene(true) transport_player_to_next_scene(true)

View File

@ -13,9 +13,9 @@
[ext_resource type="AudioStream" uid="uid://dlsd8wrx3v31f" path="res://asset/audio/sfx/环境音/序章/02_孤儿院走廊.wav" id="5_6mww0"] [ext_resource type="AudioStream" uid="uid://dlsd8wrx3v31f" path="res://asset/audio/sfx/环境音/序章/02_孤儿院走廊.wav" id="5_6mww0"]
[ext_resource type="PackedScene" uid="uid://cpc5037mesjl7" path="res://scene/ground/script/c01/s06_踢球男孩.tscn" id="5_erliv"] [ext_resource type="PackedScene" uid="uid://cpc5037mesjl7" path="res://scene/ground/script/c01/s06_踢球男孩.tscn" id="5_erliv"]
[ext_resource type="Texture2D" uid="uid://b08jrwtr3dpaq" path="res://asset/art/scene/c01/s06_孤儿院长廊围墙/bg_树干遮挡.png" id="5_rdmp5"] [ext_resource type="Texture2D" uid="uid://b08jrwtr3dpaq" path="res://asset/art/scene/c01/s06_孤儿院长廊围墙/bg_树干遮挡.png" id="5_rdmp5"]
[ext_resource type="AudioStream" uid="uid://ciuxwa4jivi3m" path="res://asset/audio/sfx/bgm/猫鼠游戏/Intro阶段.wav" id="6_lxxek"] [ext_resource type="AudioStream" uid="uid://nvnoy6pb1ogy" path="res://asset/audio/sfx/bgm/猫鼠游戏/mx_追逐part1.wav" id="6_lxxek"]
[ext_resource type="SpriteFrames" uid="uid://c6okvaeemoodq" path="res://asset/art/gif/c01_孤儿院围墙/c01_孤儿院围墙_frames.tres" id="7_dsj2r"] [ext_resource type="SpriteFrames" uid="uid://c6okvaeemoodq" path="res://asset/art/gif/c01_孤儿院围墙/c01_孤儿院围墙_frames.tres" id="7_dsj2r"]
[ext_resource type="AudioStream" uid="uid://woqygpidlpp1" path="res://asset/audio/sfx/bgm/猫鼠游戏/Loop阶段.wav" id="7_phfqg"] [ext_resource type="AudioStream" uid="uid://blrlxkkkf5w84" path="res://asset/audio/sfx/bgm/猫鼠游戏/mx_追逐part2.wav" id="7_phfqg"]
[ext_resource type="Script" uid="uid://rq6w1vuhuq1m" path="res://scene/entity/audio/sfx.gd" id="8_1g8pi"] [ext_resource type="Script" uid="uid://rq6w1vuhuq1m" path="res://scene/entity/audio/sfx.gd" id="8_1g8pi"]
[ext_resource type="PackedScene" uid="uid://b50n0hvs4yh75" path="res://addons/property-inspector/pro_animation_sprite2d/pro_animated_sprite.tscn" id="8_ouldg"] [ext_resource type="PackedScene" uid="uid://b50n0hvs4yh75" path="res://addons/property-inspector/pro_animation_sprite2d/pro_animated_sprite.tscn" id="8_ouldg"]
[ext_resource type="Texture2D" uid="uid://f6xl83h8g5mo" path="res://asset/art/scene/c01/s06_孤儿院长廊围墙/【桌椅】 上层遮挡部分.png" id="11_q3ypm"] [ext_resource type="Texture2D" uid="uid://f6xl83h8g5mo" path="res://asset/art/scene/c01/s06_孤儿院长廊围墙/【桌椅】 上层遮挡部分.png" id="11_q3ypm"]
@ -164,7 +164,6 @@ metadata/_custom_type_script = "uid://wapo47a1oddf"
position = Vector2(490, 36) position = Vector2(490, 36)
stream = ExtResource("5_6mww0") stream = ExtResource("5_6mww0")
autoplay = true autoplay = true
stream_paused = true
bus = &"game_sfx" bus = &"game_sfx"
script = ExtResource("4_qq2uh") script = ExtResource("4_qq2uh")
loop = true loop = true
@ -177,7 +176,7 @@ script = ExtResource("8_1g8pi")
mode = "BGM" mode = "BGM"
metadata/_custom_type_script = "uid://rq6w1vuhuq1m" metadata/_custom_type_script = "uid://rq6w1vuhuq1m"
[node name="BGSprite2D" parent="Ground" index="1"] [node name="BGSprite2D" parent="Ground" index="2"]
position = Vector2(0, -3) position = Vector2(0, -3)
texture = ExtResource("2_ow3ya") texture = ExtResource("2_ow3ya")
offset = Vector2(0, -155) offset = Vector2(0, -155)
@ -637,7 +636,7 @@ range_layer_max = 2
texture = ExtResource("4_6ffae") texture = ExtResource("4_6ffae")
offset = Vector2(601.5, -0.5) offset = Vector2(601.5, -0.5)
[node name="MainPlayer" parent="Ground" index="4"] [node name="MainPlayer" parent="Ground" index="5"]
modulate = Color(0.931897, 0.931897, 0.931897, 1) modulate = Color(0.931897, 0.931897, 0.931897, 1)
position = Vector2(1575, 91) position = Vector2(1575, 91)
character = "小小蝶" character = "小小蝶"
@ -727,7 +726,7 @@ offset = Vector2(0, -159)
[node name="PlayerLine2D" parent="Ground/ParallaxForeground" index="2"] [node name="PlayerLine2D" parent="Ground/ParallaxForeground" index="2"]
points = PackedVector2Array(37, 150, 4000, 150) points = PackedVector2Array(37, 150, 4000, 150)
[node name="DirectionalLight2D" parent="Ground" index="7"] [node name="DirectionalLight2D" parent="Ground" index="8"]
visible = false visible = false
[node name="书店外" type="Node2D" parent="Ground"] [node name="书店外" type="Node2D" parent="Ground"]

View File

@ -27,6 +27,8 @@ func _ready() -> void:
func _on_ground_ready() -> void: func _on_ground_ready() -> void:
# 不显示玩家,锁定玩家移动
SceneManager.freeze_player(0)
main_character = $"../DeployLayer/车夫与吕萍" main_character = $"../DeployLayer/车夫与吕萍"
footstep_sfx = $"黄包车Sfx" footstep_sfx = $"黄包车Sfx"
chapter_sfx = $chapter_sfx chapter_sfx = $chapter_sfx

View File

@ -179,7 +179,7 @@ mode = "场景背景音"
"感应玩家操作" = false "感应玩家操作" = false
metadata/_custom_type_script = "uid://rq6w1vuhuq1m" metadata/_custom_type_script = "uid://rq6w1vuhuq1m"
[node name="BGSprite2D" parent="Ground" index="1"] [node name="BGSprite2D" parent="Ground" index="2"]
position = Vector2(-12, 2) position = Vector2(-12, 2)
texture = ExtResource("8_yajus") texture = ExtResource("8_yajus")
offset = Vector2(-4, -627) offset = Vector2(-4, -627)
@ -538,15 +538,13 @@ position = Vector2(-59, 48)
[node name="CollisionShape2D" type="CollisionShape2D" parent="Ground/AmbientLayer/路灯序列2/路灯9/Area2D"] [node name="CollisionShape2D" type="CollisionShape2D" parent="Ground/AmbientLayer/路灯序列2/路灯9/Area2D"]
shape = SubResource("RectangleShape2D_jd8t2") shape = SubResource("RectangleShape2D_jd8t2")
[node name="MainPlayer" parent="Ground" index="4"] [node name="MainPlayer" parent="Ground" index="5"]
visible = false visible = false
position = Vector2(26, 118) position = Vector2(26, 118)
catty_light_energy = 1.0 catty_light_energy = 1.0
character = "小小蝶" character = "小小蝶"
action_locked = true
action_freezed = true
[node name="CameraFocusMarker" parent="Ground" index="5" node_paths=PackedStringArray("focusing_node")] [node name="CameraFocusMarker" parent="Ground" index="6" node_paths=PackedStringArray("focusing_node")]
focusing_node = NodePath("../DeployLayer/车夫与吕萍") focusing_node = NodePath("../DeployLayer/车夫与吕萍")
force_offset = Vector2(50, -48) force_offset = Vector2(50, -48)

View File

@ -63,6 +63,14 @@ func _oneshot_wind():
$"冷飕飕Sfx".play() $"冷飕飕Sfx".play()
func _on_wind_finished():
set_data("first_enter", true)
%MainPlayer.hide_sprite = false
wind_blows.visible = false
# 使用气泡文字
SceneManager.pop_os_with_str("c02_冷飕飕的", false, true)
func xiaochan_disappear(): func xiaochan_disappear():
var xc = $"../DeployLayer/Ambush小蝉闪现/小蝉" as AnimatedSprite2D var xc = $"../DeployLayer/Ambush小蝉闪现/小蝉" as AnimatedSprite2D
xc.play() xc.play()
@ -79,14 +87,6 @@ func _on_flyer_exit(arg):
SceneManager.pop_debug_dialog_info("程序", "发放 steam 成就") SceneManager.pop_debug_dialog_info("程序", "发放 steam 成就")
func _on_wind_finished():
set_data("first_enter", true)
%MainPlayer.hide_sprite = false
wind_blows.visible = false
# 使用气泡文字
SceneManager.pop_os_with_str("c02_冷飕飕的", false, true)
func lumber_interacted(): func lumber_interacted():
SceneManager.call_deferred("enable_prop_item", "prop_火柴") SceneManager.call_deferred("enable_prop_item", "prop_火柴")
SceneManager.get_inspector().quit_and_hidden.connect(_on_inspector_quit, CONNECT_ONE_SHOT) SceneManager.get_inspector().quit_and_hidden.connect(_on_inspector_quit, CONNECT_ONE_SHOT)
@ -104,7 +104,6 @@ func _on_blink_finished(blink_sprite):
func _on_music_box_exited(_arg): func _on_music_box_exited(_arg):
SceneManager.release_player()
if 5 <= ArchiveManager.get_global_value("c02_musicbox_stage"): if 5 <= ArchiveManager.get_global_value("c02_musicbox_stage"):
_display_paper_man(false) _display_paper_man(false)
# _display_paper_man(true) # _display_paper_man(true)
@ -127,14 +126,6 @@ func _on_try_exit():
SceneManager.release_player() SceneManager.release_player()
func display_music_box():
# 展示八音盒
music_box.visible = true
SceneManager.freeze_player(0)
# TODO 打开音效
SceneManager.pop_debug_dialog_info("音效", "显示八音盒")
func check_if_show_shoes(): func check_if_show_shoes():
# 不论是否推出,都需要 enable 调整为 false # 不论是否推出,都需要 enable 调整为 false
$"../DeployLayer/Ambush推小鞋子".enabled = false $"../DeployLayer/Ambush推小鞋子".enabled = false

View File

@ -73,7 +73,7 @@ script = ExtResource("5_36l5t")
autoplay_group = &"c02_楼道1" autoplay_group = &"c02_楼道1"
metadata/_custom_type_script = "uid://cpejxlfni6n52" metadata/_custom_type_script = "uid://cpejxlfni6n52"
[node name="BGSprite2D" parent="Ground" index="1"] [node name="BGSprite2D" parent="Ground" index="2"]
self_modulate = Color(0.831373, 0.886275, 0.956863, 1) self_modulate = Color(0.831373, 0.886275, 0.956863, 1)
position = Vector2(-1, 0) position = Vector2(-1, 0)
scale = Vector2(0.5, 0.5) scale = Vector2(0.5, 0.5)
@ -245,14 +245,14 @@ texture = SubResource("GradientTexture2D_fvldj")
position = Vector2(880, 121) position = Vector2(880, 121)
texture = SubResource("GradientTexture2D_fvldj") texture = SubResource("GradientTexture2D_fvldj")
[node name="MainPlayer" parent="Ground" index="4"] [node name="MainPlayer" parent="Ground" index="5"]
position = Vector2(53, 98) position = Vector2(53, 98)
facing_direction = Vector2(1, 0) facing_direction = Vector2(1, 0)
[node name="PlayerLine2D" parent="Ground/ParallaxForeground" index="2"] [node name="PlayerLine2D" parent="Ground/ParallaxForeground" index="2"]
points = PackedVector2Array(37, 150, 670, 150) points = PackedVector2Array(37, 150, 670, 150)
[node name="DirectionalLight2D" parent="Ground" index="7"] [node name="DirectionalLight2D" parent="Ground" index="8"]
visible = false visible = false
energy = 0.8 energy = 0.8
blend_mode = 1 blend_mode = 1

View File

@ -247,7 +247,7 @@ func bully_end():
SceneManager.release_player() SceneManager.release_player()
# #TODO 小猫玩具微亮 # #TODO 小猫玩具微亮
# SceneManager.pop_debug_dialog_info("美术", "手中小猫玩具微亮") # SceneManager.pop_debug_dialog_info("美术", "手中小猫玩具微亮")
SceneManager.pop_os_with_str("c02_霸凌救小蝉开始", true, true) SceneManager.pop_os_with_str("c02_霸凌救小蝉开始")
# 准备好点火 # 准备好点火
ArchiveManager.set_global_entry("c02_ready_to_fire", true) ArchiveManager.set_global_entry("c02_ready_to_fire", true)
GlobalFunctor.c02_fire_count_down_try_start() GlobalFunctor.c02_fire_count_down_try_start()

View File

@ -304,7 +304,7 @@ script = ExtResource("6_lq23y")
autoplay_group = &"c02_楼道2" autoplay_group = &"c02_楼道2"
metadata/_custom_type_script = "uid://cpejxlfni6n52" metadata/_custom_type_script = "uid://cpejxlfni6n52"
[node name="BGSprite2D" parent="Ground" index="1"] [node name="BGSprite2D" parent="Ground" index="2"]
light_mask = 5 light_mask = 5
texture = ExtResource("3_sqv8l") texture = ExtResource("3_sqv8l")
@ -496,6 +496,7 @@ hook_os_key = "c02_院子_要下雨"
position = Vector2(809, 75) position = Vector2(809, 75)
sign_mark_offset = Vector2(0, -16.88) sign_mark_offset = Vector2(0, -16.88)
enabled = false enabled = false
action_key = 4
prop_key = "prop_小鞋子2" prop_key = "prop_小鞋子2"
[node name="Sprite2D" type="Sprite2D" parent="Ground/DeployLayer/Pickable小鞋子"] [node name="Sprite2D" type="Sprite2D" parent="Ground/DeployLayer/Pickable小鞋子"]
@ -598,7 +599,7 @@ position = Vector2(2037, 67)
sprite_frames = ExtResource("4_gd6xp") sprite_frames = ExtResource("4_gd6xp")
animation = &"疯子看井" animation = &"疯子看井"
frame_progress = 0.298829 frame_progress = 0.298829
walk_to_edge_width = -1.0 snap_to_edge = false
action_key = 3 action_key = 3
height = 49.11 height = 49.11
collision_width_and_x = Vector2(37.08, 0) collision_width_and_x = Vector2(37.08, 0)
@ -943,7 +944,7 @@ energy = 1.2
range_item_cull_mask = 4 range_item_cull_mask = 4
texture = SubResource("GradientTexture2D_plfv5") texture = SubResource("GradientTexture2D_plfv5")
[node name="MainPlayer" parent="Ground" index="4"] [node name="MainPlayer" parent="Ground" index="5"]
position = Vector2(2128, 93) position = Vector2(2128, 93)
facing_direction = Vector2(1, 0) facing_direction = Vector2(1, 0)
@ -963,7 +964,7 @@ scale = Vector2(1.08, 1.08)
[node name="PlayerLine2D" parent="Ground/ParallaxForeground" index="2"] [node name="PlayerLine2D" parent="Ground/ParallaxForeground" index="2"]
points = PackedVector2Array(37, 150, 2250, 150) points = PackedVector2Array(37, 150, 2250, 150)
[node name="DirectionalLight2D" parent="Ground" index="7"] [node name="DirectionalLight2D" parent="Ground" index="8"]
visible = false visible = false
energy = 0.6 energy = 0.6
blend_mode = 1 blend_mode = 1

View File

@ -33,8 +33,8 @@ func _on_little_hand_first_interacted() -> void:
# 9 小手交互,吓摔倒 # 9 小手交互,吓摔倒
little_hand.enabled = false little_hand.enabled = false
var duration = 3.0 var duration = 3.0
SceneManager.pop_os_with_str(tr("c02_小手出现摔倒"), false, false)
SceneManager.freeze_player(duration, 9) SceneManager.freeze_player(duration, 9)
SceneManager.pop_os_with_str(tr("c02_小手出现摔倒"), false, false)
get_tree().create_timer(1.5).timeout.connect($"Sfx摔倒".play) get_tree().create_timer(1.5).timeout.connect($"Sfx摔倒".play)
await get_tree().create_timer(duration).timeout await get_tree().create_timer(duration).timeout
SceneManager.release_player() SceneManager.release_player()

View File

@ -50,7 +50,7 @@ script = ExtResource("5_g8amr")
autoplay_group = &"c02_房间里1" autoplay_group = &"c02_房间里1"
metadata/_custom_type_script = "uid://cpejxlfni6n52" metadata/_custom_type_script = "uid://cpejxlfni6n52"
[node name="BGSprite2D" parent="Ground" index="1"] [node name="BGSprite2D" parent="Ground" index="2"]
light_mask = 5 light_mask = 5
position = Vector2(47, 2) position = Vector2(47, 2)
texture = ExtResource("3_66gue") texture = ExtResource("3_66gue")
@ -121,7 +121,7 @@ offset_bottom = -19.0
[node name="小手讨东西" parent="Ground/DeployLayer" index="7" instance=ExtResource("10_a43aq")] [node name="小手讨东西" parent="Ground/DeployLayer" index="7" instance=ExtResource("10_a43aq")]
position = Vector2(295, -6) position = Vector2(295, -6)
[node name="MainPlayer" parent="Ground" index="4"] [node name="MainPlayer" parent="Ground" index="5"]
position = Vector2(447, 98) position = Vector2(447, 98)
facing_direction = Vector2(-1, 0) facing_direction = Vector2(-1, 0)
@ -133,7 +133,7 @@ texture = ExtResource("6_tio43")
[node name="PlayerLine2D" parent="Ground/ParallaxForeground" index="2"] [node name="PlayerLine2D" parent="Ground/ParallaxForeground" index="2"]
points = PackedVector2Array(70, 150, 495, 150) points = PackedVector2Array(70, 150, 495, 150)
[node name="DirectionalLight2D" parent="Ground" index="7"] [node name="DirectionalLight2D" parent="Ground" index="8"]
visible = false visible = false
energy = 0.9 energy = 0.9
blend_mode = 1 blend_mode = 1

View File

@ -874,7 +874,7 @@ bus = &"game_sfx"
script = ExtResource("4_2e08x") script = ExtResource("4_2e08x")
metadata/_custom_type_script = "uid://rq6w1vuhuq1m" metadata/_custom_type_script = "uid://rq6w1vuhuq1m"
[node name="BGSprite2D" parent="Ground" index="1"] [node name="BGSprite2D" parent="Ground" index="2"]
light_mask = 5 light_mask = 5
position = Vector2(0, -2) position = Vector2(0, -2)
texture = ExtResource("3_och2w") texture = ExtResource("3_och2w")
@ -1143,7 +1143,7 @@ texture = ExtResource("37_osg51")
collision_width_and_x = Vector2(150, 0) collision_width_and_x = Vector2(150, 0)
hook_method = "glimpse_hide_out" hook_method = "glimpse_hide_out"
[node name="MainPlayer" parent="Ground" index="4"] [node name="MainPlayer" parent="Ground" index="5"]
position = Vector2(63, 95) position = Vector2(63, 95)
catty_light_energy = 0.5 catty_light_energy = 0.5
facing_direction = Vector2(1, 0) facing_direction = Vector2(1, 0)
@ -1156,7 +1156,7 @@ texture = ExtResource("5_26mqt")
[node name="PlayerLine2D" parent="Ground/ParallaxForeground" index="2"] [node name="PlayerLine2D" parent="Ground/ParallaxForeground" index="2"]
points = PackedVector2Array(37, 150, 900, 150) points = PackedVector2Array(37, 150, 900, 150)
[node name="DirectionalLight2D" parent="Ground" index="7"] [node name="DirectionalLight2D" parent="Ground" index="8"]
visible = false visible = false
energy = 0.9 energy = 0.9
blend_mode = 1 blend_mode = 1

View File

@ -18,7 +18,7 @@ func _on_ground_ready() -> void:
func _intro(): func _intro():
SceneManager.lock_player() SceneManager.get_lock().lock_all()
# var player = SceneManager.get_player() as MainPlayer # var player = SceneManager.get_player() as MainPlayer
var player = %MainPlayer as MainPlayer var player = %MainPlayer as MainPlayer
player.hide_sprite = true player.hide_sprite = true
@ -38,5 +38,5 @@ func _intro():
layer.disable_crawl = false layer.disable_crawl = false
anim.visible = false anim.visible = false
player.hide_sprite = false player.hide_sprite = false
SceneManager.unlock_player() SceneManager.get_lock().unlock_all()
SceneManager.pop_center_notification(tr("ui_boxcat_press_s")) SceneManager.pop_center_notification(tr("ui_boxcat_press_s"))

View File

@ -32,12 +32,12 @@ script = ExtResource("5_72mc1")
autoplay_group = &"c02_房间里1" autoplay_group = &"c02_房间里1"
metadata/_custom_type_script = "uid://cpejxlfni6n52" metadata/_custom_type_script = "uid://cpejxlfni6n52"
[node name="BGSprite2D" parent="Ground" index="1"] [node name="BGSprite2D" parent="Ground" index="2"]
texture = ExtResource("3_oskpk") texture = ExtResource("3_oskpk")
offset = Vector2(0, -103.7) offset = Vector2(0, -103.7)
[node name="portal_left" parent="Ground/DeployLayer" index="0"] [node name="portal_left" parent="Ground/DeployLayer" index="0"]
position = Vector2(152, 56) position = Vector2(151, 54)
target_scene = "c02_s17" target_scene = "c02_s17"
target_portal = "1" target_portal = "1"
status = "opened" status = "opened"
@ -50,12 +50,12 @@ position = Vector2(211, 3)
sprite_frames = ExtResource("5_ycgng") sprite_frames = ExtResource("5_ycgng")
animation = &"猫钻进盒子" animation = &"猫钻进盒子"
[node name="MainPlayer" parent="Ground" index="4"] [node name="MainPlayer" parent="Ground" index="5"]
position = Vector2(231, 71) position = Vector2(231, 71)
character = "盒子猫" character = "盒子猫"
facing_direction = Vector2(1, 0) facing_direction = Vector2(1, 0)
[node name="CameraFocusMarker" parent="Ground" index="5"] [node name="CameraFocusMarker" parent="Ground" index="6"]
force_offset = Vector2(-20, 0) force_offset = Vector2(-20, 0)
[node name="FGSprite2D" parent="Ground/ParallaxForeground/FGParallaxLayer" index="0"] [node name="FGSprite2D" parent="Ground/ParallaxForeground/FGParallaxLayer" index="0"]
@ -64,7 +64,7 @@ position = Vector2(3584, -7)
[node name="PlayerLine2D" parent="Ground/ParallaxForeground" index="2"] [node name="PlayerLine2D" parent="Ground/ParallaxForeground" index="2"]
points = PackedVector2Array(37, 150, 400, 150) points = PackedVector2Array(37, 150, 400, 150)
[node name="DirectionalLight2D" parent="Ground" index="7"] [node name="DirectionalLight2D" parent="Ground" index="8"]
blend_mode = 1 blend_mode = 1
[node name="盒子猫CanvasLayer" parent="Ground" instance=ExtResource("4_vv3sh")] [node name="盒子猫CanvasLayer" parent="Ground" instance=ExtResource("4_vv3sh")]

View File

@ -91,7 +91,5 @@ unique_name_in_owner = true
unique_name_in_owner = true unique_name_in_owner = true
script = ExtResource("13_l338h") script = ExtResource("13_l338h")
radius = 3.0 radius = 3.0
delay_arrived = 0.1
action_on_arrived = 4 action_on_arrived = 4
delay_after_action = 0.4
metadata/_custom_type_script = "uid://cnt01hiw52bmn" metadata/_custom_type_script = "uid://cnt01hiw52bmn"

View File

@ -184,7 +184,7 @@ func _on_interacted() -> void:
# 7 拿起纸杯 8 监听纸杯 # 7 拿起纸杯 8 监听纸杯
SceneManager.freeze_player(0, 7) SceneManager.freeze_player(0, 7)
await SceneManager.get_player().animation_finished await SceneManager.get_player().animation_finished
SceneManager.freeze_player(0, 8) SceneManager.player_action(8)
SceneManager.pop_debug_dialog_info("音效", "纸杯电话童谣") SceneManager.pop_debug_dialog_info("音效", "纸杯电话童谣")
sfx_bgm.play() sfx_bgm.play()
# 交互时,已经在对话中 # 交互时,已经在对话中

View File

@ -18,7 +18,7 @@
[sub_resource type="RectangleShape2D" id="RectangleShape2D_yatcw"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_yatcw"]
resource_local_to_scene = true resource_local_to_scene = true
size = Vector2(10, 70) size = Vector2(20, 70)
[node name="小手讨东西" type="Sprite2D"] [node name="小手讨东西" type="Sprite2D"]
texture = ExtResource("1_47cqy") texture = ExtResource("1_47cqy")
@ -120,8 +120,6 @@ texture = ExtResource("10_47cqy")
[node name="SignSnapper" type="Marker2D" parent="."] [node name="SignSnapper" type="Marker2D" parent="."]
unique_name_in_owner = true unique_name_in_owner = true
script = ExtResource("15_lr23o") script = ExtResource("15_lr23o")
release_player_on_arrived = false radius = 3.0
delay_arrived = 0.1
action_on_arrived = 4 action_on_arrived = 4
delay_after_action = 0.4
metadata/_custom_type_script = "uid://cnt01hiw52bmn" metadata/_custom_type_script = "uid://cnt01hiw52bmn"