create-aura3d 1.4.3 → 1.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/showcase-spec-artifacts.d.ts +5 -0
- package/dist/showcase-spec-artifacts.d.ts.map +1 -1
- package/dist/showcase-spec-artifacts.js +11 -2
- package/dist/showcase-spec-artifacts.js.map +1 -1
- package/dist/showcase-spec-asset-pair-composition.d.ts +116 -0
- package/dist/showcase-spec-asset-pair-composition.d.ts.map +1 -0
- package/dist/showcase-spec-asset-pair-composition.js +336 -0
- package/dist/showcase-spec-asset-pair-composition.js.map +1 -0
- package/dist/showcase-spec-compiler.d.ts.map +1 -1
- package/dist/showcase-spec-compiler.js +149 -10
- package/dist/showcase-spec-compiler.js.map +1 -1
- package/dist/showcase-spec-composition-evidence.d.ts +14 -0
- package/dist/showcase-spec-composition-evidence.d.ts.map +1 -0
- package/dist/showcase-spec-composition-evidence.js +123 -0
- package/dist/showcase-spec-composition-evidence.js.map +1 -0
- package/dist/showcase-spec-evidence.js +50 -1
- package/dist/showcase-spec-evidence.js.map +1 -1
- package/dist/showcase-spec-game-geometry-extractor.d.ts +4 -2
- package/dist/showcase-spec-game-geometry-extractor.d.ts.map +1 -1
- package/dist/showcase-spec-game-geometry-extractor.js +260 -30
- package/dist/showcase-spec-game-geometry-extractor.js.map +1 -1
- package/dist/showcase-spec-game-geometry-probe.d.ts +20 -0
- package/dist/showcase-spec-game-geometry-probe.d.ts.map +1 -0
- package/dist/showcase-spec-game-geometry-probe.js +16 -0
- package/dist/showcase-spec-game-geometry-probe.js.map +1 -0
- package/dist/showcase-spec-game-replacement-evidence.js +7 -3
- package/dist/showcase-spec-game-replacement-evidence.js.map +1 -1
- package/dist/showcase-spec-game-scene-scale.d.ts +10 -0
- package/dist/showcase-spec-game-scene-scale.d.ts.map +1 -0
- package/dist/showcase-spec-game-scene-scale.js +71 -0
- package/dist/showcase-spec-game-scene-scale.js.map +1 -0
- package/dist/showcase-spec-game-template-evidence.d.ts +10 -0
- package/dist/showcase-spec-game-template-evidence.d.ts.map +1 -1
- package/dist/showcase-spec-game-template-evidence.js +50 -7
- package/dist/showcase-spec-game-template-evidence.js.map +1 -1
- package/dist/showcase-spec-gameplay-evidence.js +4 -3
- package/dist/showcase-spec-gameplay-evidence.js.map +1 -1
- package/dist/showcase-spec-parser.d.ts.map +1 -1
- package/dist/showcase-spec-parser.js +3 -0
- package/dist/showcase-spec-parser.js.map +1 -1
- package/dist/showcase-spec-platformer-artifacts.d.ts +1 -0
- package/dist/showcase-spec-platformer-artifacts.d.ts.map +1 -1
- package/dist/showcase-spec-platformer-artifacts.js +188 -56
- package/dist/showcase-spec-platformer-artifacts.js.map +1 -1
- package/dist/showcase-spec-racing-artifacts.d.ts +1 -0
- package/dist/showcase-spec-racing-artifacts.d.ts.map +1 -1
- package/dist/showcase-spec-racing-artifacts.js +208 -31
- package/dist/showcase-spec-racing-artifacts.js.map +1 -1
- package/dist/showcase-spec-replacement-candidates.js +2 -1
- package/dist/showcase-spec-replacement-candidates.js.map +1 -1
- package/dist/showcase-spec-types.d.ts +22 -0
- package/dist/showcase-spec-types.d.ts.map +1 -1
- package/package.json +2 -2
- package/templates/animation-channel/package.json +1 -1
- package/templates/animation-studio/package.json +5 -5
- package/templates/character-controller/package.json +3 -3
- package/templates/cinematic-scene/package.json +1 -1
- package/templates/episode-builder/package.json +1 -1
- package/templates/falling-blocks-starter/package.json +1 -1
- package/templates/fighting-game/package.json +1 -1
- package/templates/mini-game/package.json +1 -1
- package/templates/product-viewer/package.json +1 -1
- package/templates/prompt-animation-channel/package.json +1 -1
- package/templates/racing-starter/package.json +1 -1
- package/templates/racing-starter/src/main.ts +2 -2
- package/templates/three-compat-architecture-interior/package.json +1 -1
- package/templates/three-compat-asset-inspector/package.json +1 -1
- package/templates/three-compat-character-viewer/package.json +1 -1
- package/templates/three-compat-custom-threejs-migration/package.json +1 -1
- package/templates/three-compat-large-scene/package.json +1 -1
- package/templates/three-compat-material-authoring/package.json +1 -1
- package/templates/three-compat-postprocess-scene/package.json +1 -1
- package/templates/three-compat-premium-product-viewer/package.json +1 -1
|
@@ -1,29 +1,60 @@
|
|
|
1
1
|
import { createPlatformerTemplatePlan } from "./showcase-spec-game-template-evidence.js";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import { platformerSceneScale } from "./showcase-spec-game-scene-scale.js";
|
|
3
|
+
export function createPlatformerGeometryContractSource(spec, platformer) {
|
|
4
4
|
const templatePlan = createPlatformerTemplatePlan(spec, platformer);
|
|
5
5
|
const { playableSurfaceMap: _playableSurfaceMap, ...levelPlan } = templatePlan;
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
const surfaceMap = templatePlan.playableSurfaceMap;
|
|
7
|
+
const minX = Math.min(...surfaceMap.surfaces.map((surface) => surface.x - surface.width / 2));
|
|
8
|
+
const maxX = Math.max(...surfaceMap.surfaces.map((surface) => surface.x + surface.width / 2));
|
|
9
|
+
const minY = Math.min(...surfaceMap.surfaces.map((surface) => surface.y));
|
|
10
|
+
const maxY = Math.max(...surfaceMap.surfaces.map((surface) => surface.y + surface.height));
|
|
11
|
+
const contract = {
|
|
12
|
+
schema: "aura3d-game-geometry-contract/1.0",
|
|
13
|
+
routeId: spec.routeId,
|
|
14
|
+
category: "platformer",
|
|
15
|
+
geometrySource: surfaceMap.source,
|
|
16
|
+
sourceReport: platformer.levelDesign.playableSurfaceEvidence,
|
|
17
|
+
surfaceMap: templatePlan.playableSurfaceMap,
|
|
18
|
+
worldAssetBindings: platformer.worldAssets.map((assetId) => ({
|
|
19
|
+
worldAsset: assetId,
|
|
20
|
+
...(assetId === templatePlan.playableSurfaceMap.assetId
|
|
21
|
+
? {
|
|
22
|
+
worldAssetHash: templatePlan.playableSurfaceMap.assetHash,
|
|
23
|
+
surfaceSource: templatePlan.playableSurfaceMap.source,
|
|
24
|
+
confidence: templatePlan.playableSurfaceMap.confidence
|
|
25
|
+
}
|
|
26
|
+
: {}),
|
|
27
|
+
surfaceIds: templatePlan.platforms
|
|
28
|
+
.filter((surface) => surface.worldAsset === assetId)
|
|
29
|
+
.map((surface) => surface.id)
|
|
30
|
+
})),
|
|
31
|
+
level: {
|
|
32
|
+
...levelPlan,
|
|
33
|
+
platforms: templatePlan.platforms.map(({ id, x, y, width, height }) => ({ id, x, y, width, height }))
|
|
34
|
+
},
|
|
35
|
+
authoredSeconds: platformer.levelDesign.minPlayableSeconds,
|
|
36
|
+
cameraBounds: { minX: minX - 0.8, maxX: maxX + 0.8, minY: minY - 0.8, maxY: maxY + 0.8 },
|
|
37
|
+
evidence: {
|
|
38
|
+
geometryReport: platformer.levelDesign.playableSurfaceEvidence,
|
|
39
|
+
routePrimaryScreenshot: platformer.levelDesign.assetPairEvidence?.screenshotEvidence,
|
|
40
|
+
routePrimaryScreenshotSha256: platformer.levelDesign.assetPairEvidence?.screenshotSha256
|
|
41
|
+
},
|
|
42
|
+
design: platformer.levelDesign
|
|
9
43
|
};
|
|
44
|
+
return `// Generated by the Aura3D showcase spec compiler. Do not edit.
|
|
45
|
+
export const gameGeometryContract = ${JSON.stringify(contract, null, 2)} as const;
|
|
46
|
+
`;
|
|
47
|
+
}
|
|
48
|
+
export function createPlatformerRouteSource(spec, platformer) {
|
|
49
|
+
const characterAsset = requireAsset(spec, platformer.characterAsset);
|
|
50
|
+
const templatePlan = createPlatformerTemplatePlan(spec, platformer);
|
|
10
51
|
const playableSurfaceMap = templatePlan.playableSurfaceMap;
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
...(assetId === playableSurfaceMap.assetId
|
|
15
|
-
? {
|
|
16
|
-
worldAssetHash: playableSurfaceMap.assetHash,
|
|
17
|
-
surfaceSource: playableSurfaceMap.source,
|
|
18
|
-
confidence: playableSurfaceMap.confidence
|
|
19
|
-
}
|
|
20
|
-
: {}),
|
|
21
|
-
surfaceIds: templatePlan.platforms
|
|
22
|
-
.filter((platform) => platform.worldAsset === assetId)
|
|
23
|
-
.map((platform) => platform.id)
|
|
24
|
-
}));
|
|
52
|
+
const sceneScale = platformerSceneScale(playableSurfaceMap);
|
|
53
|
+
const worldAsset = requireAsset(spec, playableSurfaceMap.assetId);
|
|
54
|
+
const panelMarkup = createPlatformerPanelMarkup(spec);
|
|
25
55
|
return `import { createAuraApp, game, lights, model, scene } from "@aura3d/engine";
|
|
26
56
|
import { assets } from "../../../src/aura-assets";
|
|
57
|
+
import { gameGeometryContract } from "./generated/game-geometry";
|
|
27
58
|
|
|
28
59
|
const input = game.input({
|
|
29
60
|
actions: {
|
|
@@ -35,52 +66,59 @@ const input = game.input({
|
|
|
35
66
|
axes: { moveX: { negative: "left", positive: "right" } },
|
|
36
67
|
bufferMs: 120
|
|
37
68
|
});
|
|
38
|
-
const authoredPlayableSeconds =
|
|
39
|
-
const playableSurfaceMap =
|
|
69
|
+
const authoredPlayableSeconds = gameGeometryContract.authoredSeconds;
|
|
70
|
+
const playableSurfaceMap = gameGeometryContract.surfaceMap;
|
|
40
71
|
const level = game.assetBoundPlatformerLevel({
|
|
41
72
|
characterAsset: "${platformer.characterAsset}",
|
|
42
|
-
worldAssetBindings:
|
|
73
|
+
worldAssetBindings: gameGeometryContract.worldAssetBindings,
|
|
43
74
|
playableSurfaceMap,
|
|
75
|
+
authoredPlayableSeconds,
|
|
44
76
|
minPlayableSeconds: ${platformer.levelDesign.minPlayableSeconds},
|
|
45
77
|
minCheckpoints: ${platformer.levelDesign.minCheckpoints},
|
|
46
|
-
level:
|
|
78
|
+
level: gameGeometryContract.level
|
|
47
79
|
});
|
|
48
80
|
const platformerScene = game.platformerSceneBinding({
|
|
49
81
|
surfaceMap: playableSurfaceMap,
|
|
50
82
|
level,
|
|
51
83
|
worldAsset: "${playableSurfaceMap.assetId}",
|
|
52
|
-
targetSceneWidth:
|
|
53
|
-
worldModelTargetMaxDimension:
|
|
84
|
+
targetSceneWidth: ${sceneScale.targetSceneWidth},
|
|
85
|
+
worldModelTargetMaxDimension: ${sceneScale.worldModelTargetMaxDimension},
|
|
54
86
|
worldY: -0.72,
|
|
55
87
|
worldZ: -0.46,
|
|
56
88
|
playerZ: 0.42,
|
|
57
|
-
playerTargetHeight: 0.
|
|
58
|
-
playerYOffset: 0
|
|
89
|
+
playerTargetHeight: 0.44,
|
|
90
|
+
playerYOffset: 0
|
|
59
91
|
});
|
|
92
|
+
const platforms = level.platforms ?? [];
|
|
93
|
+
const checkpoints = level.checkpoints ?? [];
|
|
94
|
+
const hazards = level.hazards ?? [];
|
|
95
|
+
const characterScaleRatio = level.assetBinding.characterScaleRatio ?? 1;
|
|
60
96
|
const platformerState = game.platformer(level);
|
|
61
97
|
let state = platformerState.snapshot();
|
|
62
98
|
const initialPlayerPose = platformerScene.toScenePlayer(state.player);
|
|
99
|
+
let playerFacing = 1;
|
|
100
|
+
const playerYawForFacing = (facing: number) => facing >= 0 ? Math.PI / 2 : -Math.PI / 2;
|
|
63
101
|
let frameCount = 0;
|
|
64
102
|
|
|
65
103
|
const completionProof = {
|
|
66
104
|
completed: true,
|
|
67
105
|
stable: true,
|
|
68
106
|
finalTime: level.assetBinding.authoredPlayableSeconds,
|
|
69
|
-
checkpoints:
|
|
107
|
+
checkpoints: checkpoints.map((checkpoint) => checkpoint.id),
|
|
70
108
|
eventCounts: {
|
|
71
|
-
respawn:
|
|
109
|
+
respawn: hazards.length > 0 ? 1 : 0,
|
|
72
110
|
finish: level.finish ? 1 : 0
|
|
73
111
|
}
|
|
74
112
|
};
|
|
75
113
|
const kitContractProof = {
|
|
76
114
|
movementChangesPosition: false,
|
|
77
115
|
jumpChangesVerticalState: false,
|
|
78
|
-
checkpointOrProgression:
|
|
79
|
-
hazardRespawnOrRetry:
|
|
116
|
+
checkpointOrProgression: checkpoints.length >= ${platformer.levelDesign.minCheckpoints},
|
|
117
|
+
hazardRespawnOrRetry: hazards.length > 0,
|
|
80
118
|
finishProgression: Boolean(level.finish),
|
|
81
|
-
checkpointEvent:
|
|
82
|
-
hazardEvent:
|
|
83
|
-
respawnEvent:
|
|
119
|
+
checkpointEvent: checkpoints.length >= ${platformer.levelDesign.minCheckpoints},
|
|
120
|
+
hazardEvent: hazards.length > 0,
|
|
121
|
+
respawnEvent: hazards.length > 0,
|
|
84
122
|
finishEvent: Boolean(level.finish),
|
|
85
123
|
resetRestoresStart: false
|
|
86
124
|
};
|
|
@@ -88,13 +126,34 @@ const animationStateHistory = [{ state: "idle" }];
|
|
|
88
126
|
function round(value: number): number {
|
|
89
127
|
return Math.round(value * 1000) / 1000;
|
|
90
128
|
}
|
|
129
|
+
const platformerCamera = game.platformerCameraRig({
|
|
130
|
+
sceneBinding: platformerScene,
|
|
131
|
+
player: state.player,
|
|
132
|
+
mode: "follow",
|
|
133
|
+
targetNode: "platformer-player",
|
|
134
|
+
distance: 3.7,
|
|
135
|
+
height: 0.52,
|
|
136
|
+
lookAhead: 0.7,
|
|
137
|
+
fov: 40
|
|
138
|
+
});
|
|
139
|
+
setupPlatformerPanel();
|
|
91
140
|
|
|
92
141
|
const app = createAuraApp("#app", {
|
|
93
142
|
diagnostics: { overlay: false, performancePanel: false },
|
|
94
143
|
scene: scene()
|
|
95
|
-
.
|
|
144
|
+
.add(model(${worldAsset.typedRef}, {
|
|
145
|
+
name: "platformer-bound-world-asset",
|
|
146
|
+
role: "primaryWorld",
|
|
147
|
+
scaleMode: "fit",
|
|
148
|
+
targetMaxDimension: platformerScene.worldModel.targetMaxDimension
|
|
149
|
+
}).position(...platformerScene.worldModel.position).rotate(...platformerScene.worldModel.rotation).runtime(game.runtimeNode("platformer-bound-world-asset", {
|
|
150
|
+
tags: ["world", "typed-secondary-primary-asset", "certified-visible-geometry"]
|
|
151
|
+
})))
|
|
152
|
+
.addMany(game.platformerPresentationSurfaces({
|
|
96
153
|
sceneBinding: platformerScene,
|
|
97
154
|
level,
|
|
155
|
+
mode: "asset-overlay",
|
|
156
|
+
guideVisibility: "public",
|
|
98
157
|
platformColor: "#526972",
|
|
99
158
|
platformTrimColor: "#b7f3ff",
|
|
100
159
|
hazardColor: "#ff6978",
|
|
@@ -105,26 +164,42 @@ const app = createAuraApp("#app", {
|
|
|
105
164
|
name: "platformer-readable-character",
|
|
106
165
|
role: "primaryCharacter",
|
|
107
166
|
scaleMode: "fit",
|
|
108
|
-
targetHeight: 0.
|
|
109
|
-
}).position(...initialPlayerPose.position).runtime(game.runtimeNode("platformer-player", {
|
|
167
|
+
targetHeight: 0.44
|
|
168
|
+
}).position(...initialPlayerPose.position).rotate(0, playerYawForFacing(playerFacing), 0).runtime(game.runtimeNode("platformer-player", {
|
|
110
169
|
tags: ["player", "character", "typed-primary-asset"]
|
|
111
170
|
})))
|
|
112
|
-
.add(lights.studio())
|
|
113
|
-
.camera(
|
|
114
|
-
sceneBinding: platformerScene,
|
|
115
|
-
player: state.player,
|
|
116
|
-
mode: "follow",
|
|
117
|
-
targetNode: "platformer-player",
|
|
118
|
-
distance: 4.15,
|
|
119
|
-
height: 0.44,
|
|
120
|
-
lookAhead: 0.72,
|
|
121
|
-
fov: 41
|
|
122
|
-
}))
|
|
171
|
+
.add(lights.studio({ intensity: 1.5 }))
|
|
172
|
+
.camera(platformerCamera)
|
|
123
173
|
});
|
|
124
174
|
|
|
125
175
|
const player = app.nodes.require("platformer-player");
|
|
176
|
+
Object.defineProperty(window, "__AURA3D_COMPOSITION_PROBE__", {
|
|
177
|
+
value: {
|
|
178
|
+
category: "platformer",
|
|
179
|
+
camera: platformerCamera,
|
|
180
|
+
subject: { position: initialPlayerPose.position, rotation: [0, 0, 0], targetSize: 0.44 },
|
|
181
|
+
playSpacePoints: platforms.flatMap((surface) => [
|
|
182
|
+
platformerScene.toScenePoint({ x: surface.x, y: surface.y + surface.height }),
|
|
183
|
+
platformerScene.toScenePoint({ x: surface.x + surface.width, y: surface.y + surface.height })
|
|
184
|
+
]),
|
|
185
|
+
contactPoint: platformerScene.contactPointForPlayer(state.player),
|
|
186
|
+
setSubjectSuppressed: (suppressed: boolean) => {
|
|
187
|
+
app.pause();
|
|
188
|
+
player.setScale(suppressed ? 0.0001 : 1);
|
|
189
|
+
app.step(0);
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
configurable: true
|
|
193
|
+
});
|
|
194
|
+
const hud = {
|
|
195
|
+
x: requireElement("x-value"),
|
|
196
|
+
score: requireElement("score-value"),
|
|
197
|
+
deaths: requireElement("death-value"),
|
|
198
|
+
checkpoint: requireElement("checkpoint-value"),
|
|
199
|
+
surface: requireElement("surface-value")
|
|
200
|
+
};
|
|
126
201
|
function readAnimationState(): string {
|
|
127
|
-
if (state.events.some((event) => event.type === "
|
|
202
|
+
if (state.events.some((event) => event.type === "hazard")) return "hit";
|
|
128
203
|
if (state.player.vy > 0.05) return "jump";
|
|
129
204
|
if (state.player.vy < -0.05) return "fall";
|
|
130
205
|
if (Math.abs(state.player.vx) > 0.01) return "run";
|
|
@@ -136,7 +211,7 @@ function rememberAnimationState(): void {
|
|
|
136
211
|
if (lastState !== nextState) animationStateHistory.push({ state: nextState });
|
|
137
212
|
}
|
|
138
213
|
function playerSurfaceAlignment() {
|
|
139
|
-
const standingSurface =
|
|
214
|
+
const standingSurface = platforms.find((surface) => {
|
|
140
215
|
const minX = surface.x - 0.04;
|
|
141
216
|
const maxX = surface.x + surface.width + 0.04;
|
|
142
217
|
const surfaceTop = surface.y + surface.height;
|
|
@@ -159,7 +234,9 @@ function routeDiagnostics() {
|
|
|
159
234
|
snapshot: {
|
|
160
235
|
x: state.player.x,
|
|
161
236
|
y: state.player.y,
|
|
162
|
-
vy: state.player.vy
|
|
237
|
+
vy: state.player.vy,
|
|
238
|
+
facing: playerFacing,
|
|
239
|
+
facingYaw: playerYawForFacing(playerFacing)
|
|
163
240
|
},
|
|
164
241
|
sceneBinding: platformerScene.evidence,
|
|
165
242
|
surfaceContact: platformerScene.contactPointForPlayer(state.player),
|
|
@@ -172,6 +249,10 @@ const mountedEvidence = {
|
|
|
172
249
|
schema: "aura3d-showcase-compiled-platformer-route/1.1",
|
|
173
250
|
appId: "${spec.routeId}",
|
|
174
251
|
status: "ready",
|
|
252
|
+
controls: { keyboard: ["ArrowLeft", "ArrowRight", "KeyA", "KeyD", "Space", "ArrowUp", "KeyW", "KeyR"] },
|
|
253
|
+
systems: { input: "game.input", simulation: "game.platformer", geometry: "certified-platformer-surfaces", camera: "game.platformerCameraRig" },
|
|
254
|
+
claimBoundary: "Bounded certified-surface platformer presentation; no physics-engine, automatic GLB-to-game, or unsupported skinned-animation claim.",
|
|
255
|
+
platformerStateStatus: state.status,
|
|
175
256
|
frameCount,
|
|
176
257
|
score: state.score,
|
|
177
258
|
coins: state.collected.length,
|
|
@@ -186,13 +267,14 @@ const mountedEvidence = {
|
|
|
186
267
|
levelDesign: {
|
|
187
268
|
authoredPlayableSeconds: level.assetBinding.authoredPlayableSeconds,
|
|
188
269
|
minimumMeaningfulPlaySeconds: ${platformer.levelDesign.minPlayableSeconds},
|
|
189
|
-
surfaceCount:
|
|
270
|
+
surfaceCount: platforms.length,
|
|
190
271
|
styleCompatible: true,
|
|
191
|
-
scaleCompatible:
|
|
272
|
+
scaleCompatible: characterScaleRatio > 0 && characterScaleRatio <= 1,
|
|
192
273
|
surfaceContactProven: initialSurfaceAlignment.feetOnSurface,
|
|
193
274
|
visibleGameGeometrySource: "surface-map-bound-game-level",
|
|
194
275
|
worldAssetUsedForSurfaceEvidence: "${playableSurfaceMap.assetId}",
|
|
195
|
-
|
|
276
|
+
noDebugSurfaceGuides: true,
|
|
277
|
+
visualReviewPass: ${spec.evidence.visualReviewPassed === true}
|
|
196
278
|
},
|
|
197
279
|
primaryAssets: [${spec.primaryAssets.map((asset) => `"${asset.id}"`).join(", ")}],
|
|
198
280
|
platformer: {
|
|
@@ -200,7 +282,7 @@ const mountedEvidence = {
|
|
|
200
282
|
characterAsset: "${platformer.characterAsset}",
|
|
201
283
|
worldAssets: [${platformer.worldAssets.map((assetId) => `"${assetId}"`).join(", ")}],
|
|
202
284
|
gameplayRequirements: [${platformer.gameplayRequirements.map((requirement) => `"${requirement}"`).join(", ")}],
|
|
203
|
-
levelDesign:
|
|
285
|
+
levelDesign: gameGeometryContract.design,
|
|
204
286
|
playableSurfaceMap,
|
|
205
287
|
assetBinding: level.assetBinding,
|
|
206
288
|
sceneBinding: platformerScene.evidence
|
|
@@ -217,12 +299,16 @@ const mountedEvidence = {
|
|
|
217
299
|
}
|
|
218
300
|
};
|
|
219
301
|
Object.defineProperty(window, "${spec.globalName}", { value: mountedEvidence, configurable: true, writable: true });
|
|
302
|
+
updatePlatformerHud();
|
|
220
303
|
|
|
221
304
|
function publishPlatformerEvidence(): void {
|
|
222
305
|
rememberAnimationState();
|
|
223
306
|
const scenePlayer = platformerScene.toScenePlayer(state.player);
|
|
307
|
+
if (Math.abs(state.player.vx) > 0.01) playerFacing = state.player.vx >= 0 ? 1 : -1;
|
|
224
308
|
player.setPosition(...scenePlayer.position);
|
|
225
|
-
|
|
309
|
+
player.setRotation(0, playerYawForFacing(playerFacing), 0);
|
|
310
|
+
mountedEvidence.status = "running";
|
|
311
|
+
mountedEvidence.platformerStateStatus = state.status;
|
|
226
312
|
mountedEvidence.frameCount = frameCount;
|
|
227
313
|
mountedEvidence.score = state.score;
|
|
228
314
|
mountedEvidence.coins = state.collected.length;
|
|
@@ -233,6 +319,7 @@ function publishPlatformerEvidence(): void {
|
|
|
233
319
|
sampleFrame: frameCount
|
|
234
320
|
};
|
|
235
321
|
mountedEvidence.diagnostics = routeDiagnostics();
|
|
322
|
+
updatePlatformerHud();
|
|
236
323
|
}
|
|
237
324
|
|
|
238
325
|
app.onFrame(({ dt }) => {
|
|
@@ -240,6 +327,7 @@ app.onFrame(({ dt }) => {
|
|
|
240
327
|
input.update(step);
|
|
241
328
|
if (input.pressed("reset")) {
|
|
242
329
|
state = platformerState.reset();
|
|
330
|
+
playerFacing = 1;
|
|
243
331
|
frameCount += 1;
|
|
244
332
|
mountedEvidence.gameplay.resetWorks = true;
|
|
245
333
|
kitContractProof.resetRestoresStart = state.checkpointId === "start" && state.collected.length === 0;
|
|
@@ -263,8 +351,52 @@ app.onFrame(({ dt }) => {
|
|
|
263
351
|
kitContractProof.jumpChangesVerticalState ||= mountedEvidence.gameplay.jumpChangesY || Math.abs(state.player.vy) > 0.05;
|
|
264
352
|
publishPlatformerEvidence();
|
|
265
353
|
});
|
|
354
|
+
|
|
355
|
+
function setupPlatformerPanel(): void {
|
|
356
|
+
const panel = document.getElementById("panel");
|
|
357
|
+
if (!panel) return;
|
|
358
|
+
panel.innerHTML = ${JSON.stringify(panelMarkup)};
|
|
359
|
+
bindHoldControl("left-control", "KeyA");
|
|
360
|
+
bindHoldControl("right-control", "KeyD");
|
|
361
|
+
document.getElementById("jump-control")?.addEventListener("click", () => pulseKey("Space"));
|
|
362
|
+
document.getElementById("reset-control")?.addEventListener("click", () => pulseKey("KeyR"));
|
|
363
|
+
}
|
|
364
|
+
function bindHoldControl(id: string, code: string): void {
|
|
365
|
+
const button = document.getElementById(id);
|
|
366
|
+
if (!button) return;
|
|
367
|
+
const release = () => window.dispatchEvent(new KeyboardEvent("keyup", { code, bubbles: true }));
|
|
368
|
+
button.addEventListener("pointerdown", () => window.dispatchEvent(new KeyboardEvent("keydown", { code, bubbles: true })));
|
|
369
|
+
button.addEventListener("pointerup", release);
|
|
370
|
+
button.addEventListener("pointercancel", release);
|
|
371
|
+
button.addEventListener("pointerleave", release);
|
|
372
|
+
}
|
|
373
|
+
function pulseKey(code: string): void {
|
|
374
|
+
window.dispatchEvent(new KeyboardEvent("keydown", { code, bubbles: true }));
|
|
375
|
+
window.setTimeout(() => window.dispatchEvent(new KeyboardEvent("keyup", { code, bubbles: true })), 40);
|
|
376
|
+
}
|
|
377
|
+
function updatePlatformerHud(): void {
|
|
378
|
+
hud.x.textContent = round(state.player.x).toFixed(2);
|
|
379
|
+
hud.score.textContent = String(state.score);
|
|
380
|
+
hud.deaths.textContent = String(state.deaths);
|
|
381
|
+
hud.checkpoint.textContent = state.checkpointId;
|
|
382
|
+
const alignment = playerSurfaceAlignment();
|
|
383
|
+
hud.surface.textContent = alignment.feetOnSurface ? "Grounded on " + alignment.surfaceId : "Airborne";
|
|
384
|
+
}
|
|
385
|
+
function requireElement(id: string): HTMLElement {
|
|
386
|
+
const element = document.getElementById(id);
|
|
387
|
+
if (!element) throw new Error("Missing element #" + id);
|
|
388
|
+
return element;
|
|
389
|
+
}
|
|
266
390
|
`;
|
|
267
391
|
}
|
|
392
|
+
function createPlatformerPanelMarkup(spec) {
|
|
393
|
+
return `<span class="label">Certified surface route</span>
|
|
394
|
+
<h1>${spec.label}</h1>
|
|
395
|
+
<p class="claim">Run across a mesh-derived verdant course with checkpoints, collectibles, a hazard retry, and a finish state.</p>
|
|
396
|
+
<section class="panel-metrics" aria-label="Live runner metrics"><div class="metrics-row"><article><span>X</span><strong id="x-value">0.00</strong></article><article><span>Score</span><strong id="score-value">0</strong></article><article><span>Deaths</span><strong id="death-value">0</strong></article><article><span>Checkpoint</span><strong id="checkpoint-value">start</strong></article></div><div class="objective" id="surface-value">Finding surface…</div></section>
|
|
397
|
+
<section aria-label="Runner controls"><h2>Run the route</h2><div class="button-grid"><button id="left-control" type="button">Move left</button><button id="right-control" type="button">Move right</button><button id="jump-control" type="button">Jump</button><button id="reset-control" type="button">Reset</button></div><ul class="controls-list"><li>Use A / D or arrow keys to move.</li><li>Press W, Up, or Space to jump.</li><li>Press R to restart from the beginning.</li></ul></section>
|
|
398
|
+
<section aria-label="Geometry contract"><h2>Surface contract</h2><p class="claim">The visible world and player contacts share the same hash-bound mesh extraction transform.</p></section>`;
|
|
399
|
+
}
|
|
268
400
|
function requireAsset(spec, assetId) {
|
|
269
401
|
const asset = spec.primaryAssets.find((candidate) => candidate.id === assetId);
|
|
270
402
|
if (!asset)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"showcase-spec-platformer-artifacts.js","sourceRoot":"","sources":["../../../../packages/create-aura3d/src/showcase-spec-platformer-artifacts.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,4BAA4B,EAAE,MAAM,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"showcase-spec-platformer-artifacts.js","sourceRoot":"","sources":["../../../../packages/create-aura3d/src/showcase-spec-platformer-artifacts.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { ShowcaseRacingSpec, ShowcaseSpec } from "./showcase-spec-types.js";
|
|
2
|
+
export declare function createRacingGeometryContractSource(spec: ShowcaseSpec, racing: ShowcaseRacingSpec): string;
|
|
2
3
|
export declare function createRacingRouteSource(spec: ShowcaseSpec, racing: ShowcaseRacingSpec): string;
|
|
3
4
|
//# sourceMappingURL=showcase-spec-racing-artifacts.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"showcase-spec-racing-artifacts.d.ts","sourceRoot":"","sources":["../../../../packages/create-aura3d/src/showcase-spec-racing-artifacts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EAEb,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"showcase-spec-racing-artifacts.d.ts","sourceRoot":"","sources":["../../../../packages/create-aura3d/src/showcase-spec-racing-artifacts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EAEb,MAAM,0BAA0B,CAAC;AAIlC,wBAAgB,kCAAkC,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAuDzG;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAmX9F"}
|