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

144 lines
3.9 KiB
GDScript3
Raw Normal View History

@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)
# TODO 美术更新
SceneManager.pop_debug_dialog_info("美术", "寻人启事: 飘动迷你版+详情版")
2025-03-09 14:01:51 +00:00
var inspect_texture = preload("res://asset/art/scene/c01/s07_书店外/纸片_正面.png")
SceneManager.get_inspector().pop_prop_inspection("", inspect_texture, true)
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