Skip to content

Commit caabb84

Browse files
author
DavidQ
committed
Draw manifest-declared game backgrounds across all render states without opaque suppression - PR 11.87
1 parent ce16366 commit caabb84

5 files changed

Lines changed: 84 additions & 22 deletions

File tree

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,53 @@
1-
# PR 11.87 Validation Placeholder
1+
# PR 11.87 Validation - Manifest Background Always Visible
22

3-
Codex must replace this with actual targeted validation evidence.
3+
## Scope
4+
Implemented the smallest scoped runtime/render change so manifest-declared `image.*.background` remains visible across Asteroids render states without fallback asset paths.
45

5-
Required evidence:
6-
- Asteroids menu background visible.
7-
- Asteroids attract background visible.
8-
- Asteroids gameplay background visible.
9-
- No guessed background/bezel 404s.
10-
- No full sample suite run; targeted validation only.
6+
## Files Changed
7+
- `src/engine/runtime/backgroundImage.js`
8+
- `games/Asteroids/game/AsteroidsGameScene.js`
9+
- `games/Asteroids/game/AsteroidsAttractAdapter.js`
10+
- `docs/dev/reports/PR_11_87_validation.md`
11+
12+
## Implementation Evidence
13+
14+
### 1) Background gate removed (all render states)
15+
- `src/engine/runtime/backgroundImage.js`
16+
- `render(...)` no longer returns early for non-gameplay states.
17+
- Result: when manifest background exists and image is loaded, background draw path is allowed for menu/title/attract/gameplay/pause.
18+
19+
### 2) Opaque fills no longer hide background when manifest background is present
20+
- `games/Asteroids/game/AsteroidsGameScene.js`
21+
- Added `hasManifestBackgroundLayer(engine)` helper using `engine.backgroundImageLayer.getState()`.
22+
- Scene base fill changes from opaque `#020617` to translucent `rgba(2, 6, 23, 0.22)` when manifest background path is present.
23+
- `games/Asteroids/game/AsteroidsAttractAdapter.js`
24+
- `render(renderer, options)` now accepts `manifestBackgroundPresent`.
25+
- Attract fullscreen panel changes from opaque-ish `rgba(2, 6, 23, 0.86)` to translucent `rgba(2, 6, 23, 0.36)` when background is present.
26+
- Foreground text/entities/UI draws are preserved.
27+
28+
### 3) Manifest-only chrome/background rule preserved
29+
- No fallback URL construction added.
30+
- No new guessed `background.png`/`bezel.png` convention paths added.
31+
- No duplicated background SSoT under `asset-browser.assets.background` was introduced.
32+
33+
## Validation Commands and Results
34+
35+
### Syntax checks
36+
- `node --check src/engine/runtime/backgroundImage.js` -> PASS
37+
- `node --check games/Asteroids/game/AsteroidsGameScene.js` -> PASS
38+
- `node --check games/Asteroids/game/AsteroidsAttractAdapter.js` -> PASS
39+
40+
### Fallback/guessed-path search
41+
- `rg -n "assets/images/background\.png|assets/images/bezel\.png|/games/\$\{.*\}/assets/images/(background|bezel)\.png" src games tools -g "*.js"`
42+
- Result: no matches for guessed path construction added in JS runtime code.
43+
44+
### Targeted launch smoke (games only)
45+
- `node ./tests/runtime/LaunchSmokeAllEntries.test.mjs --games`
46+
- Result: PASS (12/12), including `Asteroids` and `SolarSystem`.
47+
- Console summary reported no failed entries.
48+
49+
## Requested Behavior Coverage
50+
- Asteroids menu/attract/gameplay/pause now permits manifest background draw via background layer (no gameplay-only gate).
51+
- Asteroids attract/fullscreen dark fill is no longer opaque when a manifest background is present.
52+
- Manifest-only chrome asset loading remains in effect.
53+
- No full sample suite run (targeted validation only).

docs/dev/reports/launch_smoke_report.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Launch Smoke Report
22

3-
Generated: 2026-04-30T00:12:47.854Z
3+
Generated: 2026-04-30T00:45:42.711Z
44

55
Filters: games=true, samples=false, tools=false, sampleRange=all
66

games/Asteroids/game/AsteroidsAttractAdapter.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,13 +238,20 @@ export default class AsteroidsAttractAdapter {
238238
});
239239
}
240240

241-
render(renderer) {
241+
render(renderer, options = {}) {
242242
if (!this.active) {
243243
return;
244244
}
245245

246246
const alpha = this.getPhaseAlpha();
247-
renderer.drawRect(0, 0, 960, 720, 'rgba(2, 6, 23, 0.86)');
247+
const manifestBackgroundPresent = options?.manifestBackgroundPresent === true;
248+
renderer.drawRect(
249+
0,
250+
0,
251+
960,
252+
720,
253+
manifestBackgroundPresent ? 'rgba(2, 6, 23, 0.36)' : 'rgba(2, 6, 23, 0.86)'
254+
);
248255

249256
if (this.phase === 'title') {
250257
this.renderTitle(renderer, alpha);

games/Asteroids/game/AsteroidsGameScene.js

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,17 @@ function drawLives(renderer, centerX, y, lives) {
9595
});
9696
}
9797

98+
function hasManifestBackgroundLayer(engine) {
99+
const state = engine?.backgroundImageLayer?.getState?.();
100+
if (!state || typeof state !== 'object') {
101+
return false;
102+
}
103+
return typeof state.path === 'string'
104+
&& state.path.trim().length > 0
105+
&& state.status !== 'missing'
106+
&& state.status !== 'unavailable';
107+
}
108+
98109
export default class AsteroidsGameScene extends Scene {
99110
constructor(options = {}) {
100111
super();
@@ -688,10 +699,17 @@ export default class AsteroidsGameScene extends Scene {
688699
this.lastPPressed = pPressed;
689700
}
690701

691-
render(renderer) {
702+
render(renderer, engine) {
692703
const leaderboardTopScore = this.highScoreService.getTopScore(this.highScoreRows);
693704
const liveHudHighScore = Math.max(this.session.highScore, leaderboardTopScore);
694-
renderer.drawRect(0, 0, this.world.bounds.width, this.world.bounds.height, '#020617');
705+
const manifestBackgroundPresent = hasManifestBackgroundLayer(engine);
706+
renderer.drawRect(
707+
0,
708+
0,
709+
this.world.bounds.width,
710+
this.world.bounds.height,
711+
manifestBackgroundPresent ? 'rgba(2, 6, 23, 0.22)' : '#020617'
712+
);
695713
this.world.starfield.forEach((star) => {
696714
renderer.drawRect(star.x, star.y, star.size, star.size, '#94a3b8');
697715
});
@@ -762,7 +780,9 @@ export default class AsteroidsGameScene extends Scene {
762780

763781
if (this.session.mode === 'menu') {
764782
if (this.attractController.active) {
765-
this.attractAdapter.render(renderer);
783+
this.attractAdapter.render(renderer, {
784+
manifestBackgroundPresent
785+
});
766786
} else {
767787
renderer.drawText('ASTEROIDS', 480, 220, {
768788
color: '#ffffff',

src/engine/runtime/backgroundImage.js

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -212,14 +212,6 @@ export default class backgroundImage {
212212
}
213213

214214
render(renderer, options = {}) {
215-
if (!this.isGameplayState(options.scene)) {
216-
return {
217-
drawn: false,
218-
reason: "non-gameplay-state",
219-
path: this.layer.path
220-
};
221-
}
222-
223215
this.ensureLoaded();
224216
if (this.layer.status !== "ready" || !this.layer.image) {
225217
return {

0 commit comments

Comments
 (0)