@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("美术", "寻人启事: 飘动迷你版+详情版") 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