链式 Tween
一个 tween 连续跑四个步骤。tween_callback 让当前步骤在屏幕上亮起,parallel 则把两个属性放进同一个步骤。
上方的编辑器正在运行这个项目。改一行代码,它就会重新加载。
用到的 Godot 类
TweenPolygon2DLine2D
代码
scripts/main.gd
extends Node
const SIZE: Vector2 = Vector2(64, 64)
const START: Vector2 = Vector2(560, 230)
const STEP_TIME: float = 0.55
const BLUE: Color = Color('#8da5f3')
const GREEN: Color = Color('#8eef97')
const STEPS: Array = [
'1 tween_property > position:x',
'2 parallel > position:y + rotation',
'3 parallel > scale + color',
'4 parallel > everything back',
]
var rows: Array[Label] = []
var box: Polygon2D
func _ready() -> void:
_add_background()
_add_label('tween_callback marks each step, parallel runs two at once', Vector2(40, 40), Color('#999999'))
for i in STEPS.size():
rows.append(_add_label(STEPS[i], Vector2(60, 120 + i * 38), Color('#4a5162')))
var route: Line2D = Line2D.new()
route.width = 2.0
route.default_color = Color('#2a2f3d')
route.closed = true
route.add_point(START)
route.add_point(Vector2(1060, START.y))
route.add_point(Vector2(1060, 520))
add_child(route)
box = _make_square(BLUE)
box.position = START
add_child(box)
var facing: Polygon2D = _make_circle(9.0, Color('#12141a'))
facing.position = Vector2(0, -SIZE.y * 0.28)
box.add_child(facing)
var chain: Tween = create_tween().set_loops()
chain.tween_callback(_show_step.bind(0))
chain.tween_property(box, 'position:x', 1060.0, STEP_TIME).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN_OUT)
chain.tween_callback(_show_step.bind(1))
chain.tween_property(box, 'position:y', 520.0, STEP_TIME).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN_OUT)
chain.parallel().tween_property(box, 'rotation', PI, STEP_TIME).as_relative()
chain.tween_callback(_show_step.bind(2))
chain.tween_property(box, 'scale', Vector2(1.9, 1.9), STEP_TIME).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT)
chain.parallel().tween_property(box, 'color', GREEN, STEP_TIME)
chain.tween_callback(_show_step.bind(3))
chain.tween_property(box, 'position', START, STEP_TIME).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_IN_OUT)
chain.parallel().tween_property(box, 'rotation', PI, STEP_TIME).as_relative()
chain.parallel().tween_property(box, 'scale', Vector2.ONE, STEP_TIME)
chain.parallel().tween_property(box, 'color', BLUE, STEP_TIME)
print('one tween, four steps, the highlighted line is the one running')
func _show_step(index: int) -> void:
for i in rows.size():
rows[i].add_theme_color_override('font_color', GREEN if i == index else Color('#4a5162'))
func _add_background() -> void:
var background: ColorRect = ColorRect.new()
background.color = Color('#12141a')
add_child(background)
background.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
func _add_label(text: String, at: Vector2, color: Color) -> Label:
var label: Label = Label.new()
label.text = text
label.position = at
label.add_theme_color_override('font_color', color)
add_child(label)
return label
func _make_circle(radius: float, color: Color) -> Polygon2D:
var points: PackedVector2Array = PackedVector2Array()
for i in 20:
var angle: float = TAU * i / 20
points.append(Vector2(cos(angle), sin(angle)) * radius)
var circle: Polygon2D = Polygon2D.new()
circle.polygon = points
circle.color = color
return circle
func _make_square(color: Color) -> Polygon2D:
var square: Polygon2D = Polygon2D.new()
square.polygon = PackedVector2Array(
[
-SIZE * 0.5,
Vector2(SIZE.x, -SIZE.y) * 0.5,
SIZE * 0.5,
Vector2(-SIZE.x, SIZE.y) * 0.5,
]
)
square.color = color
return square