公转与自转

三层嵌套的 Node2D 和两次旋转。子节点因为父节点在转而公转,孙节点又绕着子节点转。

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

用到的 Godot 类

Node2DLine2DPolygon2D

代码

scripts/main.gd
extends Node

const HUB_SPEED: float = 0.35
const PLANET_SPEED: float = 1.5
const ORBIT_RADIUS: float = 220.0
const MOON_RADIUS: float = 78.0

var hub: Node2D
var planet: Node2D


func _ready() -> void:
	_add_background()

	var view: Vector2 = get_viewport().get_visible_rect().size

	hub = Node2D.new()
	hub.position = view * 0.5
	hub.add_child(_make_ring(ORBIT_RADIUS))
	hub.add_child(_make_rect(Vector2(ORBIT_RADIUS, 8), Color('#2a2f3d'), Vector2(ORBIT_RADIUS * 0.5, 0)))
	hub.add_child(_make_circle(40.0, Color('#f3d48d')))
	add_child(hub)

	planet = Node2D.new()
	planet.position = Vector2(ORBIT_RADIUS, 0)
	planet.add_child(_make_ring(MOON_RADIUS))
	planet.add_child(_make_rect(Vector2(MOON_RADIUS, 6), Color('#2a2f3d'), Vector2(MOON_RADIUS * 0.5, 0)))
	planet.add_child(_make_circle(26.0, Color('#8da5f3')))
	hub.add_child(planet)

	var moon: Node2D = Node2D.new()
	moon.position = Vector2(MOON_RADIUS, 0)
	moon.add_child(_make_circle(12.0, Color('#8eef97')))
	planet.add_child(moon)

	_add_label('the hub spins, the planet rides that rotation, the moon rides the planet', Vector2(40, 40))


func _process(delta: float) -> void:
	hub.rotation += HUB_SPEED * delta
	planet.rotation += PLANET_SPEED * delta


func _make_ring(radius: float) -> Line2D:
	var ring: Line2D = Line2D.new()
	ring.width = 2.0
	ring.default_color = Color('#2a2f3d')

	for i in 49:
		ring.add_point(Vector2(cos(TAU * i / 48.0), sin(TAU * i / 48.0)) * radius)

	return ring


func _make_rect(size: Vector2, color: Color, at: Vector2) -> 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
	rect.position = at

	return rect


func _make_circle(radius: float, color: Color) -> Polygon2D:
	var points: PackedVector2Array = PackedVector2Array()

	for i in 28:
		points.append(Vector2(cos(TAU * i / 28.0), sin(TAU * i / 28.0)) * radius)

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

	return circle


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


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)

更多运动示例