Mola amortecida

Uma mola criticamente amortecida e um seguidor com lerp rastreando o mesmo alvo em movimento. A mola acompanha, o lerp fica para trás.

O editor acima está rodando este projeto. Mude uma linha e ele recarrega.

Classes do Godot usadas

Polygon2DLine2DLabel

O código

scripts/main.gd
extends Node

const STIFFNESS: float = 160.0
const LERP_WEIGHT: float = 1.6
const TARGET_SPEED: float = 1.6
const TRACE_POINTS: int = 150
const TRACE_STEP: float = 3.0
const SIZE: Vector2 = Vector2(34, 34)

var damping: float = 2.0 * sqrt(STIFFNESS)
var target_marker: Polygon2D
var spring_marker: Polygon2D
var lerp_marker: Polygon2D
var target_trace: Line2D
var spring_trace: Line2D
var lerp_trace: Line2D
var guide: Line2D
var row_target: float = 0.0
var row_spring: float = 0.0
var row_lerp: float = 0.0
var spring_x: float = 0.0
var spring_velocity: float = 0.0
var lerp_x: float = 0.0
var center_x: float = 0.0
var amplitude: float = 0.0
var elapsed: float = 0.0


func _ready() -> void:
	_add_background()

	var view: Vector2 = get_viewport().get_visible_rect().size
	center_x = view.x * 0.5
	amplitude = view.x * 0.29
	spring_x = center_x
	lerp_x = center_x
	row_target = view.y * 0.17
	row_spring = row_target + 44.0
	row_lerp = row_spring + 44.0

	guide = Line2D.new()
	guide.width = 2.0
	guide.default_color = Color('#2a2f3d')
	guide.points = PackedVector2Array([Vector2(0, row_target - 40), Vector2(0, view.y - 40)])
	guide.position.x = center_x
	add_child(guide)

	target_trace = _add_trace(Color('#f3d48d'))
	spring_trace = _add_trace(Color('#8da5f3'))
	lerp_trace = _add_trace(Color('#8eef97'))

	target_marker = _add_marker(Color('#f3d48d'), row_target)
	spring_marker = _add_marker(Color('#8da5f3'), row_spring)
	lerp_marker = _add_marker(Color('#8eef97'), row_lerp)

	_add_label('target', Vector2(40, row_target - 12), Color('#f3d48d'))
	_add_label('spring, critically damped', Vector2(40, row_spring - 12), Color('#8da5f3'))
	_add_label('lerp toward the target', Vector2(40, row_lerp - 12), Color('#8eef97'))
	_add_label('the same target, followed two ways, each trail is the last seconds of travel', Vector2(40, 40), Color('#999999'))


func _process(delta: float) -> void:
	elapsed += delta

	var target_x: float = center_x + sin(elapsed * TARGET_SPEED) * amplitude

	spring_velocity += ((target_x - spring_x) * STIFFNESS - spring_velocity * damping) * delta
	spring_x += spring_velocity * delta
	lerp_x = lerp(lerp_x, target_x, LERP_WEIGHT * delta)

	target_marker.position.x = target_x
	spring_marker.position.x = spring_x
	lerp_marker.position.x = lerp_x
	guide.position.x = target_x

	_push(target_trace, target_x, row_target)
	_push(spring_trace, spring_x, row_spring)
	_push(lerp_trace, lerp_x, row_lerp)


func _push(trace: Line2D, value: float, top: float) -> void:
	var points: PackedVector2Array = trace.points
	points.insert(0, Vector2(value, top))

	if points.size() > TRACE_POINTS:
		points.resize(TRACE_POINTS)

	for i in points.size():
		points[i] = Vector2(points[i].x, top + i * TRACE_STEP)

	trace.points = points


func _add_trace(color: Color) -> Line2D:
	var trace: Line2D = Line2D.new()
	trace.width = 3.0
	trace.default_color = Color(color, 0.55)
	add_child(trace)

	return trace


func _add_marker(color: Color, row: float) -> Polygon2D:
	var marker: Polygon2D = _make_rect(SIZE, color)
	marker.position = Vector2(center_x, row)
	add_child(marker)

	return marker


func _add_label(text: String, at: Vector2, color: Color) -> void:
	var label: Label = Label.new()
	label.text = text
	label.position = at
	label.add_theme_color_override('font_color', color)
	label.add_theme_font_size_override('font_size', 20)
	add_child(label)


func _make_rect(size: Vector2, color: Color) -> Polygon2D:
	var rect: Polygon2D = Polygon2D.new()
	rect.polygon = PackedVector2Array([-size * 0.5, Vector2(size.x, -size.y) * 0.5, size * 0.5, Vector2(-size.x, size.y) * 0.5])
	rect.color = color

	return rect


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)

Mais exemplos de Movimento