Initial commit: SpaceshipTest, a top-down space RTS in Godot 4.7.1

A fleet of neon-outlined ships explores a procedurally generated, seeded
infinite world: tap/joystick steering, pinch zoom, formation pivoting,
planet landings, an ore economy with extractors and haulers, and player
built structures (mothership, ship crafter, command centre).

All art is hand-drawn with draw_* calls rather than textures, and the
backgrounds are camera-relative shaders so they stay precise at large
world coordinates.

Includes a 35-test headless suite (tests/run_tests.sh) plus screenshot
tooling that renders real frames through Xvfb and Mesa softpipe, since
--headless has no GPU.

Excluded from version control: .godot/ (import cache, and it holds
export credentials), builds/, android/build/ and packaged APKs - all
regenerable, and ~325 MB combined.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Loïc Wisniewski 2026-08-10 18:41:58 +02:00
commit 85814ce88c
192 changed files with 9602 additions and 0 deletions

31
ViewUtils.gd Normal file
View file

@ -0,0 +1,31 @@
class_name ViewUtils
extends RefCounted
# Computes the exact world-space rect currently visible on screen by
# transforming the viewport's real screen corners through the actual canvas
# transform, instead of approximating with viewport_size * camera.zoom
# (which assumes a simple centered mapping - stretch/aspect="expand" doesn't
# necessarily expand symmetrically around center, which was making that
# approximation under/over-shoot on one side and cull content that was
# actually on screen).
static func get_visible_world_rect(node: Node) -> Rect2:
var canvas_transform: Transform2D = node.get_viewport().get_canvas_transform()
var inverse: Transform2D = canvas_transform.affine_inverse()
var size: Vector2 = node.get_viewport_rect().size
var corners: Array = [
inverse * Vector2(0, 0),
inverse * Vector2(size.x, 0),
inverse * Vector2(0, size.y),
inverse * Vector2(size.x, size.y),
]
var min_pt: Vector2 = corners[0]
var max_pt: Vector2 = corners[0]
for c in corners:
min_pt.x = min(min_pt.x, c.x)
min_pt.y = min(min_pt.y, c.y)
max_pt.x = max(max_pt.x, c.x)
max_pt.y = max(max_pt.y, c.y)
return Rect2(min_pt, max_pt - min_pt)