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:
commit
85814ce88c
192 changed files with 9602 additions and 0 deletions
53
tests/_screenshot_tool.gd
Normal file
53
tests/_screenshot_tool.gd
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
extends SceneTree
|
||||
|
||||
# Reusable screenshot tool - NOT run via run_tests.sh (underscore prefix).
|
||||
# Loads a given scene, waits for a given number of frames to render, then
|
||||
# saves a PNG and quits. Must be run WITHOUT --headless (that forces
|
||||
# Godot's dummy/null renderer) - see tests/screenshot.sh for the full
|
||||
# invocation (Xvfb + Mesa softpipe; llvmpipe's JIT crashes with SIGILL in
|
||||
# this environment, softpipe's non-JIT rasterizer does not).
|
||||
#
|
||||
# Args (after `--`): <scene_res_path> <output_png_path> [wait_frames]
|
||||
|
||||
var wait_frames: int = 60
|
||||
var frames: int = 0
|
||||
var scene_path: String
|
||||
var output_path: String
|
||||
var loaded_scene: Node
|
||||
|
||||
|
||||
func _initialize() -> void:
|
||||
var args: PackedStringArray = OS.get_cmdline_user_args()
|
||||
if args.size() < 2:
|
||||
printerr("usage: -- <scene_res_path> <output_png_path> [wait_frames]")
|
||||
quit(1)
|
||||
return
|
||||
|
||||
scene_path = args[0]
|
||||
output_path = args[1]
|
||||
if args.size() >= 3:
|
||||
wait_frames = int(args[2])
|
||||
|
||||
var packed: PackedScene = load(scene_path)
|
||||
if packed == null:
|
||||
printerr("could not load scene: %s" % scene_path)
|
||||
quit(1)
|
||||
return
|
||||
|
||||
loaded_scene = packed.instantiate()
|
||||
root.add_child(loaded_scene)
|
||||
|
||||
|
||||
func _process(_delta: float) -> bool:
|
||||
frames += 1
|
||||
if frames < wait_frames:
|
||||
return false
|
||||
var img: Image = root.get_viewport().get_texture().get_image()
|
||||
var err: int = img.save_png(output_path)
|
||||
if err != OK:
|
||||
printerr("save_png failed with error %d" % err)
|
||||
quit(1)
|
||||
return true
|
||||
print("SCREENSHOT_SAVED: %s (%s)" % [output_path, str(img.get_size())])
|
||||
quit(0)
|
||||
return true
|
||||
Loading…
Reference in a new issue