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>
31 lines
1.1 KiB
GDScript
31 lines
1.1 KiB
GDScript
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)
|