Skip to content

Commit 73f77e8

Browse files
author
DavidQ
committed
Add pre-game bezel stretch override file auto-create
1 parent 3af43ae commit 73f77e8

6 files changed

Lines changed: 53 additions & 74 deletions

File tree

docs/dev/CODEX_COMMANDS.md

Lines changed: 9 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,15 @@
1+
12
MODEL: GPT-5.4
23
REASONING: high
34

4-
COMMAND:
5-
Create `BUILD_PR_LEVEL_10_20_FIX_BEZEL_PATH_AND_BACKGROUND_DRAW_ORDER`.
6-
7-
Implement the confirmed Asteroids runtime fixes:
8-
9-
1. Fix fullscreen bezel path duplication
10-
- current bad URL example:
11-
`http://127.0.0.1:5500/games/Asteroids/games/Asteroids/assets/images/bezel.png`
12-
- normalize asset path resolution so bezel resolves once to:
13-
`games/Asteroids/assets/images/bezel.png`
14-
15-
2. Preserve canvas layout
16-
- do NOT resize the canvas internal game dimensions
17-
- do NOT stretch the game resolution
18-
- keep canvas centered
19-
- preserve intended game width and height
20-
21-
3. Fix background rendering
22-
- keep `backgroundImage` as a separate class/module from `fullscreenBezel`
23-
- draw `backgroundImage` only during gameplay states
24-
- draw it immediately after clear
25-
- draw it before starfield and before all other world/gameplay content
26-
- inspect Asteroids render order and fix any layer that currently hides the background
27-
28-
4. Keep bezel as HTML overlay
29-
- keep `fullscreenBezel` as a separate HTML/container-level overlay
30-
- only show it in fullscreen
31-
- ensure it is visibly on screen, not just present in the DOM
32-
33-
5. Use this exact bezel transparency fit rule
34-
- from left to right, find first transparent pixel
35-
- from right to left, find first transparent pixel
36-
- from top to bottom, find first transparent pixel
37-
- from bottom to top, find first transparent pixel
38-
- use those four values as the transparency window
39-
- maintain canvas aspect ratio
40-
- stretch the displayed canvas to fill the transparency window as much as possible
41-
- keep the displayed canvas centered in that window
42-
- do NOT change internal game resolution
43-
- if top/bottom does not fill, use that result for resize
44-
- if left/right does not fill, use that result for resize
45-
- if no valid transparency window is found, fall back to existing centered-canvas behavior
46-
47-
6. Add one shared extra-stretch setting
48-
- create one single developer-facing variable that applies equally to all four sides
49-
- use it to push the displayed canvas slightly farther toward the bezel opening edges when the default fit is just short
50-
- place this in a small easy-to-find config/override file, not hidden in code constants
51-
- when bezel is detected, check whether that file exists
52-
- if it does not exist, create it automatically for the developer with a safe default value
53-
- keep filename/location obvious near the relevant game asset/config area
5+
UPDATE EXISTING PR:
546

55-
7. Validate
56-
- bezel URL/path not duplicated
57-
- bezel visible in fullscreen
58-
- canvas internal size unchanged
59-
- canvas centered
60-
- exact four-direction transparency rule used
61-
- displayed canvas fills transparency window as fully as possible while preserving aspect ratio
62-
- shared extra-stretch variable affects all four sides equally
63-
- override/config file is auto-created when missing and bezel is detected
64-
- background visible during gameplay
65-
- background absent in non-gameplay states
66-
- starfield no longer hides background incorrectly
7+
Add startup behavior:
678

68-
8. Final packaging step is REQUIRED
69-
- package ALL changed files into this exact repo-structured ZIP:
70-
`<project folder>/tmp/BUILD_PR_LEVEL_10_20_FIX_BEZEL_PATH_AND_BACKGROUND_DRAW_ORDER.zip`
9+
- On game load (before gameplay)
10+
- If bezel detected AND override file missing:
11+
create:
12+
games/<game>/assets/images/bezel.stretch.override.json
7113

72-
Hard rules:
73-
- write implementation code only through Codex
74-
- include changed implementation files in Codex ZIP
75-
- no docs-only completion by Codex
76-
- no missing ZIP
77-
- no unrelated repo changes
14+
- Do NOT overwrite if it already exists
15+
- Ensure this runs once during init

docs/dev/COMMIT_COMMENT.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
Fix bezel path and gameplay background draw order, add bezel extra-stretch override
2-
BUILD_PR_LEVEL_10_20_FIX_BEZEL_PATH_AND_BACKGROUND_DRAW_ORDER
1+
Add pre-game bezel stretch override file auto-create
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
## ADDITIONAL REQUIREMENT UPDATE
3+
4+
When the game loads (pre-gameplay phase):
5+
6+
If a bezel is detected AND the file:
7+
games/<game>/assets/images/bezel.stretch.override.json
8+
9+
DOES NOT exist:
10+
- automatically create this file
11+
- create it BEFORE gameplay begins (startup/init phase)
12+
- include the shared stretch variable with a safe default
13+
- ensure this happens only once (do not overwrite existing file)
14+
15+
Intent:
16+
- developer immediately sees where to tweak stretch
17+
- no manual setup required
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"uniformEdgeStretchPx": 5
2+
"uniformEdgeStretchPx": 10
33
}

src/engine/runtime/fullscreenBezel.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,7 @@ export default class fullscreenBezel {
549549
? options.stretchConfigProvider
550550
: loadBezelStretchConfig;
551551
this.stretchConfigPromise = null;
552+
this.stretchConfigInitialized = false;
552553
this.uniformEdgeStretchPx = 0;
553554
this.transparentWindowRect = null;
554555
this.imageSize = null;
@@ -565,6 +566,7 @@ export default class fullscreenBezel {
565566
canvasLayoutMode: this.canvasLayoutMode,
566567
transparentWindowRect: this.transparentWindowRect,
567568
stretchConfigPath: this.stretchConfigPath,
569+
stretchConfigInitialized: this.stretchConfigInitialized,
568570
uniformEdgeStretchPx: this.uniformEdgeStretchPx
569571
};
570572
}
@@ -609,6 +611,11 @@ export default class fullscreenBezel {
609611
}
610612

611613
refreshStretchConfig() {
614+
if (this.stretchConfigInitialized) {
615+
return this.stretchConfigPromise;
616+
}
617+
this.stretchConfigInitialized = true;
618+
612619
if (!this.stretchConfigPath || typeof this.stretchConfigProvider !== "function") {
613620
this.applyStretchConfig(DEFAULT_BEZEL_STRETCH_CONFIG);
614621
return null;

tests/core/BackgroundImageAndFullscreenBezel.test.mjs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,17 @@ async function testBezelStretchConfigAutoCreate() {
417417
const absolutePath = path.resolve(tempRoot, configPath);
418418
const saved = JSON.parse(await fs.readFile(absolutePath, "utf8"));
419419
assert.deepEqual(saved, { uniformEdgeStretchPx: 0 });
420+
421+
const existingContent = { uniformEdgeStretchPx: 12 };
422+
await fs.writeFile(absolutePath, `${JSON.stringify(existingContent, null, 2)}\n`, "utf8");
423+
const loadedExisting = await ensureBezelStretchConfigFile(configPath, {
424+
cwd: tempRoot,
425+
fsModule: fs,
426+
pathModule: path
427+
});
428+
const savedAfterReload = JSON.parse(await fs.readFile(absolutePath, "utf8"));
429+
assert.deepEqual(loadedExisting, existingContent);
430+
assert.deepEqual(savedAfterReload, existingContent);
420431
} finally {
421432
await fs.rm(tempRoot, { recursive: true, force: true });
422433
}
@@ -433,10 +444,12 @@ async function testBezelDetectionTriggersStretchConfigAutoCreate() {
433444
documentRef.body.appendChild(host);
434445

435446
try {
447+
let providerCalls = 0;
436448
const bezel = new fullscreenBezel({
437449
canvas,
438450
documentRef,
439451
stretchConfigProvider(configPath) {
452+
providerCalls += 1;
440453
return ensureBezelStretchConfigFile(configPath, {
441454
cwd: tempRoot,
442455
fsModule: fs,
@@ -445,9 +458,13 @@ async function testBezelDetectionTriggersStretchConfigAutoCreate() {
445458
}
446459
});
447460
bezel.attach();
461+
assert.equal(providerCalls, 0);
448462
bezel.element.naturalWidth = 1920;
449463
bezel.element.naturalHeight = 1080;
450464
bezel.element.onload?.();
465+
assert.equal(providerCalls, 1);
466+
bezel.sync({ fullscreenActive: false, fullscreenElement: host });
467+
assert.equal(providerCalls, 1);
451468
if (bezel.stretchConfigPromise) {
452469
await bezel.stretchConfigPromise;
453470
}
@@ -456,6 +473,7 @@ async function testBezelDetectionTriggersStretchConfigAutoCreate() {
456473
const saved = JSON.parse(await fs.readFile(createdPath, "utf8"));
457474
assert.deepEqual(saved, { uniformEdgeStretchPx: 0 });
458475
assert.equal(bezel.getState().stretchConfigPath, "games/Asteroids/assets/images/bezel.stretch.override.json");
476+
assert.equal(bezel.getState().stretchConfigInitialized, true);
459477
} finally {
460478
await fs.rm(tempRoot, { recursive: true, force: true });
461479
}

0 commit comments

Comments
 (0)