Add README screenshots: staged in-game captures between description and Downloads
CI / headless-tests (push) Successful in 2m22s
CI / headless-tests (push) Successful in 2m22s
- New capture tool src/test/capture_screenshots.gd (windowed, staged: venue overview, targeting an NPC, access inspection, radio report) - Generated shots saved to docs/screenshots/ and embedded as a 2x2 gallery in README above the Downloads section
This commit is contained in:
1 parent
eb1776e614
commit
f7486d7539
7 files changed
+95
-1
No files matched your search
@@ -25,7 +25,7 @@ Session memory for durable decisions, state, and gotchas. Keep concise, remove o
|
|||||||
- Newly added: LATE shift phase (start 700s) with a reachability test; PROTESTER archetype + events + colors; CALL_SOMEONE reaction; `DoorState` core class + `L` binding + visual indicator; flashlight (`G`, SpotLight3D, perception bonus at evening/late); persistence wired (`Save.save_shift_result` on shift end, history + best score on the review screen); `NavigationRegion3D` flat navmesh + `NavigationAgent3D` NPC paths (steps now visual-only); strings moved to `res://content/strings.en.json` (41 keys, loader keeps `lookup`/`fmt`); `export_presets.cfg` (Linux/Windows/macOS) + `tools/build_releases.sh` + `docs/RELEASING.md`; README Downloads section.
|
- Newly added: LATE shift phase (start 700s) with a reachability test; PROTESTER archetype + events + colors; CALL_SOMEONE reaction; `DoorState` core class + `L` binding + visual indicator; flashlight (`G`, SpotLight3D, perception bonus at evening/late); persistence wired (`Save.save_shift_result` on shift end, history + best score on the review screen); `NavigationRegion3D` flat navmesh + `NavigationAgent3D` NPC paths (steps now visual-only); strings moved to `res://content/strings.en.json` (41 keys, loader keeps `lookup`/`fmt`); `export_presets.cfg` (Linux/Windows/macOS) + `tools/build_releases.sh` + `docs/RELEASING.md`; README Downloads section.
|
||||||
- Run tests: `godot --headless --path . --script res://src/test/test_runner.gd`
|
- Run tests: `godot --headless --path . --script res://src/test/test_runner.gd`
|
||||||
- Boot check: `godot --headless --path . --quit-after 120`
|
- Boot check: `godot --headless --path . --quit-after 120`
|
||||||
- Screenshot tool: `godot --path . --script res://src/test/take_screenshot.gd` (writes to `user://screenshot.png`).
|
- Screenshot tools: `godot --path . -s res://src/test/take_screenshot.gd` (single shot to `user://screenshot.png`); `godot --path . -s res://src/test/capture_screenshots.gd` (staged README gallery shots to `user://screenshots/`, copied to `docs/screenshots/`).
|
||||||
- Release build verified locally: export templates for 4.3 installed at `~/.local/share/godot/export_templates/4.3.stable/`; `./tools/build_releases.sh` produced Linux/Windows/macOS artifacts for 0.1.0 in `build/` and the Linux binary passed a headless smoke test. Publishing to Gitea still needs a token (see `tools/publish_release.sh`, `docs/RELEASING.md`).
|
- Release build verified locally: export templates for 4.3 installed at `~/.local/share/godot/export_templates/4.3.stable/`; `./tools/build_releases.sh` produced Linux/Windows/macOS artifacts for 0.1.0 in `build/` and the Linux binary passed a headless smoke test. Publishing to Gitea still needs a token (see `tools/publish_release.sh`, `docs/RELEASING.md`).
|
||||||
|
|
||||||
## Known Issues / Notes
|
## Known Issues / Notes
|
||||||
|
|||||||
@@ -6,6 +6,15 @@ The central design goal is simple:
|
|||||||
|
|
||||||
> The player wins by choosing the lowest level of escalation that keeps everyone safe.
|
> The player wins by choosing the lowest level of escalation that keeps everyone safe.
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|---|---|
|
||||||
|
|  |  |
|
||||||
|
|  |  |
|
||||||
|
|
||||||
|
*Screenshots are generated by [`src/test/capture_screenshots.gd`](src/test/capture_screenshots.gd) from the current build.*
|
||||||
|
|
||||||
## ⬇️ Downloads
|
## ⬇️ Downloads
|
||||||
|
|
||||||
| Platform | Package |
|
| Platform | Package |
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 61 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 75 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 79 KiB |
@@ -0,0 +1,85 @@
|
|||||||
|
extends SceneTree
|
||||||
|
## Dev helper: run the game windowed and capture staged screenshots for the
|
||||||
|
## README. Saves 1600x900 PNGs to user://screenshots/.
|
||||||
|
## Usage: godot --path . --script res://src/test/capture_screenshots.gd
|
||||||
|
|
||||||
|
const OUT_DIR := "user://screenshots"
|
||||||
|
const MAX_FRAMES := 2400 # hard cap (~40s)
|
||||||
|
|
||||||
|
var frames := 0
|
||||||
|
var gm: Node = null
|
||||||
|
var state := 0
|
||||||
|
var state_frames := 0
|
||||||
|
var targeted := false
|
||||||
|
|
||||||
|
func _initialize() -> void:
|
||||||
|
root.size = Vector2i(1600, 900)
|
||||||
|
var packed: PackedScene = load("res://scenes/main.tscn")
|
||||||
|
var inst: Node = packed.instantiate()
|
||||||
|
root.add_child(inst)
|
||||||
|
|
||||||
|
func _process(_delta: float) -> bool:
|
||||||
|
frames += 1
|
||||||
|
# The main scene's _ready may not have run when _initialize added it;
|
||||||
|
# look for GameManager lazily each frame until it exists.
|
||||||
|
if gm == null:
|
||||||
|
gm = root.find_child("GameManager", true, false)
|
||||||
|
if gm == null and frames > 120:
|
||||||
|
push_error("GameManager not found")
|
||||||
|
quit(1)
|
||||||
|
return true
|
||||||
|
if frames > MAX_FRAMES:
|
||||||
|
print("timeout reached")
|
||||||
|
quit(0)
|
||||||
|
return true
|
||||||
|
_advance()
|
||||||
|
return false
|
||||||
|
|
||||||
|
func _advance() -> void:
|
||||||
|
state_frames += 1
|
||||||
|
match state:
|
||||||
|
0:
|
||||||
|
# 2s overview from the guard post.
|
||||||
|
if state_frames >= 120:
|
||||||
|
_shoot("01-venue-overview.png")
|
||||||
|
state = 1
|
||||||
|
state_frames = 0
|
||||||
|
1:
|
||||||
|
# Wait for a nearby NPC so the interaction HUD has a target.
|
||||||
|
if gm != null and gm.npcs.size() > 0:
|
||||||
|
gm.call("_cycle_nearby_target")
|
||||||
|
targeted = true
|
||||||
|
state = 2
|
||||||
|
state_frames = 0
|
||||||
|
2:
|
||||||
|
# Give the HUD a moment, then shoot the interaction shot.
|
||||||
|
if state_frames >= 30:
|
||||||
|
_shoot("02-targeting-npc.png")
|
||||||
|
if targeted and gm != null:
|
||||||
|
gm.call("_toggle_inspection")
|
||||||
|
state = 3
|
||||||
|
state_frames = 0
|
||||||
|
3:
|
||||||
|
if state_frames >= 30:
|
||||||
|
_shoot("03-access-inspection.png")
|
||||||
|
if gm != null:
|
||||||
|
gm.hud.hide_inspection()
|
||||||
|
# Re-target (target may have moved) before opening the radio form.
|
||||||
|
if gm.npcs.size() > 0:
|
||||||
|
gm.call("_cycle_nearby_target")
|
||||||
|
gm.call("_open_radio", false)
|
||||||
|
state = 4
|
||||||
|
state_frames = 0
|
||||||
|
4:
|
||||||
|
if state_frames >= 30:
|
||||||
|
_shoot("04-radio-report.png")
|
||||||
|
state = 5
|
||||||
|
quit(0)
|
||||||
|
|
||||||
|
func _shoot(file_name: String) -> void:
|
||||||
|
var dir := DirAccess.open("user://")
|
||||||
|
if dir == null or not dir.dir_exists("screenshots"):
|
||||||
|
dir.make_dir_recursive("screenshots")
|
||||||
|
var img: Image = root.get_texture().get_image()
|
||||||
|
var err := img.save_png(OUT_DIR.path_join(file_name))
|
||||||
|
print("%s -> err=%d (%dx%d)" % [file_name, err, img.get_width(), img.get_height()])
|
||||||
Reference in new issue
Block a user