173 lines
5.1 KiB
GDScript
173 lines
5.1 KiB
GDScript
extends AnimatedSprite2D
|
|
|
|
signal before_restart
|
|
|
|
var MOVE_SPEED := 180.0
|
|
const RESET_Y := -300.0
|
|
|
|
@export var mute := false:
|
|
set(val):
|
|
mute = val
|
|
_on_mute_updated()
|
|
@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
|
|
@export var left_static_collision: CollisionShape2D
|
|
@export var right_static_collision: CollisionShape2D
|
|
|
|
@onready var footstep_sfx = $"Sfx2D棺材怪脚步声" as Sfx2D
|
|
@onready var chop_sfx = $"Sfx2D棺材怪切刀" as Sfx2D
|
|
|
|
@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
|
|
|
|
var left_hand_x_offset: float
|
|
var right_hand_x_offset: float
|
|
var chopped_safe_period := false
|
|
var finished := false
|
|
|
|
func _ready() -> void:
|
|
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)
|
|
_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()
|
|
|
|
|
|
# 停止切肉动作, x 对齐到 move_target
|
|
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
|
|
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
|
|
|
|
|
|
var aiming := 0
|
|
const AIMING_DURATION := 2.0
|
|
|
|
|
|
func chop_left(aiming_duration := AIMING_DURATION) -> void:
|
|
if aiming:
|
|
return
|
|
hand_mode = 0
|
|
aiming += 1
|
|
_checkout_hand_animation(false)
|
|
var tween = create_tween()
|
|
if aiming_duration > 0.0:
|
|
tween.tween_property(remote_left_shadow, "scale", Vector2.ONE, aiming_duration)
|
|
tween.tween_callback(left_side_sprite.play)
|
|
tween.tween_property(remote_left_side, "position:y", 0.0, 0.2)
|
|
if aiming_duration <= 0.0:
|
|
tween.parallel().tween_property(remote_left_shadow, "scale", Vector2.ONE, 0.3)
|
|
tween.tween_callback(chop_sfx.play)
|
|
tween.tween_callback(toggle_safe_period.bind(true))
|
|
tween.tween_callback(shake)
|
|
tween.tween_callback(func(): aiming -= 1)
|
|
tween.tween_interval(0.1)
|
|
tween.tween_property(remote_left_shadow, "scale", Vector2.ZERO, 0.4)
|
|
tween.parallel().tween_property(remote_left_side, "position:y", RESET_Y, 0.5)
|
|
tween.tween_callback(toggle_safe_period.bind(false))
|
|
|
|
|
|
func chop_right(aiming_duration := AIMING_DURATION) -> void:
|
|
if aiming:
|
|
return
|
|
hand_mode = 1
|
|
aiming += 1
|
|
_checkout_hand_animation(false)
|
|
var tween = create_tween()
|
|
if aiming_duration > 0.0:
|
|
tween.tween_property(remote_right_shadow, "scale", Vector2.ONE, aiming_duration)
|
|
tween.tween_callback(right_side_sprite.play)
|
|
tween.tween_property(remote_right_side, "position:y", 0.0, 0.2)
|
|
if aiming_duration <= 0.0:
|
|
tween.parallel().tween_property(remote_right_shadow, "scale", Vector2.ONE, 0.3)
|
|
tween.tween_callback(chop_sfx.play)
|
|
tween.tween_callback(toggle_safe_period.bind(true))
|
|
tween.tween_callback(shake)
|
|
tween.tween_callback(func(): aiming -= 1)
|
|
tween.tween_interval(0.1)
|
|
tween.tween_property(remote_right_shadow, "scale", Vector2.ZERO, 0.4)
|
|
tween.parallel().tween_property(remote_right_side, "position:y", RESET_Y, 0.5)
|
|
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
|
|
|
|
|
|
func shake() -> void:
|
|
SceneManager.get_camera_marker().shake_camera(6.0)
|
|
|
|
|
|
func _on_player_chopped(_body) -> void:
|
|
if chopped_safe_period:
|
|
return
|
|
if finished:
|
|
return
|
|
finished = true
|
|
SceneManager.lock_player()
|
|
await SceneManager.player_action(7)
|
|
await Util.wait(1.0)
|
|
SceneManager.unlock_player()
|
|
before_restart.emit()
|
|
# restart
|
|
get_tree().reload_current_scene()
|
|
|
|
|
|
func _physics_process(delta: float) -> 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
|
|
var x = global_position.x
|
|
if chopped_safe_period or abs(target_x - x) < 0.1:
|
|
stop()
|
|
if footstep_sfx.playing:
|
|
footstep_sfx.stop()
|
|
else:
|
|
var speed = MOVE_SPEED
|
|
# if aiming:
|
|
# speed *= 0.6
|
|
global_position.x = move_toward(x, target_x, delta * speed)
|
|
# if Time.get_ticks_msec() % 100 == 0:
|
|
# prints(x, target_x)
|
|
if not footstep_sfx.playing:
|
|
footstep_sfx.play()
|
|
_checkout_hand_animation()
|
|
|
|
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)
|