挤压与拉伸

两边是节奏完全相同的同一个跳跃,只有右边对缩放做了 tween。多出的三行就是全部差别。

上方的编辑器正在运行这个项目。改一行代码,它就会重新加载。

用到的 Godot 类

TweenPolygon2DColorRect

代码

scripts/main.gd
extends Node

const RADIUS: float = 46.0
const GROUND_Y: float = 580.0
const TOP_Y: float = 250.0
const CROUCH: float = 0.18
const HALF: float = 0.51


func _ready() -> void:
	_add_background()
	_add_label('same jump, same timing, only the scale changes', Vector2(40, 40), Color('#999999'))
	_add_ground()

	_add_label('position only', Vector2(350, 620), Color('#999999'))
	_add_label('position + scale', Vector2(760, 620), Color('#8eef97'))

	var plain: Polygon2D = _make_ball(Color('#8da5f3'))
	plain.position = Vector2(430, GROUND_Y)
	add_child(plain)

	var juiced: Polygon2D = _make_ball(Color('#8eef97'))
	juiced.position = Vector2(850, GROUND_Y)
	add_child(juiced)

	var flat: Tween = create_tween().set_loops()
	flat.tween_interval(CROUCH)
	flat.tween_property(plain, 'position:y', TOP_Y, HALF).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
	flat.tween_property(plain, 'position:y', GROUND_Y, HALF).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN)

	var juice: Tween = create_tween().set_loops()
	juice.tween_property(juiced, 'scale', Vector2(1.38, 0.62), CROUCH).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
	juice.tween_callback(juiced.set_scale.bind(Vector2(0.72, 1.38)))
	juice.tween_property(juiced, 'position:y', TOP_Y, HALF).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
	juice.parallel().tween_property(juiced, 'scale', Vector2.ONE, HALF)
	juice.tween_property(juiced, 'position:y', GROUND_Y, HALF).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN)
	juice.parallel().tween_property(juiced, 'scale', Vector2(0.74, 1.36), HALF)

	print('the green ball is round only at the top of the arc')


func _add_ground() -> void:
	var floor_rect: ColorRect = ColorRect.new()
	floor_rect.color = Color('#2a2f3d')
	floor_rect.position = Vector2(0, GROUND_Y)
	floor_rect.size = Vector2(1280, 8)
	add_child(floor_rect)

	var divider: ColorRect = ColorRect.new()
	divider.color = Color('#2a2f3d')
	divider.position = Vector2(639, 120)
	divider.size = Vector2(2, 460)
	add_child(divider)


# the origin sits on the contact point, so scaling squashes against the floor
func _make_ball(color: Color) -> Polygon2D:
	var points: PackedVector2Array = PackedVector2Array()

	for i in 32:
		var angle: float = TAU * i / 32
		points.append(Vector2(cos(angle), sin(angle)) * RADIUS - Vector2(0, RADIUS))

	var ball: Polygon2D = Polygon2D.new()
	ball.polygon = points
	ball.color = color

	return ball


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) -> void:
	var label: Label = Label.new()
	label.text = text
	label.position = at
	label.add_theme_color_override('font_color', color)
	add_child(label)

更多动画示例