xiandie/scene/ground/script/c01/s12_飘动的寻人启事.gd

141 lines
3.7 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.

@tool
extends Node2D
@export var velocity := 0.1
@export var area_size := Vector2(400, 50):
set(val):
area_size = val
queue_redraw()
@export var gizmo_outline_color := Color(0.5, 0.3, 0.4, 0.8):
set(val):
gizmo_outline_color = val
queue_redraw()
@onready var remote_node := $Node2D
@onready var remote_sprite := %Sprite2D
@onready var sign_mark := %Sign as Sign
var interacted_x = -10000
func _draw() -> void:
if Engine.is_editor_hint():
# draw gizmo
var area_rect = Rect2(Vector2.ZERO, area_size)
# 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)
# 最多保持 4 个点; 先生成两个在左侧,再生成两个在右侧,然后再回到左侧,以此循环,形成左右摇摆的闭合路径
var bezier_points = []
var current_position = Vector2.ZERO
var weight := 0.0
func _ready() -> void:
if Engine.is_editor_hint():
return
# init points
for i in range(4):
bezier_points.append(_rand_point())
sign_mark.enabled = visible
sign_mark.interacted.connect(_on_interacted)
visibility_changed.connect(_on_visibility_changed)
interacted_x = ArchiveManager.archive.ground_archive().get_value(
name, "interacted_x", interacted_x
)
if interacted_x > -10000:
remote_node.position = Vector2(interacted_x, area_size.y)
remote_sprite.material = null
func _on_visibility_changed() -> void:
sign_mark.enabled = visible
func _new_point() -> void:
# remove the first point
bezier_points.remove_at(0)
# add a new point
bezier_points.append(_rand_point())
func _on_interacted() -> void:
if interacted_x == -10000:
interacted_x = remote_node.position.x
remote_node.position.y = area_size.y
remote_sprite.material = null
ArchiveManager.archive.ground_archive().set_pair(name, "interacted_x", interacted_x)
if GlobalConfig.DEBUG:
print("interacted_x:", interacted_x)
# SceneManager.enable_prop_item("c01_吕萍_记笔记_right")
var _generated_points = -1
func _rand_point() -> Vector2:
_generated_points += 1
# upleft,mid,downright,upright,mid,downleft,...
match _generated_points % 6:
0:
_generated_points = 0
# upleft
return Vector2(
randf_range(0, area_size.x * 0.3), randf_range(area_size.y * 0.6, area_size.y)
)
1:
# upleft to center
return Vector2(
randf_range(area_size.x * 0.4, area_size.x * 0.6),
randf_range(area_size.y * 0.3, area_size.y * 0.7)
)
2:
# center to downright
return Vector2(
randf_range(area_size.x * 0.7, area_size.x), randf_range(0, area_size.y * 0.4)
)
3:
# downright to upright
return Vector2(
randf_range(area_size.x * 0.7, area_size.x),
randf_range(area_size.y * 0.6, area_size.y)
)
4:
# upright to center
return Vector2(
randf_range(area_size.x * 0.4, area_size.x * 0.6),
randf_range(area_size.y * 0.3, area_size.y * 0.7)
)
_:
# center to downleft
return Vector2(randf_range(0, area_size.x * 0.3), randf_range(0, area_size.y * 0.4))
# 从 bezier_points 中取出 4 个点,然后进行贝塞尔曲线插值
# 设置到 remote_transform 的 position 与 rotation
# 速度为 velocity权重为 weight
func _process(delta: float) -> void:
if Engine.is_editor_hint() or not visible or interacted_x > -10000:
return
weight += velocity * delta
if weight >= 1.0:
weight = 0.0
_new_point()
var p0 = bezier_points[0]
var p1 = bezier_points[1]
var p2 = bezier_points[2]
var p3 = bezier_points[3]
var p = p1.cubic_interpolate(p2, p0, p3, weight)
# var p = p1.bezier_interpolate(p0, p3, p2, weight)
remote_node.position = p
# bezier 插值获得角度
remote_sprite.rotation = lerp_angle(remote_sprite.rotation, p1.angle_to(p2), delta)
remote_sprite.skew = -remote_sprite.rotation * 0.5