xiandie/scene/ground/script/c03/胖子游戏棺材怪.gd

182 lines
5.3 KiB
GDScript3
Raw Normal View History

2025-07-31 16:13:58 +00:00
extends AnimatedSprite2D
2025-08-04 16:01:54 +00:00
signal before_restart
2025-08-05 09:38:56 +00:00
# 在玩家移速基础上增加的速度
var MOVE_PLUS_SPEED := 300.0
2025-07-31 18:18:51 +00:00
const RESET_Y := -300.0
2025-07-31 16:13:58 +00:00
2025-07-31 18:18:51 +00:00
@export var mute := false:
2025-07-31 16:13:58 +00:00
set(val):
mute = val
2025-07-31 18:18:51 +00:00
_on_mute_updated()
2025-07-31 16:13:58 +00:00
@export var move_target: Node2D
@export_enum("left", "right") var hand_mode := 0
@export var left_side_sprite: AnimatedSprite2D
@export var right_side_sprite: AnimatedSprite2D
@export var left_area: Area2D
@export var right_area: Area2D
2025-07-31 18:18:51 +00:00
@export var left_static_collision: CollisionShape2D
@export var right_static_collision: CollisionShape2D
2025-07-31 16:13:58 +00:00
@onready var footstep_sfx = $"Sfx2D棺材怪脚步声" as Sfx2D
2025-08-07 10:28:19 +00:00
@onready var chop_sfx = $"Sfx2D棺材怪切刀" as Sfx
2025-07-31 16:13:58 +00:00
@onready var remote_left_side = $"左侧" as RemoteTransform2D
@onready var remote_right_side = $"右侧" as RemoteTransform2D
@onready var remote_left_shadow = $"左落点" as RemoteTransform2D
@onready var remote_right_shadow = $"右落点" as RemoteTransform2D
2025-08-05 09:38:56 +00:00
var player: MainPlayer
2025-07-31 16:13:58 +00:00
var left_hand_x_offset: float
var right_hand_x_offset: float
2025-07-31 18:18:51 +00:00
var chopped_safe_period := false
2025-08-04 16:01:54 +00:00
var finished := false
2025-07-31 16:13:58 +00:00
2025-08-05 09:38:56 +00:00
2025-07-31 16:13:58 +00:00
func _ready() -> void:
2025-08-05 09:38:56 +00:00
await SceneManager.ground_ready
player = SceneManager.get_player()
2025-07-31 16:13:58 +00:00
left_hand_x_offset = remote_left_shadow.position.x
right_hand_x_offset = remote_right_shadow.position.x
left_area.body_entered.connect(_on_player_chopped)
right_area.body_entered.connect(_on_player_chopped)
2025-07-31 18:18:51 +00:00
_on_mute_updated()
func _on_mute_updated() -> void:
if not is_node_ready():
return
if mute:
footstep_sfx.volume_db = -100
else:
footstep_sfx.reset_volumn_to_default()
2025-07-31 16:13:58 +00:00
# 停止切肉动作, x 对齐到 move_target
2025-08-04 16:01:54 +00:00
func refresh_position() -> void:
var target_x = move_target.global_position.x
if hand_mode == 0:
target_x -= left_hand_x_offset
else:
target_x -= right_hand_x_offset
global_position.x = target_x
2025-07-31 16:13:58 +00:00
remote_right_side.position.y = RESET_Y
remote_left_side.position.y = RESET_Y
remote_left_shadow.scale = Vector2.ZERO
remote_right_shadow.scale = Vector2.ZERO
2025-08-04 16:01:54 +00:00
var aiming := 0
const AIMING_DURATION := 2.0
func chop_left(aiming_duration := AIMING_DURATION) -> void:
if aiming:
return
2025-07-31 18:18:51 +00:00
hand_mode = 0
2025-08-04 16:01:54 +00:00
aiming += 1
2025-07-31 18:18:51 +00:00
_checkout_hand_animation(false)
2025-07-31 16:13:58 +00:00
var tween = create_tween()
2025-07-31 18:18:51 +00:00
if aiming_duration > 0.0:
tween.tween_property(remote_left_shadow, "scale", Vector2.ONE, aiming_duration)
tween.tween_callback(left_side_sprite.play)
2025-08-05 09:38:56 +00:00
tween.tween_property(remote_left_side, "position:y", 0.0, 0.15)
2025-07-31 18:18:51 +00:00
if aiming_duration <= 0.0:
2025-08-04 16:01:54 +00:00
tween.parallel().tween_property(remote_left_shadow, "scale", Vector2.ONE, 0.3)
2025-07-31 16:13:58 +00:00
tween.tween_callback(chop_sfx.play)
2025-07-31 18:18:51 +00:00
tween.tween_callback(toggle_safe_period.bind(true))
2025-07-31 16:13:58 +00:00
tween.tween_callback(shake)
2025-08-04 16:01:54 +00:00
tween.tween_callback(func(): aiming -= 1)
tween.tween_interval(0.1)
2025-08-05 09:38:56 +00:00
tween.tween_property(remote_left_shadow, "scale", Vector2(0.2, 0.2), 0.2)
tween.parallel().tween_property(remote_left_side, "position:y", RESET_Y, 0.4)
2025-07-31 18:18:51 +00:00
tween.tween_callback(toggle_safe_period.bind(false))
2025-08-04 16:01:54 +00:00
func chop_right(aiming_duration := AIMING_DURATION) -> void:
if aiming:
return
2025-07-31 18:18:51 +00:00
hand_mode = 1
2025-08-04 16:01:54 +00:00
aiming += 1
2025-07-31 18:18:51 +00:00
_checkout_hand_animation(false)
2025-07-31 16:13:58 +00:00
var tween = create_tween()
2025-07-31 18:18:51 +00:00
if aiming_duration > 0.0:
tween.tween_property(remote_right_shadow, "scale", Vector2.ONE, aiming_duration)
tween.tween_callback(right_side_sprite.play)
2025-08-05 09:38:56 +00:00
tween.tween_property(remote_right_side, "position:y", 0.0, 0.15)
2025-07-31 18:18:51 +00:00
if aiming_duration <= 0.0:
2025-08-04 16:01:54 +00:00
tween.parallel().tween_property(remote_right_shadow, "scale", Vector2.ONE, 0.3)
2025-07-31 16:13:58 +00:00
tween.tween_callback(chop_sfx.play)
2025-07-31 18:18:51 +00:00
tween.tween_callback(toggle_safe_period.bind(true))
2025-07-31 16:13:58 +00:00
tween.tween_callback(shake)
2025-08-04 16:01:54 +00:00
tween.tween_callback(func(): aiming -= 1)
tween.tween_interval(0.1)
2025-08-06 15:54:49 +00:00
tween.tween_property(remote_right_shadow, "scale", Vector2(0.2, 0.2), 0.5)
2025-08-05 09:38:56 +00:00
tween.parallel().tween_property(remote_right_side, "position:y", RESET_Y, 0.4)
2025-07-31 18:18:51 +00:00
tween.tween_callback(toggle_safe_period.bind(false))
func toggle_safe_period(safe: bool) -> void:
chopped_safe_period = safe
left_static_collision.disabled = not safe
right_static_collision.disabled = not safe
2025-07-31 16:13:58 +00:00
func shake() -> void:
2025-07-31 18:18:51 +00:00
SceneManager.get_camera_marker().shake_camera(6.0)
2025-07-31 16:13:58 +00:00
func _on_player_chopped(_body) -> void:
2025-07-31 18:18:51 +00:00
if chopped_safe_period:
return
2025-08-05 09:38:56 +00:00
if finished:
2025-08-04 16:01:54 +00:00
return
finished = true
2025-07-31 16:13:58 +00:00
SceneManager.lock_player()
await SceneManager.player_action(7)
await Util.wait(1.0)
SceneManager.unlock_player()
2025-08-04 16:01:54 +00:00
before_restart.emit()
2025-07-31 16:13:58 +00:00
# restart
get_tree().reload_current_scene()
func _physics_process(delta: float) -> void:
2025-08-05 09:38:56 +00:00
if not player:
return
2025-07-31 16:13:58 +00:00
var target_x = move_target.global_position.x
2025-07-31 18:18:51 +00:00
if hand_mode == 0:
target_x -= left_hand_x_offset
else:
target_x -= right_hand_x_offset
2025-07-31 16:13:58 +00:00
var x = global_position.x
2025-07-31 18:18:51 +00:00
if chopped_safe_period or abs(target_x - x) < 0.1:
2025-07-31 16:13:58 +00:00
stop()
if footstep_sfx.playing:
footstep_sfx.stop()
else:
2025-08-05 09:38:56 +00:00
var speed = MOVE_PLUS_SPEED
speed += abs(player.velocity.x)
if aiming:
2025-08-06 15:54:49 +00:00
speed *= 0.6
2025-07-31 18:18:51 +00:00
global_position.x = move_toward(x, target_x, delta * speed)
# if Time.get_ticks_msec() % 100 == 0:
# prints(x, target_x)
2025-07-31 16:13:58 +00:00
if not footstep_sfx.playing:
footstep_sfx.play()
2025-07-31 18:18:51 +00:00
_checkout_hand_animation()
2025-08-05 09:38:56 +00:00
2025-07-31 18:18:51 +00:00
func _checkout_hand_animation(is_move := true) -> void:
var target_animation = ""
if is_move:
target_animation = "棺材怪移动" if hand_mode == 0 else "棺材怪移动右"
else:
target_animation = "棺材怪左砍" if hand_mode == 0 else "棺材怪右砍"
if not is_playing() or animation != target_animation:
if hand_mode == 0:
play(target_animation)
else:
play(target_animation)