Screen wrap
An Asteroids ship and eight rocks that leave one edge and come back on the other. Two calls to wrapf do it.
The editor above is running this project. Change a line and it reloads.
Godot classes used
Node2DPolygon2DInput
The code
scripts/main.gd
extends Node
const TURN_SPEED: float = 3.4
const THRUST: float = 420.0
const DRAG: float = 0.35
const MARGIN: float = 46.0
const ROCKS: int = 8
var ship: Node2D
var velocity: Vector2 = Vector2(230, -160)
var rocks: Array[Node2D] = []
var drifts: Array[Vector2] = []
var spins: Array[float] = []
var view: Vector2
func _ready() -> void:
_add_background()
view = get_viewport().get_visible_rect().size
for i in ROCKS:
var rock: Node2D = Node2D.new()
rock.position = Vector2(randf_range(0, view.x), randf_range(0, view.y))
rock.add_child(_make_rock(randf_range(18, 40)))
add_child(rock)
rocks.append(rock)
drifts.append(Vector2(randf_range(-160, 160), randf_range(-160, 160)))
spins.append(randf_range(-1.2, 1.2))
ship = Node2D.new()
ship.position = view * 0.5
ship.add_child(_make_ship())
add_child(ship)
_add_label('left and right to turn, up to thrust, everything leaves one edge and returns on the other', Vector2(40, 40))
print('arrow keys to fly, the ship wraps around the screen')
func _process(delta: float) -> void:
ship.rotation += Input.get_axis('ui_left', 'ui_right') * TURN_SPEED * delta
if Input.is_action_pressed('ui_up'):
velocity += Vector2.RIGHT.rotated(ship.rotation) * THRUST * delta
velocity = velocity.lerp(Vector2.ZERO, DRAG * delta)
ship.position = _wrap(ship.position + velocity * delta)
for i in rocks.size():
rocks[i].position = _wrap(rocks[i].position + drifts[i] * delta)
rocks[i].rotation += spins[i] * delta
func _wrap(at: Vector2) -> Vector2:
return Vector2(wrapf(at.x, -MARGIN, view.x + MARGIN), wrapf(at.y, -MARGIN, view.y + MARGIN))
func _make_ship() -> Polygon2D:
var ship_body: Polygon2D = Polygon2D.new()
ship_body.polygon = PackedVector2Array([Vector2(30, 0), Vector2(-18, -17), Vector2(-9, 0), Vector2(-18, 17)])
ship_body.color = Color('#8da5f3')
return ship_body
func _make_rock(radius: float) -> Polygon2D:
var points: PackedVector2Array = PackedVector2Array()
for i in 9:
var angle: float = TAU * i / 9.0
points.append(Vector2(cos(angle), sin(angle)) * radius * randf_range(0.7, 1.2))
var rock: Polygon2D = Polygon2D.new()
rock.polygon = points
rock.color = Color('#2a2f3d').lerp(Color('#8da5f3'), 0.22)
return rock
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)