xiandie/scene/ground/script/c02/追猫猪头怪.gd

220 lines
6.4 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

extends Node2D
# transfer_mode 意味着检测 portal_key然后显示
@export var transfer_mode := true
# 脚步声周期时间
@export var footstep_wait_time := 0.5
# 追击速度
@export var speed := 50
# 转身范围,超过这个范围/在这个范围内不 hidden 都会转身
@export var trun_back_detact_x := 150
# 抓取范围,优先 catch_front 播放 猪头怪抓盒子猫
# 其次 catch_nearby 播放 猪头怪抓盒子猫后段
@export var catch_front_x_range := Vector2(55 - 3, 55 + 3)
@export var catch_nearby_x_range := Vector2(-10, 55)
# 观测范围,在观测范围内进入盒子仍旧会被抓
@export var watching_x := 180
# 允许被抓后重开游戏
var allow_restart_game := true
@onready var sfx_footstep = $SfxFootstep as Sfx2D
@onready var sprite2d = $AnimatedSprite2D as AnimatedSprite2D
# 检测到猫钻进盒子的过程
var cat_hiding_detacted = false
var footstep_timer := Timer.new()
var player
var camera
var catty_canvas_layer
# 运动&检测, 初始为 false
var move_and_detact = false:
set(val):
move_and_detact = val
toggle_footstep_sfx(move_and_detact)
if val and is_node_ready():
sprite2d.play("猪头怪走路")
# 启用的瞬间先执行检测
_physics_process(0.0)
func _ready() -> void:
SceneManager.get_ground().ready.connect(_on_ground_ready)
# 抓盒子猫后,传送回初始场景,跳过其 intro 过程(从纸面逐渐进入黑板粉笔空间)
ArchiveManager.archive.set_global_entry("c02_boxcat_skip_intro", true)
func _on_ground_ready():
player = SceneManager.get_player()
camera = SceneManager.get_camera_marker()
catty_canvas_layer = SceneManager.get_ground().get_node("盒子猫CanvasLayer")
var archive = ArchiveManager.archive as AssembledArchive
var portal = archive.entrance_portal
var chasing_started = ArchiveManager.get_global_value("c02_boxcat_chasing_started", false)
if archive.current_scene == "c02_s13":
# 开始追逐后,禁用二楼两只
if chasing_started and not transfer_mode:
queue_free()
return
elif not chasing_started:
if transfer_mode:
queue_free()
return
if portal == "left" and name != &"追猫猪头怪_左侧":
queue_free()
return
if portal != "left" and name != &"追猫猪头怪_右侧":
queue_free()
return
# c02_s13 开始追逐; call_deferred 延时设置
ArchiveManager.archive.set_global_entry.call_deferred(
"c02_boxcat_chasing_started", true
)
elif not chasing_started:
# 如果没有开始追逐,且不是 13 号场景(二楼),则销毁
queue_free()
return
# TODO 高度对齐
position.y = player.position.y
# 脚步声 timer
footstep_timer.one_shot = false
footstep_timer.autostart = false
footstep_timer.wait_time = footstep_wait_time
footstep_timer.timeout.connect(_on_footstep_timer_timeout)
add_child(footstep_timer)
if transfer_mode:
visible = false
var portal_node = (
SceneManager.get_ground().get_node("DeployLayer/portal_" + portal) as Portal2D
)
global_position.x = portal_node.global_position.x
# 禁用传送过来的 portal 3s
_disable_portal_a_few_seconds(portal_node)
# 3 秒后传送
get_tree().create_timer(1.0).timeout.connect(_do_transfer)
if GlobalConfig.DEBUG:
print("猪头怪 Transfer to: " + portal)
else:
move_and_detact = true
var footstep_count := 0
func _on_footstep_timer_timeout() -> void:
sfx_footstep.play()
footstep_count += 1
if footstep_count % 2 == 0:
# shake camera
camera.shake_camera(4.0, 5.0)
# 启用/禁用脚步声
func toggle_footstep_sfx(play := true):
if play:
footstep_timer.start()
else:
footstep_timer.stop()
# 禁用传送过来的 portal 3s
func _disable_portal_a_few_seconds(portal_node: Portal2D):
portal_node.enabled = false
await create_tween().tween_interval(3.0).finished
portal_node.enabled = true
func _do_transfer():
if player.global_position.x > global_position.x:
_toggle_flip_h()
modulate.a = 0.0
visible = true
var tween = create_tween()
tween.tween_property(self, "modulate:a", 1.0, 2.0)
await tween.finished
move_and_detact = true
# 转身追击
func turn_back():
move_and_detact = false
# 呼吸一帧,然后转身
sprite2d.play("猪头怪呼吸")
await sprite2d.animation_looped
_toggle_flip_h()
move_and_detact = true
func _toggle_flip_h():
sprite2d.flip_h = !sprite2d.flip_h
sprite2d.offset.x = -sprite2d.offset.x
# 抓小猫
func do_catch(front: bool):
move_and_detact = false
SceneManager.freeze_player(0)
# 抓小猫时 lock palyer
SceneManager.lock_player()
# 呼吸一帧,然后抓取
sprite2d.play("猪头怪呼吸")
await sprite2d.animation_looped
player.hide_sprite = true
if front:
# 优先 catch_front 播放 猪头怪抓盒子猫
sprite2d.play("猪头怪抓盒子猫")
else:
# 其次 catch_nearby 播放 猪头怪抓盒子猫后段
sprite2d.play("猪头怪抓盒子猫后段")
# TODO 音效
SceneManager.pop_debug_dialog_info("音效", "抓取过程。 从捡小猫开始=" + str(front))
await sprite2d.animation_finished
# 等待动画播放后秒,再检查是否允许重开游戏
if allow_restart_game:
SceneManager.get_ground_loader().transition_to_scene("c02_s12", "left")
func _physics_process(delta: float) -> void:
if not move_and_detact:
return
var player_pos = player.global_position
# 玩家到猪头怪面前的距离(有符号)
var signed_x_diff = player_pos.x - global_position.x
# 默认向左, flip_h 后向右
if not sprite2d.flip_h:
signed_x_diff *= -1
# 猫是否在盒子里
var is_cat_hideen = catty_canvas_layer.crawling
# 检查隐藏小猫,在观测范围内进入盒子仍旧会被抓
if signed_x_diff < 0 or signed_x_diff > watching_x:
# 如果离开一定范围,重置 cat_hiding_detacted
cat_hiding_detacted = false
else:
cat_hiding_detacted = cat_hiding_detacted or not is_cat_hideen
# 检查是否抓取
if cat_hiding_detacted or not is_cat_hideen:
if signed_x_diff > catch_front_x_range.x and signed_x_diff < catch_front_x_range.y:
# 优先 catch_front 播放 猪头怪抓盒子猫
do_catch(true)
return
elif signed_x_diff > catch_nearby_x_range.x and signed_x_diff < catch_nearby_x_range.y:
# 其次 catch_nearby 播放 猪头怪抓盒子猫后段
do_catch(false)
return
# 检查是否需要转身,超过这个范围/在这个范围内不 hidden 都会转身
if signed_x_diff < 0 and trun_back_detact_x < -signed_x_diff:
turn_back()
return
# 更新追击位置
var mov_delta = speed * delta
if not sprite2d.flip_h:
mov_delta *= -1
global_position.x += mov_delta