Skip to content

Commit 0270973

Browse files
author
DavidQ
committed
Continue AsteroidsGameScene cleanup without gameplay behavior changes - PR_26139_028-asteroids-game-scene-cleanup
1 parent 02f0c49 commit 0270973

4 files changed

Lines changed: 261 additions & 111 deletions

File tree

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# PR_26139_028-asteroids-game-scene-cleanup
2+
3+
## Summary
4+
- Audited `AsteroidsGameScene.js` for isolated helper logic after PR_26139_027.
5+
- Extracted debug-event summary formatting and dev-console diagnostics context building into `games/Asteroids/game/asteroidsDebugDiagnostics.js`.
6+
- Kept `AsteroidsGameScene.js` focused on scene lifecycle, update, render, and orchestration.
7+
- Did not change beat timing, collision, manifest rendering, asteroid scale tuning, or ship flame flicker behavior.
8+
9+
## Moved Logic
10+
- `formatAsteroidsDebugEventSummary`
11+
- `buildAsteroidsDebugDiagnosticsContext`
12+
- shared Asteroids debug world-stage list
13+
14+
## Behavior Preservation
15+
- Gameplay state is still owned by `AsteroidsGameScene`, `AsteroidsSession`, and `AsteroidsWorld`.
16+
- The new diagnostics helper reads existing scene/world/session state and returns the same diagnostics contract used by Asteroids debug tooling.
17+
- Weighted beat timing remains owned by the PR_26139_027 helper and was not retuned.
18+
19+
## Validation
20+
- PASS: `npm run build:manifest`
21+
- PASS: `npx playwright test tests/playwright/tools/AsteroidsBeatTiming.spec.mjs --project=playwright --workers=1 --reporter=list`
22+
- 1 passed.
23+
- PASS: `npx playwright test tests/playwright/tools/AsteroidsGameSceneCleanup.spec.mjs --project=playwright --workers=1 --reporter=list`
24+
- 1 passed.
25+
- PASS: `git diff --check`
26+
27+
## Targeted Gameplay Smoke
28+
- Added `AsteroidsGameSceneCleanup.spec.mjs`.
29+
- The smoke boots Asteroids, starts gameplay from the booted scene, verifies active gameplay state, and exercises the extracted diagnostics helper through the scene debug integration path.
30+
31+
## Coverage
32+
- Playwright impacted: Yes.
33+
- V8 coverage collected changed Asteroids files:
34+
- `(56%) games/Asteroids/game/AsteroidsGameScene.js - changed JS file with browser V8 coverage`
35+
- `(100%) games/Asteroids/game/asteroidsDebugDiagnostics.js - changed JS file with browser V8 coverage`
36+
37+
## Full Samples
38+
- Full samples smoke test was skipped.
39+
- Reason: scope is limited to Asteroids scene helper extraction with targeted Asteroids gameplay and beat timing validation.
40+
41+
## Manual Validation
42+
1. Launch `games/Asteroids/index.html`.
43+
2. Start a one-player game.
44+
3. Confirm ship, asteroids, bullets, UFOs, and manifest-rendered objects behave as before.
45+
4. Confirm large-to-medium-to-small asteroid splitting keeps the PR_26139_027 weighted beat cadence behavior.
46+
5. Confirm no console errors appear during normal gameplay.

games/Asteroids/game/AsteroidsGameScene.js

Lines changed: 17 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ import AsteroidsAttractAdapter from './AsteroidsAttractAdapter.js';
1414
import AsteroidsHighScoreService from '../systems/AsteroidsHighScoreService.js';
1515
import AsteroidsInitialsEntry from '../systems/AsteroidsInitialsEntry.js';
1616
import { createAsteroidGeometryProfilesFromObjectVectorAssets } from './asteroidObjectGeometry.js';
17+
import {
18+
ASTEROIDS_DEBUG_WORLD_STAGES,
19+
buildAsteroidsDebugDiagnosticsContext,
20+
formatAsteroidsDebugEventSummary
21+
} from './asteroidsDebugDiagnostics.js';
1722
import {
1823
calculateAsteroidsBeatTiming,
1924
getAsteroidsBeatWeightedTotal
@@ -289,17 +294,6 @@ export default class AsteroidsGameScene extends Scene {
289294
}
290295
}
291296

292-
formatDebugEventSummary(details = {}) {
293-
if (!details || typeof details !== 'object') {
294-
return '';
295-
}
296-
297-
const summaryParts = Object.entries(details)
298-
.map(([key, value]) => `${key}=${String(value)}`)
299-
.slice(0, 4);
300-
return summaryParts.join(' ');
301-
}
302-
303297
pushDebugEvent(type, details = {}) {
304298
const eventType = typeof type === 'string' ? type.trim() : '';
305299
if (!eventType) {
@@ -309,7 +303,7 @@ export default class AsteroidsGameScene extends Scene {
309303
const entry = {
310304
frame: this.debugFrame,
311305
type: eventType,
312-
summary: this.formatDebugEventSummary(details),
306+
summary: formatAsteroidsDebugEventSummary(details),
313307
details: { ...details },
314308
timestamp: Date.now(),
315309
};
@@ -411,103 +405,6 @@ export default class AsteroidsGameScene extends Scene {
411405
this.lastWave = this.world.wave;
412406
}
413407

414-
buildDebugDiagnosticsContext(engine, dtSeconds, frameEvents = {}) {
415-
const safeDt = Number.isFinite(dtSeconds) && dtSeconds > 0 ? dtSeconds : 1 / 60;
416-
const fps = safeDt > 0 ? Math.round(1 / safeDt) : 0;
417-
const activePlayer = this.session.activePlayer || { id: 1, score: 0, lives: 0 };
418-
const recentEvents = this.debugEvents.slice(-12);
419-
const input = engine?.input;
420-
const worldStages = ['parallax', 'entities', 'sprite-effects', 'vector-overlay'];
421-
422-
return {
423-
runtime: {
424-
sceneId: 'asteroids-showcase',
425-
status: this.session.mode,
426-
fps,
427-
frameTimeMs: Math.round(safeDt * 1000 * 100) / 100,
428-
debugMode: this.debugConfig.debugMode,
429-
debugEnabled: this.debugConfig.debugEnabled === true,
430-
},
431-
camera: {
432-
x: 0,
433-
y: 0,
434-
viewportWidth: this.world.bounds.width,
435-
viewportHeight: this.world.bounds.height,
436-
},
437-
entities: {
438-
count: (this.world.shipActive ? 1 : 0) + this.world.asteroids.length + this.world.bullets.length + this.world.ufoBullets.length + (this.world.ufo ? 1 : 0),
439-
shipActive: this.world.shipActive,
440-
asteroidCount: this.world.asteroids.length,
441-
bulletCount: this.world.bullets.length,
442-
ufoBulletCount: this.world.ufoBullets.length,
443-
},
444-
tilemap: {
445-
width: 0,
446-
height: 0,
447-
tileSize: 0,
448-
},
449-
input: {
450-
left: input?.isDown?.('ArrowLeft') === true,
451-
right: input?.isDown?.('ArrowRight') === true,
452-
thrust: input?.isDown?.('ArrowUp') === true,
453-
fire: input?.isDown?.('Space') === true,
454-
pause: input?.isDown?.('KeyP') === true,
455-
consoleToggle: input?.isDown?.('ShiftLeft') === true && input?.isDown?.('Backquote') === true,
456-
overlayToggle: (input?.isDown?.('ControlLeft') === true || input?.isDown?.('ControlRight') === true) && input?.isDown?.('ShiftLeft') === true && input?.isDown?.('Backquote') === true,
457-
},
458-
hotReload: {
459-
enabled: false,
460-
pending: false,
461-
mode: 'showcase-manual',
462-
},
463-
validation: {
464-
errorCount: 0,
465-
warningCount: 0,
466-
asteroidsRecentEvents: recentEvents,
467-
asteroidsFrameEvents: frameEvents,
468-
},
469-
render: {
470-
stages: worldStages,
471-
debugSurfaceTail: ['debug-overlay', 'dev-console-surface'],
472-
},
473-
assets: {
474-
asteroidsShowcase: {
475-
session: {
476-
mode: this.session.mode,
477-
status: this.session.status,
478-
activePlayer: activePlayer.id,
479-
score: activePlayer.score,
480-
highScore: this.session.highScore,
481-
lives: activePlayer.lives,
482-
wave: this.world.wave,
483-
isPaused: this.isPaused,
484-
},
485-
entities: {
486-
ship: {
487-
active: this.world.shipActive,
488-
x: this.world.ship.x,
489-
y: this.world.ship.y,
490-
vx: this.world.ship.vx,
491-
vy: this.world.ship.vy,
492-
angle: this.world.ship.angle,
493-
},
494-
asteroidCount: this.world.asteroids.length,
495-
bulletCount: this.world.bullets.length,
496-
ufoBulletCount: this.world.ufoBullets.length,
497-
ufo: {
498-
active: Boolean(this.world.ufo),
499-
type: this.world.ufo?.type || '',
500-
},
501-
},
502-
presets: {
503-
defaultCommand: 'asteroidsshowcase.preset.default',
504-
eventsCommand: 'asteroidsshowcase.preset.events',
505-
},
506-
},
507-
},
508-
};
509-
}
510-
511408
updateDebugIntegration(engine, dtSeconds, frameEvents = {}) {
512409
if (!this.devConsoleIntegration) {
513410
return;
@@ -516,7 +413,16 @@ export default class AsteroidsGameScene extends Scene {
516413
this.devConsoleIntegration.update({
517414
engine,
518415
scene: this,
519-
diagnosticsContext: this.buildDebugDiagnosticsContext(engine, dtSeconds, frameEvents),
416+
diagnosticsContext: buildAsteroidsDebugDiagnosticsContext({
417+
debugConfig: this.debugConfig,
418+
debugEvents: this.debugEvents,
419+
dtSeconds,
420+
engine,
421+
frameEvents,
422+
isPaused: this.isPaused,
423+
session: this.session,
424+
world: this.world
425+
}),
520426
});
521427
}
522428

@@ -882,7 +788,7 @@ export default class AsteroidsGameScene extends Scene {
882788

883789
if (this.devConsoleIntegration) {
884790
this.devConsoleIntegration.render(renderer, {
885-
worldStages: ['parallax', 'entities', 'sprite-effects', 'vector-overlay'],
791+
worldStages: [...ASTEROIDS_DEBUG_WORLD_STAGES],
886792
});
887793
}
888794
this.publishObjectVectorRuntimeDiagnostics();
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
export const ASTEROIDS_DEBUG_WORLD_STAGES = Object.freeze(['parallax', 'entities', 'sprite-effects', 'vector-overlay']);
2+
3+
export function formatAsteroidsDebugEventSummary(details = {}) {
4+
if (!details || typeof details !== 'object') {
5+
return '';
6+
}
7+
8+
const summaryParts = Object.entries(details)
9+
.map(([key, value]) => `${key}=${String(value)}`)
10+
.slice(0, 4);
11+
return summaryParts.join(' ');
12+
}
13+
14+
export function buildAsteroidsDebugDiagnosticsContext({
15+
debugConfig,
16+
debugEvents,
17+
dtSeconds,
18+
engine,
19+
frameEvents,
20+
isPaused,
21+
session,
22+
world,
23+
}) {
24+
const safeDt = Number.isFinite(dtSeconds) && dtSeconds > 0 ? dtSeconds : 1 / 60;
25+
const fps = safeDt > 0 ? Math.round(1 / safeDt) : 0;
26+
const activePlayer = session.activePlayer || { id: 1, score: 0, lives: 0 };
27+
const recentEvents = debugEvents.slice(-12);
28+
const input = engine?.input;
29+
30+
return {
31+
runtime: {
32+
sceneId: 'asteroids-showcase',
33+
status: session.mode,
34+
fps,
35+
frameTimeMs: Math.round(safeDt * 1000 * 100) / 100,
36+
debugMode: debugConfig.debugMode,
37+
debugEnabled: debugConfig.debugEnabled === true,
38+
},
39+
camera: {
40+
x: 0,
41+
y: 0,
42+
viewportWidth: world.bounds.width,
43+
viewportHeight: world.bounds.height,
44+
},
45+
entities: {
46+
count: (world.shipActive ? 1 : 0) + world.asteroids.length + world.bullets.length + world.ufoBullets.length + (world.ufo ? 1 : 0),
47+
shipActive: world.shipActive,
48+
asteroidCount: world.asteroids.length,
49+
bulletCount: world.bullets.length,
50+
ufoBulletCount: world.ufoBullets.length,
51+
},
52+
tilemap: {
53+
width: 0,
54+
height: 0,
55+
tileSize: 0,
56+
},
57+
input: {
58+
left: input?.isDown?.('ArrowLeft') === true,
59+
right: input?.isDown?.('ArrowRight') === true,
60+
thrust: input?.isDown?.('ArrowUp') === true,
61+
fire: input?.isDown?.('Space') === true,
62+
pause: input?.isDown?.('KeyP') === true,
63+
consoleToggle: input?.isDown?.('ShiftLeft') === true && input?.isDown?.('Backquote') === true,
64+
overlayToggle: (input?.isDown?.('ControlLeft') === true || input?.isDown?.('ControlRight') === true) && input?.isDown?.('ShiftLeft') === true && input?.isDown?.('Backquote') === true,
65+
},
66+
hotReload: {
67+
enabled: false,
68+
pending: false,
69+
mode: 'showcase-manual',
70+
},
71+
validation: {
72+
errorCount: 0,
73+
warningCount: 0,
74+
asteroidsRecentEvents: recentEvents,
75+
asteroidsFrameEvents: frameEvents,
76+
},
77+
render: {
78+
stages: [...ASTEROIDS_DEBUG_WORLD_STAGES],
79+
debugSurfaceTail: ['debug-overlay', 'dev-console-surface'],
80+
},
81+
assets: {
82+
asteroidsShowcase: {
83+
session: {
84+
mode: session.mode,
85+
status: session.status,
86+
activePlayer: activePlayer.id,
87+
score: activePlayer.score,
88+
highScore: session.highScore,
89+
lives: activePlayer.lives,
90+
wave: world.wave,
91+
isPaused,
92+
},
93+
entities: {
94+
ship: {
95+
active: world.shipActive,
96+
x: world.ship.x,
97+
y: world.ship.y,
98+
vx: world.ship.vx,
99+
vy: world.ship.vy,
100+
angle: world.ship.angle,
101+
},
102+
asteroidCount: world.asteroids.length,
103+
bulletCount: world.bullets.length,
104+
ufoBulletCount: world.ufoBullets.length,
105+
ufo: {
106+
active: Boolean(world.ufo),
107+
type: world.ufo?.type || '',
108+
},
109+
},
110+
presets: {
111+
defaultCommand: 'asteroidsshowcase.preset.default',
112+
eventsCommand: 'asteroidsshowcase.preset.events',
113+
},
114+
},
115+
},
116+
};
117+
}

0 commit comments

Comments
 (0)