Skip to content

Commit 396616c

Browse files
author
DavidQ
committed
Remove Asteroids shared tool fallback geometry and load object vectors from manifest - PR_26133_029-remove-asteroids-shared-tool-fallbacks
1 parent 526dbdf commit 396616c

19 files changed

Lines changed: 444 additions & 742 deletions
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Asteroids Shared Tool Fallback Removal Report
2+
3+
Task: PR_26133_029-remove-asteroids-shared-tool-fallbacks
4+
Date: 2026-05-14
5+
6+
## Removed Fallbacks
7+
8+
- Removed `tools/shared/asteroidsPlatformDemo.js`.
9+
- Removed shared-tool usage of the hardcoded Asteroids SVG constants:
10+
- `ASTEROIDS_SHIP_SVG`
11+
- `ASTEROIDS_LARGE_SVG`
12+
- `ASTEROIDS_MEDIUM_SVG`
13+
- `ASTEROIDS_SMALL_SVG`
14+
- Removed the Asteroids `BASE_VECTOR_MAP` runtime collision fallback from `games/Asteroids/entities/Asteroid.js`.
15+
- Removed Asteroids-specific object IDs and geometry fixtures from `tools/shared/vectorAssetSystem.js`.
16+
17+
## Remaining Manifest Load Path
18+
19+
- Canonical Asteroids geometry remains in `games/Asteroids/game.manifest.json`.
20+
- Runtime/editor geometry source:
21+
- `game.workspace.tools["object-vector-studio-v2"].objects`
22+
- object IDs such as `object.asteroids.ship` and `object.asteroids.asteroid.small`
23+
- Asteroid collision profiles are now derived from the validated Object Vector payload passed into `AsteroidsGameScene`.
24+
- Preview SVG generation is covered by `ObjectVectorRuntimeAssetService.createSvgString(...)`, which generates SVG from manifest object geometry at runtime.
25+
26+
## Object ID vs Shape ID
27+
28+
- `object.*` IDs remain the runtime/gameplay identity SSoT.
29+
- Shape IDs such as `ship-hull` and `small-asteroid-ridge` remain local editable IDs inside their owning object.
30+
- Shape IDs are used only for local editing and frame override references; they are not promoted to runtime object identity.
31+
32+
## Validation
33+
34+
- PASS - `npm run test:workspace-v2` completed with 49 passing tests.
35+
- PASS - Manifest Object Vector payload validated through `ObjectVectorRuntimeAssetService`.
36+
- PASS - Focused Asteroids transform and collision probes use geometry derived from `game.manifest.json`.
37+
- PASS - Targeted scans found no hardcoded Asteroids SVG constants in `tools/shared`.
38+
- PASS - Targeted scans found no `BASE_VECTOR_MAP` fallback in active Asteroids runtime code.
Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# PR_26133_028 Playwright V8 Coverage Report
1+
# PR_26133_029 Playwright V8 Coverage Report
22

3-
Task: PR_26133_028-remove-vector-map-editor-runtime-dependency
4-
Date: 2026-05-13
3+
Task: PR_26133_029-remove-asteroids-shared-tool-fallbacks
4+
Date: 2026-05-14
55

66
## Result
77

@@ -14,27 +14,27 @@ PASS - Coverage reporting was generated during `npm run test:workspace-v2`.
1414

1515
## Exercised Tool Entry Points
1616

17-
- Workspace Manager V2: 91%, 10 runtime JS files exercised.
18-
- Asset Manager V2: 74%, 13 runtime JS files exercised.
19-
- Preview Generator V2: 82%, 19 runtime JS files exercised.
20-
- Palette Manager V2: 62%, 12 runtime JS files exercised.
21-
- Tool Template V2: not exercised by this Playwright run.
22-
- Workspace Manager: not exercised by this Playwright run.
17+
- Workspace Manager V2: exercised by all 49 tests.
18+
- Object Vector Studio V2: exercised through shell, editing, dirty-state, geometry, and Asteroids runtime-loading flows.
19+
- Asset Manager V2 and Preview Generator V2: exercised by Workspace Manager V2 cross-tool tests.
20+
- Tool Template V2 and legacy Workspace Manager: not targeted by this Playwright run.
2321

2422
## Changed Runtime JS Coverage
2523

26-
- `tools/shared/asteroidsPlatformDemo.js`: not collected by Playwright V8 coverage; covered by focused node probe.
27-
- `tools/shared/vectorAssetSystem.js`: not collected by Playwright V8 coverage; covered by focused node probe.
28-
- Object Vector Studio V2 runtime/editor modules from the prior object-ID path remain covered by the Workspace V2 run.
24+
- `games/Asteroids/game/asteroidObjectGeometry.js`: covered by focused node probes; used by Asteroids scene/world construction.
25+
- `games/Asteroids/entities/Asteroid.js`: covered by focused Asteroids vector-transform and collision probes.
26+
- `games/Asteroids/game/AsteroidsWorld.js`: covered by focused collision timing probes.
27+
- `games/Asteroids/game/AsteroidsGameScene.js` and `games/Asteroids/index.js`: covered by focused validation boot probe and Workspace V2 Asteroids runtime test.
28+
- `tools/shared/vectorAssetSystem.js`: covered by focused node probe.
29+
- `tools/shared/asteroidsPlatformDemo.js`: removed.
2930

3031
## PR-Specific Coverage/Validation Relevance
3132

32-
The workspace-v2 run exercises the Object Vector Studio V2 editor and Asteroids runtime paths affected by this PR:
33+
The Workspace V2 run plus focused probes verify the paths affected by this PR:
3334

34-
- Asteroids workspace hydration without `vector-map-editor`.
35-
- Object Vector Studio V2 loading/editing of Asteroids objects through `object-vector-studio-v2.objects`.
36-
- Asteroids runtime Object Vector rendering through `object.asteroids.*` IDs.
37-
- Workspace save summaries without vector-map-editor tool state.
38-
- Asteroids manifest schema validation after vector-map removal.
35+
- Object Vector Studio V2 remains the editor/source payload for Asteroids geometry.
36+
- Asteroids runtime uses manifest-backed `object.asteroids.*` object IDs.
37+
- Shared tools no longer carry Asteroids-specific SVG fallback constants or the Asteroids platform demo module.
38+
- Shape IDs remain local editable shape IDs inside each object and are not used as runtime object identity.
3939

4040
Generated source report: `docs/dev/reports/playwright_v8_coverage_report.txt`.
Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,36 @@
1-
# PR_26133_028 Workspace V2 Validation
1+
# PR_26133_029 Workspace V2 Validation
22

3-
Task: PR_26133_028-remove-vector-map-editor-runtime-dependency
4-
Date: 2026-05-13
3+
Task: PR_26133_029-remove-asteroids-shared-tool-fallbacks
4+
Date: 2026-05-14
55

66
## Result
77

88
PASS - `npm run test:workspace-v2`
99

1010
- 49 Playwright tests passed.
11-
- Focused Asteroids/Object Vector workspace checks passed before the full run.
12-
- Asteroids manifest schema validation passed after removing the Asteroids `vector-map-editor` payload.
11+
- Object Vector Studio V2 still loads and edits the Asteroids object payload through `tools.object-vector-studio-v2.objects`.
12+
- Asteroids runtime coverage in Workspace Manager V2 still renders Object Vector assets through `object.asteroids.*` object IDs.
1313
- No sample JSON files were changed.
1414

1515
## Targeted Verification
1616

17-
- PASS - Asteroids Workspace Manager V2 context no longer includes `vector-map-editor`.
18-
- PASS - Object Vector Studio V2 still loads the 6 Asteroids objects from `object-vector-studio-v2.objects`.
19-
- PASS - Asteroids runtime renders ship, asteroid, and UFO Object Vector objects through `object.asteroids.*` IDs.
20-
- PASS - Asteroids manifest contains no `vector.asteroids.*` runtime/editor payload.
21-
- PASS - `tools/shared/asteroidsPlatformDemo.js` and `tools/shared/vectorAssetSystem.js` no longer reference Asteroids `vector-map-editor` data.
22-
- PASS - Save summaries no longer include `vector-map-editor vectors=5`.
23-
- PASS - No runtime console/page errors were reported by the targeted Playwright coverage.
17+
- PASS - `tools/shared/asteroidsPlatformDemo.js` was removed.
18+
- PASS - `tools/shared` contains no hardcoded Asteroids SVG constants or Asteroids object-vector fallback data.
19+
- PASS - `games/Asteroids/entities/Asteroid.js` no longer defines `BASE_VECTOR_MAP`.
20+
- PASS - Asteroid collision geometry is derived from the manifest Object Vector payload.
21+
- PASS - Object Vector runtime payload validation loads 6 Asteroids objects from `games/Asteroids/game.manifest.json`.
22+
- PASS - Small, medium, and large asteroid geometry profiles resolve from object IDs while shape IDs remain local shape identifiers.
23+
- PASS - No `vector.asteroids.*` references remain in the active Asteroids runtime/shared-tool validation targets.
2424

2525
## Commands
2626

27-
- PASS - `node --check tools/shared/asteroidsPlatformDemo.js`
27+
- PASS - `node --check games/Asteroids/game/asteroidObjectGeometry.js`
28+
- PASS - `node --check games/Asteroids/entities/Asteroid.js`
29+
- PASS - `node --check games/Asteroids/game/AsteroidsWorld.js`
30+
- PASS - `node --check games/Asteroids/game/AsteroidsGameScene.js`
31+
- PASS - `node --check games/Asteroids/index.js`
2832
- PASS - `node --check tools/shared/vectorAssetSystem.js`
29-
- PASS - `node --check tests/playwright/tools/WorkspaceManagerV2.spec.mjs`
3033
- PASS - `node --check tests/games/AsteroidsPlatformDemo.test.mjs`
31-
- PASS - `node --check tests/games/AsteroidsAssetReferenceAdoption.test.mjs`
32-
- PASS - `node --check tests/tools/VectorAssetSystem.test.mjs`
33-
- PASS - `node --check tests/tools/AssetUsageIntegration.test.mjs`
34-
- PASS - Asteroids manifest schema and runtime object ID probe with `WorkspaceManagerV2ContextService` and `ObjectVectorRuntimeAssetService`.
35-
- PASS - Focused node test probes for Asteroids platform demo, Asteroids asset reference adoption, VectorAssetSystem, and AssetUsageIntegration.
36-
- PASS - `npx playwright test tests/playwright/tools/WorkspaceManagerV2.spec.mjs --project=playwright --workers=1 --reporter=list --grep "header lifecycle|loads Object Vector Studio V2 runtime assets|saves empty Text to Speech|syncs Workspace Manager V2 dirty lifecycle|warns instead of injecting"`
34+
- PASS - focused node probes for Asteroids manifest Object Vector runtime, asteroid vector transforms, collision timing, Asteroids validation boot, and VectorAssetSystem.
35+
- PASS - targeted `rg` scans for removed Asteroids SVG constants, `BASE_VECTOR_MAP`, `vector.asteroids.*`, and shared Asteroids fallback usage.
3736
- PASS - `npm run test:workspace-v2`

games/Asteroids/entities/Asteroid.js

Lines changed: 24 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,40 +7,10 @@ Asteroid.js
77
import { TAU, randomRange, wrap } from '../utils/math.js';
88
import { transformPoints } from '../../../src/engine/rendering/index.js';
99

10-
const BASE_VECTOR_MAP = [
11-
{ x: 10, y: 40 },
12-
{ x: 50, y: 20 },
13-
{ x: 45, y: 5 },
14-
{ x: 25, y: -10 },
15-
{ x: 50, y: -35 },
16-
{ x: 30, y: -45 },
17-
{ x: 10, y: -38 },
18-
{ x: -20, y: -45 },
19-
{ x: -43, y: -18 },
20-
{ x: -43, y: 20 },
21-
{ x: -25, y: 20 },
22-
{ x: -25, y: 40 },
23-
];
24-
25-
function centerVectorMap(points) {
26-
const xs = points.map(({ x }) => x);
27-
const ys = points.map(({ y }) => y);
28-
const centerX = (Math.min(...xs) + Math.max(...xs)) / 2;
29-
const centerY = (Math.min(...ys) + Math.max(...ys)) / 2;
30-
return points.map(({ x, y }) => ({ x: x - centerX, y: y - centerY }));
31-
}
32-
33-
function maxRadius(points) {
34-
return Math.max(...points.map(({ x, y }) => Math.sqrt(x * x + y * y)));
35-
}
36-
37-
const CENTERED_VECTOR_MAP = centerVectorMap(BASE_VECTOR_MAP);
38-
const BASE_RADIUS = maxRadius(CENTERED_VECTOR_MAP);
39-
4010
const SIZE_PROFILES = {
41-
SML: { id: 1, targetRadius: 14 },
42-
MED: { id: 2, targetRadius: 22 },
43-
LRG: { id: 3, targetRadius: 34 },
11+
SML: { id: 1 },
12+
MED: { id: 2 },
13+
LRG: { id: 3 },
4414
};
4515

4616
const SIZE_BY_ID = {
@@ -49,19 +19,32 @@ const SIZE_BY_ID = {
4919
3: SIZE_PROFILES.LRG,
5020
};
5121

22+
function resolveGeometryProfile(geometryProfiles, sizeId) {
23+
if (geometryProfiles instanceof Map) {
24+
return geometryProfiles.get(sizeId) || geometryProfiles.get(String(sizeId)) || null;
25+
}
26+
if (geometryProfiles && typeof geometryProfiles === 'object') {
27+
return geometryProfiles[sizeId] || geometryProfiles[String(sizeId)] || null;
28+
}
29+
return null;
30+
}
31+
5232
export default class Asteroid {
53-
constructor(x, y, size = 3, rng = Math.random) {
33+
constructor(x, y, size = 3, rng = Math.random, geometryProfiles = null) {
5434
const profile = SIZE_BY_ID[size] || SIZE_PROFILES.LRG;
35+
const geometryProfile = resolveGeometryProfile(geometryProfiles, profile.id);
5536
this.x = x;
5637
this.y = y;
5738
this.vx = randomRange(-70, 70, rng);
5839
this.vy = randomRange(-70, 70, rng);
5940
this.angle = randomRange(0, TAU, rng);
6041
this.spin = randomRange(-1.4, 1.4, rng);
6142
this.size = profile.id;
62-
this.sizeLabel = Object.entries(SIZE_PROFILES).find(([, value]) => value.id === profile.id)?.[0] || 'LRG';
63-
this.scale = profile.targetRadius / BASE_RADIUS;
64-
this.radius = profile.targetRadius;
43+
this.sizeLabel = geometryProfile?.label || Object.entries(SIZE_PROFILES).find(([, value]) => value.id === profile.id)?.[0] || 'LRG';
44+
this.objectId = geometryProfile?.objectId || '';
45+
this.collisionPoints = Array.isArray(geometryProfile?.points) ? geometryProfile.points : [];
46+
this.scale = 1;
47+
this.radius = geometryProfile?.radius || 0;
6548
}
6649

6750
update(dtSeconds, bounds) {
@@ -71,7 +54,10 @@ export default class Asteroid {
7154
}
7255

7356
getPoints() {
74-
return transformPoints(CENTERED_VECTOR_MAP, {
57+
if (!this.collisionPoints.length) {
58+
return [];
59+
}
60+
return transformPoints(this.collisionPoints, {
7561
x: this.x,
7662
y: this.y,
7763
rotation: this.angle,

games/Asteroids/game/AsteroidsGameScene.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ import ShipDebrisSystem from '../systems/ShipDebrisSystem.js';
1313
import AsteroidsAttractAdapter from './AsteroidsAttractAdapter.js';
1414
import AsteroidsHighScoreService from '../systems/AsteroidsHighScoreService.js';
1515
import AsteroidsInitialsEntry from '../systems/AsteroidsInitialsEntry.js';
16+
import {
17+
ASTEROID_OBJECT_VECTOR_OBJECT_IDS,
18+
createAsteroidGeometryProfilesFromObjectVectorAssets
19+
} from './asteroidObjectGeometry.js';
1620
import {
1721
ASTEROIDS_GAME_OVER_AUTO_EXIT_SECONDS, ASTEROIDS_GAME_OVER_RETURN_MODE
1822
} from "../rules/flowRules.js";
@@ -25,11 +29,6 @@ const SCORE_TWO_X = 824;
2529
const LIFE_SPACING = 22;
2630
const PAUSE_OVERLAY_COLOR = 'rgba(2, 6, 23, 0.58)';
2731
const INITIALS_OVERLAY_COLOR = 'rgba(1, 6, 19, 0.62)';
28-
const ASTEROID_OBJECT_VECTOR_OBJECT_IDS = Object.freeze({
29-
1: "object.asteroids.asteroid.small",
30-
2: "object.asteroids.asteroid.medium",
31-
3: "object.asteroids.asteroid.large",
32-
});
3332
const UFO_OBJECT_VECTOR_OBJECT_IDS = Object.freeze({
3433
large: "object.asteroids.ufo.large",
3534
small: "object.asteroids.ufo.small",
@@ -115,6 +114,8 @@ export default class AsteroidsGameScene extends Scene {
115114
this.devConsoleIntegration = options.devConsoleIntegration || null;
116115
this.objectVectorAssets = options.objectVectorAssets || null;
117116
this.objectVectorRuntime = options.objectVectorRuntime || null;
117+
this.asteroidGeometryProfiles = options.asteroidGeometryProfiles
118+
|| createAsteroidGeometryProfilesFromObjectVectorAssets(this.objectVectorAssets);
118119
this.objectVectorPlaybackMs = 0;
119120
this.objectVectorRenderCounts = {
120121
asteroids: 0,
@@ -126,7 +127,9 @@ export default class AsteroidsGameScene extends Scene {
126127
debugMode: 'prod',
127128
debugEnabled: Boolean(this.devConsoleIntegration),
128129
};
129-
this.world = new AsteroidsWorld({ width: 960, height: 720 });
130+
this.world = new AsteroidsWorld({ width: 960, height: 720 }, {
131+
asteroidGeometryProfiles: this.asteroidGeometryProfiles
132+
});
130133
this.highScoreService = new AsteroidsHighScoreService();
131134
this.highScoreRows = this.highScoreService.loadTable();
132135
const initialTopScore = this.highScoreService.getTopScore(this.highScoreRows);

games/Asteroids/game/AsteroidsWorld.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,12 @@ function getRectOverlapDepth(x, y, radius, rect) {
136136
}
137137

138138
export default class AsteroidsWorld {
139-
constructor(bounds, { rng = Math.random } = {}) {
139+
constructor(bounds, { rng = Math.random, asteroidGeometryProfiles = null } = {}) {
140140
if (!hasLoggedWorldConstruction) {
141141
hasLoggedWorldConstruction = true;
142142
logWorldBootStage('constructed', bounds);
143143
}
144+
this.asteroidGeometryProfiles = asteroidGeometryProfiles;
144145
this.rng = typeof rng === 'function' ? rng : Math.random;
145146
this.bounds = sanitizeBounds(bounds);
146147
this.starfield = Array.from({ length: 70 }, () => ({
@@ -153,7 +154,7 @@ export default class AsteroidsWorld {
153154
}
154155

155156
createAsteroidEntity(x, y, size = 3) {
156-
return new Asteroid(x, y, size, this.rng);
157+
return new Asteroid(x, y, size, this.rng, this.asteroidGeometryProfiles);
157158
}
158159

159160
createUfoEntity(type = 'large', level = 1) {

0 commit comments

Comments
 (0)