Detailed graphics pass: authored textures, humanoid NPCs, HUD feedback, asset pipeline
- tools/generate_textures.py (deterministic PIL) produces all authored PNGs: brick facade, concrete, asphalt, awning, skyline, vignette, HUD icons, access-card art (all <=1024px, power-of-two) - WorldBuilder: textured facade/glass door/sidewalk/asphalt, striped awning with 'STEP LINE', generated skyline backdrop planes - GameManager: soft sun shadows (4-split parallel); guard in 'guard' group - NPC avatars: humanoid rig (torso/head/limbs) with archetype props (camera, delivery box, performer hat, protest sign, tourist backpack), procedural walk bob, head-turns-toward-guard attention cue - HUD: inspection artifact cards, mode icons (flashlight/door/wand), per-escalation vignette, body-camera overlay (corner brackets + REC + clock) - assets/ import convention documented; test_asset_textures_present_and_pow2 guards the pipeline (57 tests pass) - README tech stack updated for Gitea Actions + asset pipeline; screenshot gallery regenerated (day + night)
This commit is contained in:
1 parent
ac3bb7dcd8
commit
031503e161
31 files changed
+636
-57
No files matched your search
@@ -45,6 +45,39 @@ func test_street_lamps_and_marquee_built() -> bool:
|
||||
root.free()
|
||||
return a and b and TestUtils.check(night_on, "lamps brighten at night") and TestUtils.check(day_off, "lamps dim in daylight")
|
||||
|
||||
func test_asset_textures_present_and_pow2() -> bool:
|
||||
var required := [
|
||||
"res://assets/textures/brick_facade.png",
|
||||
"res://assets/textures/concrete.png",
|
||||
"res://assets/textures/asphalt.png",
|
||||
"res://assets/textures/awning.png",
|
||||
"res://assets/textures/skyline.png",
|
||||
"res://assets/textures/vignette.png",
|
||||
"res://assets/textures/icons/flashlight_on.png",
|
||||
"res://assets/textures/icons/door_locked.png",
|
||||
"res://assets/textures/icons/wand.png",
|
||||
"res://assets/textures/icons/rec_dot.png",
|
||||
"res://assets/textures/cards/id_card.png",
|
||||
"res://assets/textures/cards/wristband.png",
|
||||
"res://assets/textures/cards/ticket.png",
|
||||
"res://assets/textures/cards/credential.png",
|
||||
"res://assets/textures/cards/guest_list.png",
|
||||
]
|
||||
for path in required:
|
||||
if not FileAccess.file_exists(path):
|
||||
return TestUtils.fail("missing generated asset: %s — run tools/generate_textures.py" % path)
|
||||
var img := Image.new()
|
||||
for path in required:
|
||||
if img.load(path) != OK:
|
||||
return TestUtils.fail("cannot decode asset: %s" % path)
|
||||
var w := img.get_width()
|
||||
var h := img.get_height()
|
||||
if w > 1024 or h > 1024:
|
||||
return TestUtils.fail("asset too large: %s (%dx%d)" % [path, w, h])
|
||||
if (w & (w - 1)) != 0 or (h & (h - 1)) != 0:
|
||||
return TestUtils.fail("asset not power-of-two: %s (%dx%d)" % [path, w, h])
|
||||
return true
|
||||
|
||||
func test_door_indicator_built() -> bool:
|
||||
var root := Node3D.new()
|
||||
var builder := WorldBuilder.new(root)
|
||||
|
||||
Reference in new issue
Block a user