@aura3d/engine 1.3.3 → 1.4.1
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 +138 -15
- package/dist/assets/GLTFLoader.js +1 -0
- package/dist/assets/GLTFLoader.js.map +1 -1
- package/dist/assets/GLTFRenderResources.d.ts.map +1 -1
- package/dist/assets/GLTFRenderResources.js +1 -0
- package/dist/assets/GLTFRenderResources.js.map +1 -1
- package/dist/aura3d-cli/asset-constants.d.ts +5 -0
- package/dist/aura3d-cli/asset-constants.d.ts.map +1 -0
- package/dist/aura3d-cli/asset-constants.js +5 -0
- package/dist/aura3d-cli/asset-constants.js.map +1 -0
- package/dist/aura3d-cli/asset-core-types.d.ts +222 -0
- package/dist/aura3d-cli/asset-core-types.d.ts.map +1 -0
- package/dist/aura3d-cli/asset-core-types.js +2 -0
- package/dist/aura3d-cli/asset-core-types.js.map +1 -0
- package/dist/aura3d-cli/asset-inspection-types.d.ts +131 -0
- package/dist/aura3d-cli/asset-inspection-types.d.ts.map +1 -0
- package/dist/aura3d-cli/asset-inspection-types.js +2 -0
- package/dist/aura3d-cli/asset-inspection-types.js.map +1 -0
- package/dist/aura3d-cli/asset-manifest.d.ts +8 -0
- package/dist/aura3d-cli/asset-manifest.d.ts.map +1 -0
- package/dist/aura3d-cli/asset-manifest.js +116 -0
- package/dist/aura3d-cli/asset-manifest.js.map +1 -0
- package/dist/aura3d-cli/asset-readiness-types.d.ts +164 -0
- package/dist/aura3d-cli/asset-readiness-types.d.ts.map +1 -0
- package/dist/aura3d-cli/asset-readiness-types.js +2 -0
- package/dist/aura3d-cli/asset-readiness-types.js.map +1 -0
- package/dist/aura3d-cli/asset-source-ast.d.ts +8 -0
- package/dist/aura3d-cli/asset-source-ast.d.ts.map +1 -0
- package/dist/aura3d-cli/asset-source-ast.js +241 -0
- package/dist/aura3d-cli/asset-source-ast.js.map +1 -0
- package/dist/aura3d-cli/asset-source-roles.d.ts +4 -0
- package/dist/aura3d-cli/asset-source-roles.d.ts.map +1 -0
- package/dist/aura3d-cli/asset-source-roles.js +79 -0
- package/dist/aura3d-cli/asset-source-roles.js.map +1 -0
- package/dist/aura3d-cli/asset-source-validation.d.ts +4 -0
- package/dist/aura3d-cli/asset-source-validation.d.ts.map +1 -0
- package/dist/aura3d-cli/asset-source-validation.js +200 -0
- package/dist/aura3d-cli/asset-source-validation.js.map +1 -0
- package/dist/aura3d-cli/character-assembly-types.d.ts +39 -0
- package/dist/aura3d-cli/character-assembly-types.d.ts.map +1 -0
- package/dist/aura3d-cli/character-assembly-types.js +2 -0
- package/dist/aura3d-cli/character-assembly-types.js.map +1 -0
- package/dist/aura3d-cli/cli-help.d.ts +4 -0
- package/dist/aura3d-cli/cli-help.d.ts.map +1 -0
- package/dist/aura3d-cli/cli-help.js +48 -0
- package/dist/aura3d-cli/cli-help.js.map +1 -0
- package/dist/aura3d-cli/cli-options.d.ts +66 -0
- package/dist/aura3d-cli/cli-options.d.ts.map +1 -0
- package/dist/aura3d-cli/cli-options.js +234 -0
- package/dist/aura3d-cli/cli-options.js.map +1 -0
- package/dist/aura3d-cli/cli.js +20 -177
- package/dist/aura3d-cli/cli.js.map +1 -1
- package/dist/aura3d-cli/index.d.ts +12 -402
- package/dist/aura3d-cli/index.d.ts.map +1 -1
- package/dist/aura3d-cli/index.js +948 -90
- package/dist/aura3d-cli/index.js.map +1 -1
- package/dist/aura3d-cli/pull-bridge/adapters.d.ts +4 -0
- package/dist/aura3d-cli/pull-bridge/adapters.d.ts.map +1 -0
- package/dist/aura3d-cli/pull-bridge/adapters.js +38 -0
- package/dist/aura3d-cli/pull-bridge/adapters.js.map +1 -0
- package/dist/aura3d-cli/pull-bridge/download.d.ts +6 -0
- package/dist/aura3d-cli/pull-bridge/download.d.ts.map +1 -0
- package/dist/aura3d-cli/pull-bridge/download.js +208 -0
- package/dist/aura3d-cli/pull-bridge/download.js.map +1 -0
- package/dist/aura3d-cli/pull-bridge/profiles.d.ts +14 -0
- package/dist/aura3d-cli/pull-bridge/profiles.d.ts.map +1 -0
- package/dist/aura3d-cli/pull-bridge/profiles.js +63 -0
- package/dist/aura3d-cli/pull-bridge/profiles.js.map +1 -0
- package/dist/aura3d-cli/pull-bridge/provenance.d.ts +9 -0
- package/dist/aura3d-cli/pull-bridge/provenance.d.ts.map +1 -0
- package/dist/aura3d-cli/pull-bridge/provenance.js +99 -0
- package/dist/aura3d-cli/pull-bridge/provenance.js.map +1 -0
- package/dist/aura3d-cli/pull-bridge/pullable.d.ts +14 -0
- package/dist/aura3d-cli/pull-bridge/pullable.d.ts.map +1 -0
- package/dist/aura3d-cli/pull-bridge/pullable.js +58 -0
- package/dist/aura3d-cli/pull-bridge/pullable.js.map +1 -0
- package/dist/aura3d-cli/pull-bridge/scoring.d.ts +21 -0
- package/dist/aura3d-cli/pull-bridge/scoring.d.ts.map +1 -0
- package/dist/aura3d-cli/pull-bridge/scoring.js +177 -0
- package/dist/aura3d-cli/pull-bridge/scoring.js.map +1 -0
- package/dist/aura3d-cli/pull-bridge/search.d.ts +39 -0
- package/dist/aura3d-cli/pull-bridge/search.d.ts.map +1 -0
- package/dist/aura3d-cli/pull-bridge/search.js +114 -0
- package/dist/aura3d-cli/pull-bridge/search.js.map +1 -0
- package/dist/aura3d-cli/pull-bridge/types.d.ts +9 -0
- package/dist/aura3d-cli/pull-bridge/types.d.ts.map +1 -0
- package/dist/aura3d-cli/pull-bridge/types.js +2 -0
- package/dist/aura3d-cli/pull-bridge/types.js.map +1 -0
- package/dist/aura3d-cli/pull-bridge/vector3.d.ts +2 -0
- package/dist/aura3d-cli/pull-bridge/vector3.d.ts.map +1 -0
- package/dist/aura3d-cli/pull-bridge/vector3.js +4 -0
- package/dist/aura3d-cli/pull-bridge/vector3.js.map +1 -0
- package/dist/aura3d-cli/pull-bridge.d.ts +18 -100
- package/dist/aura3d-cli/pull-bridge.d.ts.map +1 -1
- package/dist/aura3d-cli/pull-bridge.js +59 -526
- package/dist/aura3d-cli/pull-bridge.js.map +1 -1
- package/dist/create-aura3d/cli.js +10 -0
- package/dist/create-aura3d/cli.js.map +1 -1
- package/dist/create-aura3d/index.d.ts +1 -1
- package/dist/create-aura3d/index.d.ts.map +1 -1
- package/dist/create-aura3d/index.js +3 -1
- package/dist/create-aura3d/index.js.map +1 -1
- package/dist/create-aura3d/showcase-spec-artifacts.d.ts +105 -0
- package/dist/create-aura3d/showcase-spec-artifacts.d.ts.map +1 -0
- package/dist/create-aura3d/showcase-spec-artifacts.js +143 -0
- package/dist/create-aura3d/showcase-spec-artifacts.js.map +1 -0
- package/dist/create-aura3d/showcase-spec-category-plan.d.ts +15 -0
- package/dist/create-aura3d/showcase-spec-category-plan.d.ts.map +1 -0
- package/dist/create-aura3d/showcase-spec-category-plan.js +45 -0
- package/dist/create-aura3d/showcase-spec-category-plan.js.map +1 -0
- package/dist/create-aura3d/showcase-spec-compiler.d.ts +5 -0
- package/dist/create-aura3d/showcase-spec-compiler.d.ts.map +1 -0
- package/dist/create-aura3d/showcase-spec-compiler.js +240 -0
- package/dist/create-aura3d/showcase-spec-compiler.js.map +1 -0
- package/dist/create-aura3d/showcase-spec-evidence.d.ts +7 -0
- package/dist/create-aura3d/showcase-spec-evidence.d.ts.map +1 -0
- package/dist/create-aura3d/showcase-spec-evidence.js +881 -0
- package/dist/create-aura3d/showcase-spec-evidence.js.map +1 -0
- package/dist/create-aura3d/showcase-spec-game-geometry-extractor.d.ts +21 -0
- package/dist/create-aura3d/showcase-spec-game-geometry-extractor.d.ts.map +1 -0
- package/dist/create-aura3d/showcase-spec-game-geometry-extractor.js +725 -0
- package/dist/create-aura3d/showcase-spec-game-geometry-extractor.js.map +1 -0
- package/dist/create-aura3d/showcase-spec-game-replacement-evidence.d.ts +14 -0
- package/dist/create-aura3d/showcase-spec-game-replacement-evidence.d.ts.map +1 -0
- package/dist/create-aura3d/showcase-spec-game-replacement-evidence.js +219 -0
- package/dist/create-aura3d/showcase-spec-game-replacement-evidence.js.map +1 -0
- package/dist/create-aura3d/showcase-spec-game-template-evidence.d.ts +72 -0
- package/dist/create-aura3d/showcase-spec-game-template-evidence.d.ts.map +1 -0
- package/dist/create-aura3d/showcase-spec-game-template-evidence.js +435 -0
- package/dist/create-aura3d/showcase-spec-game-template-evidence.js.map +1 -0
- package/dist/create-aura3d/showcase-spec-gameplay-evidence.d.ts +3 -0
- package/dist/create-aura3d/showcase-spec-gameplay-evidence.d.ts.map +1 -0
- package/dist/create-aura3d/showcase-spec-gameplay-evidence.js +108 -0
- package/dist/create-aura3d/showcase-spec-gameplay-evidence.js.map +1 -0
- package/dist/create-aura3d/showcase-spec-parser.d.ts +3 -0
- package/dist/create-aura3d/showcase-spec-parser.d.ts.map +1 -0
- package/dist/create-aura3d/showcase-spec-parser.js +690 -0
- package/dist/create-aura3d/showcase-spec-parser.js.map +1 -0
- package/dist/create-aura3d/showcase-spec-platformer-artifacts.d.ts +3 -0
- package/dist/create-aura3d/showcase-spec-platformer-artifacts.d.ts.map +1 -0
- package/dist/create-aura3d/showcase-spec-platformer-artifacts.js +274 -0
- package/dist/create-aura3d/showcase-spec-platformer-artifacts.js.map +1 -0
- package/dist/create-aura3d/showcase-spec-racing-artifacts.d.ts +3 -0
- package/dist/create-aura3d/showcase-spec-racing-artifacts.d.ts.map +1 -0
- package/dist/create-aura3d/showcase-spec-racing-artifacts.js +273 -0
- package/dist/create-aura3d/showcase-spec-racing-artifacts.js.map +1 -0
- package/dist/create-aura3d/showcase-spec-replacement-apply.d.ts +10 -0
- package/dist/create-aura3d/showcase-spec-replacement-apply.d.ts.map +1 -0
- package/dist/create-aura3d/showcase-spec-replacement-apply.js +166 -0
- package/dist/create-aura3d/showcase-spec-replacement-apply.js.map +1 -0
- package/dist/create-aura3d/showcase-spec-replacement-candidates.d.ts +16 -0
- package/dist/create-aura3d/showcase-spec-replacement-candidates.d.ts.map +1 -0
- package/dist/create-aura3d/showcase-spec-replacement-candidates.js +244 -0
- package/dist/create-aura3d/showcase-spec-replacement-candidates.js.map +1 -0
- package/dist/create-aura3d/showcase-spec-replacement-game-geometry.d.ts +4 -0
- package/dist/create-aura3d/showcase-spec-replacement-game-geometry.d.ts.map +1 -0
- package/dist/create-aura3d/showcase-spec-replacement-game-geometry.js +175 -0
- package/dist/create-aura3d/showcase-spec-replacement-game-geometry.js.map +1 -0
- package/dist/create-aura3d/showcase-spec-replacement-manifest.d.ts +41 -0
- package/dist/create-aura3d/showcase-spec-replacement-manifest.d.ts.map +1 -0
- package/dist/create-aura3d/showcase-spec-replacement-manifest.js +62 -0
- package/dist/create-aura3d/showcase-spec-replacement-manifest.js.map +1 -0
- package/dist/create-aura3d/showcase-spec-replacement-values.d.ts +9 -0
- package/dist/create-aura3d/showcase-spec-replacement-values.d.ts.map +1 -0
- package/dist/create-aura3d/showcase-spec-replacement-values.js +41 -0
- package/dist/create-aura3d/showcase-spec-replacement-values.js.map +1 -0
- package/dist/create-aura3d/showcase-spec-replacement.d.ts +13 -0
- package/dist/create-aura3d/showcase-spec-replacement.d.ts.map +1 -0
- package/dist/create-aura3d/showcase-spec-replacement.js +144 -0
- package/dist/create-aura3d/showcase-spec-replacement.js.map +1 -0
- package/dist/create-aura3d/showcase-spec-types.d.ts +319 -0
- package/dist/create-aura3d/showcase-spec-types.d.ts.map +1 -0
- package/dist/create-aura3d/showcase-spec-types.js +2 -0
- package/dist/create-aura3d/showcase-spec-types.js.map +1 -0
- package/dist/engine/agent-api/GameAssetValidation.d.ts +5 -0
- package/dist/engine/agent-api/GameAssetValidation.d.ts.map +1 -1
- package/dist/engine/agent-api/GameAssetValidation.js +103 -0
- package/dist/engine/agent-api/GameAssetValidation.js.map +1 -1
- package/dist/engine/agent-api/GameEvidence.d.ts +14 -1
- package/dist/engine/agent-api/GameEvidence.d.ts.map +1 -1
- package/dist/engine/agent-api/GameEvidence.js +77 -6
- package/dist/engine/agent-api/GameEvidence.js.map +1 -1
- package/dist/engine/agent-api/GameGenreKits.d.ts +473 -0
- package/dist/engine/agent-api/GameGenreKits.d.ts.map +1 -0
- package/dist/engine/agent-api/GameGenreKits.js +1269 -0
- package/dist/engine/agent-api/GameGenreKits.js.map +1 -0
- package/dist/engine/agent-api/GameRuntime.d.ts +190 -3
- package/dist/engine/agent-api/GameRuntime.d.ts.map +1 -1
- package/dist/engine/agent-api/GameRuntime.js +431 -2
- package/dist/engine/agent-api/GameRuntime.js.map +1 -1
- package/dist/engine/agent-api/GameSceneGeometryBindings.d.ts +182 -0
- package/dist/engine/agent-api/GameSceneGeometryBindings.d.ts.map +1 -0
- package/dist/engine/agent-api/GameSceneGeometryBindings.js +488 -0
- package/dist/engine/agent-api/GameSceneGeometryBindings.js.map +1 -0
- package/dist/engine/agent-api/GameSceneGeometryMath.d.ts +39 -0
- package/dist/engine/agent-api/GameSceneGeometryMath.d.ts.map +1 -0
- package/dist/engine/agent-api/GameSceneGeometryMath.js +89 -0
- package/dist/engine/agent-api/GameSceneGeometryMath.js.map +1 -0
- package/dist/engine/agent-api/PublicGameGeometry.d.ts +117 -0
- package/dist/engine/agent-api/PublicGameGeometry.d.ts.map +1 -0
- package/dist/engine/agent-api/PublicGameGeometry.js +118 -0
- package/dist/engine/agent-api/PublicGameGeometry.js.map +1 -0
- package/dist/engine/agent-api/RuntimeNodeHandle.d.ts +4 -0
- package/dist/engine/agent-api/RuntimeNodeHandle.d.ts.map +1 -1
- package/dist/engine/agent-api/RuntimeNodeHandle.js +2 -0
- package/dist/engine/agent-api/RuntimeNodeHandle.js.map +1 -1
- package/dist/engine/agent-api/SceneGroundingUtils.d.ts +86 -0
- package/dist/engine/agent-api/SceneGroundingUtils.d.ts.map +1 -1
- package/dist/engine/agent-api/SceneGroundingUtils.js +116 -0
- package/dist/engine/agent-api/SceneGroundingUtils.js.map +1 -1
- package/dist/engine/agent-api/index.d.ts +266 -5
- package/dist/engine/agent-api/index.d.ts.map +1 -1
- package/dist/engine/agent-api/index.js +2445 -113
- package/dist/engine/agent-api/index.js.map +1 -1
- package/dist/engine/agent-api/product-viewer-runtime.d.ts.map +1 -1
- package/dist/engine/production-runtime/TypedGLBActor.d.ts +14 -2
- package/dist/engine/production-runtime/TypedGLBActor.d.ts.map +1 -1
- package/dist/engine/production-runtime/TypedGLBActor.js +95 -4
- package/dist/engine/production-runtime/TypedGLBActor.js.map +1 -1
- package/dist/rendering/ForwardPass.js +7 -1
- package/dist/rendering/ForwardPass.js.map +1 -1
- package/dist/rendering/MorphTarget.d.ts +1 -0
- package/dist/rendering/MorphTarget.d.ts.map +1 -1
- package/dist/rendering/MorphTarget.js.map +1 -1
- package/dist/rendering/Renderer.js +7 -1
- package/dist/rendering/Renderer.js.map +1 -1
- package/package.json +30 -32
- package/templates/mini-game/README.md +13 -0
- package/templates/mini-game/index.html +1 -1
- package/templates/mini-game/package.json +1 -1
- package/templates/mini-game/src/main.ts +251 -21
- package/templates/mini-game/tests/playable.spec.ts +49 -0
- package/templates/mini-game/tests/screenshot.spec.ts +37 -32
|
@@ -3,6 +3,19 @@
|
|
|
3
3
|
Small interactive scene starter for agent-authored controls, movement, and route
|
|
4
4
|
health checks.
|
|
5
5
|
|
|
6
|
+
Status: playable starter, not a production game claim. This template uses a
|
|
7
|
+
typed player asset, the public `game.platformer(...)` kit, runtime nodes, HUD
|
|
8
|
+
evidence, keyboard input, reset, scoring, and screenshot tests. It proves the
|
|
9
|
+
starter boots and responds to keyboard input through the root `@aura3d/engine`
|
|
10
|
+
safe API; it does not prove production art direction, skinned animation,
|
|
11
|
+
advanced PBR, WebGPU, postprocess, or commercial game polish.
|
|
12
|
+
|
|
13
|
+
Before presenting a route from this template as production-quality, replace any
|
|
14
|
+
placeholder art with typed primary assets from the Aura3D CLI, keep
|
|
15
|
+
`model(assets.x)` for real assets, prove each claimed mechanic with keyboard
|
|
16
|
+
tests, and capture desktop/mobile screenshots where the main subject is
|
|
17
|
+
readable.
|
|
18
|
+
|
|
6
19
|
```bash
|
|
7
20
|
npm install
|
|
8
21
|
npm run dev
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"typecheck": "tsc --noEmit",
|
|
9
9
|
"build": "npm run typecheck && vite build",
|
|
10
10
|
"preview": "vite preview --host 127.0.0.1",
|
|
11
|
-
"test": "playwright test tests/route-health.spec.ts tests/screenshot.spec.ts --workers=1"
|
|
11
|
+
"test": "playwright test tests/route-health.spec.ts tests/playable.spec.ts tests/screenshot.spec.ts --workers=1"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@aura3d/engine": "1.0.0"
|
|
@@ -1,27 +1,257 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
camera,
|
|
3
|
+
createAuraApp,
|
|
4
|
+
game,
|
|
5
|
+
lights,
|
|
6
|
+
material,
|
|
7
|
+
model,
|
|
8
|
+
primitives,
|
|
9
|
+
scene,
|
|
10
|
+
type AuraNodeInput
|
|
11
|
+
} from "@aura3d/engine";
|
|
2
12
|
import { assets } from "./aura-assets";
|
|
3
13
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
declare global {
|
|
15
|
+
interface Window {
|
|
16
|
+
__AURA3D_MINI_GAME__?: MiniGameEvidence;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface MiniGameEvidence {
|
|
21
|
+
readonly status: string;
|
|
22
|
+
readonly frame: number;
|
|
23
|
+
readonly score: number;
|
|
24
|
+
readonly deaths: number;
|
|
25
|
+
readonly checkpointId: string;
|
|
26
|
+
readonly collected: readonly string[];
|
|
27
|
+
readonly player: {
|
|
28
|
+
readonly x: number;
|
|
29
|
+
readonly y: number;
|
|
30
|
+
readonly grounded: boolean;
|
|
31
|
+
};
|
|
32
|
+
readonly events: readonly string[];
|
|
33
|
+
readonly evidence: unknown;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const level = {
|
|
37
|
+
start: { x: 0, y: 0.35 },
|
|
38
|
+
finish: { x: 12.4, y: 0.35 },
|
|
39
|
+
platforms: [
|
|
40
|
+
{ id: "launch", x: -0.6, y: 0, width: 4.2, height: 0.35 },
|
|
41
|
+
{ id: "middle", x: 3.8, y: 0.62, width: 3.2, height: 0.3 },
|
|
42
|
+
{ id: "finish", x: 8.2, y: 0.18, width: 4.8, height: 0.35 }
|
|
43
|
+
],
|
|
44
|
+
movingPlatforms: [
|
|
45
|
+
{ id: "lift", x: 6.9, y: 1.05, width: 1.35, height: 0.22, axis: "y" as const, amplitude: 0.42, period: 2.4 }
|
|
46
|
+
],
|
|
47
|
+
collectibles: [
|
|
48
|
+
{ id: "coin-01", x: 1.4, y: 1.15, value: 50, radius: 0.55 },
|
|
49
|
+
{ id: "coin-02", x: 4.8, y: 1.45, value: 75, radius: 0.55 },
|
|
50
|
+
{ id: "coin-03", x: 9.8, y: 1.05, value: 100, radius: 0.55 }
|
|
51
|
+
],
|
|
52
|
+
hazards: [
|
|
53
|
+
{ id: "spikes", x: 7.7, y: 0.42, width: 0.85, height: 0.24 }
|
|
54
|
+
],
|
|
55
|
+
checkpoints: [
|
|
56
|
+
{ id: "mid", x: 5.2, y: 0.92, radius: 0.8 }
|
|
17
57
|
],
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
58
|
+
lowerBound: -2.4,
|
|
59
|
+
moveSpeed: 5.2,
|
|
60
|
+
jumpVelocity: 8,
|
|
61
|
+
dashSpeed: 9.5
|
|
62
|
+
};
|
|
23
63
|
|
|
24
|
-
|
|
64
|
+
const input = game.input({
|
|
65
|
+
actions: {
|
|
66
|
+
left: ["KeyA", "ArrowLeft"],
|
|
67
|
+
right: ["KeyD", "ArrowRight"],
|
|
68
|
+
jump: ["Space", "KeyW", "ArrowUp"],
|
|
69
|
+
dash: ["ShiftLeft", "ShiftRight"],
|
|
70
|
+
down: ["KeyS", "ArrowDown"],
|
|
71
|
+
reset: ["KeyR"]
|
|
72
|
+
},
|
|
73
|
+
axes: {
|
|
74
|
+
moveX: { negative: "left", positive: "right" }
|
|
75
|
+
},
|
|
76
|
+
bufferMs: 140
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const platformer = game.platformer(level);
|
|
80
|
+
const routeEvents = game.eventLog({ label: "mini game route events", maxEvents: 16 });
|
|
81
|
+
const hud = game.hud.bindings([
|
|
82
|
+
game.hud.score({ valuePath: "appState.score" }),
|
|
83
|
+
game.hud.lives({ valuePath: "appState.lives" }),
|
|
84
|
+
game.hud.objective({ valuePath: "appState.objective" }),
|
|
85
|
+
game.hud.checkpoint({ valuePath: "appState.checkpoint" }),
|
|
86
|
+
game.hud.eventLog({ valuePath: "appState.events" })
|
|
87
|
+
]);
|
|
88
|
+
|
|
89
|
+
const app = createAuraApp("#app", {
|
|
25
90
|
diagnostics: { overlay: true, performancePanel: true },
|
|
26
|
-
scene:
|
|
91
|
+
scene: buildScene()
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const player = app.nodes.require("mini-player");
|
|
95
|
+
const lift = app.nodes.require("platform-lift");
|
|
96
|
+
const coins = level.collectibles.map((coin) => [coin.id, app.nodes.require(`coin-${coin.id}`)] as const);
|
|
97
|
+
const checkpoint = app.nodes.require("checkpoint-mid");
|
|
98
|
+
const goal = app.nodes.require("goal");
|
|
99
|
+
const hudRoot = createHud();
|
|
100
|
+
|
|
101
|
+
let objective = "Collect coins, avoid spikes, reach the goal";
|
|
102
|
+
|
|
103
|
+
app.onFrame(({ dt }: { readonly dt: number }) => {
|
|
104
|
+
input.update(dt);
|
|
105
|
+
if (input.pressed("reset")) {
|
|
106
|
+
platformer.reset();
|
|
107
|
+
routeEvents.push({ type: "reset", label: "Route reset" });
|
|
108
|
+
objective = "Collect coins, avoid spikes, reach the goal";
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const state = platformer.step(dt, {
|
|
112
|
+
moveX: input.axis("moveX"),
|
|
113
|
+
jumpPressed: input.buffered("jump"),
|
|
114
|
+
jumpHeld: input.held("jump"),
|
|
115
|
+
dashPressed: input.pressed("dash"),
|
|
116
|
+
fastFall: input.held("down")
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
for (const event of state.events) {
|
|
120
|
+
routeEvents.push({
|
|
121
|
+
type: event.type,
|
|
122
|
+
label: event.id ? `${event.type}:${event.id}` : event.type,
|
|
123
|
+
targetId: event.id,
|
|
124
|
+
severity: event.type === "complete" || event.type === "collect" ? "success" : event.type === "hazard" || event.type === "fall" ? "warning" : "info",
|
|
125
|
+
frame: event.frame,
|
|
126
|
+
time: event.time
|
|
127
|
+
});
|
|
128
|
+
if (event.type === "checkpoint") objective = "Checkpoint reached. Finish the route.";
|
|
129
|
+
if (event.type === "complete") objective = "Finished. Press R to replay.";
|
|
130
|
+
if (event.type === "respawn") objective = "Respawned. Take the safer route.";
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
player.setPosition(state.player.x, state.player.y + 0.54, 0);
|
|
134
|
+
lift.setPosition(level.movingPlatforms[0].x + level.movingPlatforms[0].width / 2, movingLiftY(state.time), 0);
|
|
135
|
+
for (const [id, node] of coins) node.setVisible(!state.collected.includes(id));
|
|
136
|
+
checkpoint.setVisible(!state.activatedCheckpoints.includes("mid"));
|
|
137
|
+
goal.setScale(state.status === "completed" ? [0.28, 1.08, 0.18] : [0.22, 0.92, 0.16]);
|
|
138
|
+
|
|
139
|
+
renderHud(state);
|
|
140
|
+
publishEvidence(state);
|
|
27
141
|
});
|
|
142
|
+
|
|
143
|
+
publishEvidence(platformer.snapshot());
|
|
144
|
+
renderHud(platformer.snapshot());
|
|
145
|
+
|
|
146
|
+
function buildScene() {
|
|
147
|
+
const nodes: AuraNodeInput[] = [
|
|
148
|
+
model(assets.playerModel, { name: "typed mini-game player", castShadow: true })
|
|
149
|
+
.position(level.start.x, level.start.y + 0.54, 0)
|
|
150
|
+
.scale(0.42)
|
|
151
|
+
.runtime(game.runtimeNode("mini-player", { tags: ["player", "typed-asset", "runtime"] })),
|
|
152
|
+
...level.platforms.map((platform) =>
|
|
153
|
+
primitives.box({ name: `${platform.id} platform`, material: material.neon({ color: "#62d8ef", emissive: "#62d8ef", emissiveIntensity: 0.18 }) })
|
|
154
|
+
.position(platform.x + platform.width / 2, platform.y + platform.height / 2, -0.05)
|
|
155
|
+
.scale([platform.width, platform.height, 0.22])
|
|
156
|
+
),
|
|
157
|
+
primitives.box({ name: "moving lift platform", material: material.neon({ color: "#b5f77d", emissive: "#b5f77d", emissiveIntensity: 0.35 }) })
|
|
158
|
+
.position(level.movingPlatforms[0].x + level.movingPlatforms[0].width / 2, movingLiftY(0), 0)
|
|
159
|
+
.scale([level.movingPlatforms[0].width, level.movingPlatforms[0].height, 0.22])
|
|
160
|
+
.runtime(game.runtimeNode("platform-lift", { tags: ["moving-platform", "runtime"] })),
|
|
161
|
+
...level.collectibles.map((coin) =>
|
|
162
|
+
primitives.sphere({ name: `${coin.id} collectible`, material: material.neon({ color: "#f7d76b", emissive: "#f7d76b", emissiveIntensity: 0.7 }) })
|
|
163
|
+
.position(coin.x, coin.y, 0.02)
|
|
164
|
+
.scale(0.18)
|
|
165
|
+
.runtime(game.runtimeNode(`coin-${coin.id}`, { tags: ["coin", "runtime"] }))
|
|
166
|
+
),
|
|
167
|
+
primitives.box({ name: "hazard spikes", material: material.neon({ color: "#f06b7a", emissive: "#f06b7a", emissiveIntensity: 0.7 }) })
|
|
168
|
+
.position(level.hazards[0].x + level.hazards[0].width / 2, level.hazards[0].y + level.hazards[0].height / 2, 0.05)
|
|
169
|
+
.scale([level.hazards[0].width, level.hazards[0].height, 0.2]),
|
|
170
|
+
primitives.box({ name: "checkpoint marker", material: material.neon({ color: "#9df59e", emissive: "#9df59e", emissiveIntensity: 0.65 }) })
|
|
171
|
+
.position(level.checkpoints[0].x, level.checkpoints[0].y + 0.42, 0.08)
|
|
172
|
+
.scale([0.14, 0.85, 0.14])
|
|
173
|
+
.runtime(game.runtimeNode("checkpoint-mid", { tags: ["checkpoint", "runtime"] })),
|
|
174
|
+
primitives.box({ name: "finish portal", material: material.neon({ color: "#ffad57", emissive: "#ffad57", emissiveIntensity: 0.82 }) })
|
|
175
|
+
.position(level.finish.x, level.finish.y + 0.7, 0.08)
|
|
176
|
+
.scale([0.22, 0.92, 0.16])
|
|
177
|
+
.runtime(game.runtimeNode("goal", { tags: ["finish", "runtime"] }))
|
|
178
|
+
];
|
|
179
|
+
|
|
180
|
+
return scene()
|
|
181
|
+
.background("#071015")
|
|
182
|
+
.addMany(nodes)
|
|
183
|
+
.add(lights.ambient({ name: "game ambient", intensity: 0.38, color: "#d9f8ff" }))
|
|
184
|
+
.add(lights.directional({ name: "game key", position: [4, 6, 5], intensity: 1.2, color: "#ffffff" }))
|
|
185
|
+
.camera(camera.perspective({ position: [5.8, 4.3, 8.5], target: [5.8, 0.9, 0], fov: 44 }));
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function movingLiftY(time: number): number {
|
|
189
|
+
const platform = level.movingPlatforms[0];
|
|
190
|
+
return platform.y + platform.height / 2 + Math.sin((time / platform.period) * Math.PI * 2) * platform.amplitude;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function createHud(): HTMLElement {
|
|
194
|
+
const root = document.createElement("aside");
|
|
195
|
+
root.id = "mini-game-hud";
|
|
196
|
+
root.style.cssText = [
|
|
197
|
+
"position:absolute",
|
|
198
|
+
"left:16px",
|
|
199
|
+
"top:16px",
|
|
200
|
+
"z-index:5",
|
|
201
|
+
"min-width:260px",
|
|
202
|
+
"font:600 13px/1.35 Inter, system-ui, sans-serif",
|
|
203
|
+
"color:#f5fbff",
|
|
204
|
+
"background:rgba(3,9,14,0.78)",
|
|
205
|
+
"border:1px solid rgba(125,220,235,0.34)",
|
|
206
|
+
"border-radius:8px",
|
|
207
|
+
"padding:12px",
|
|
208
|
+
"pointer-events:none"
|
|
209
|
+
].join(";");
|
|
210
|
+
document.body.append(root);
|
|
211
|
+
return root;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function renderHud(state: ReturnType<typeof platformer.snapshot>): void {
|
|
215
|
+
hudRoot.innerHTML = [
|
|
216
|
+
`<strong>Aura3D Mini Game</strong>`,
|
|
217
|
+
`<div>Score ${state.score} | Lives ${state.lives} | Deaths ${state.deaths}</div>`,
|
|
218
|
+
`<div>Checkpoint ${state.checkpointId}</div>`,
|
|
219
|
+
`<div>${objective}</div>`,
|
|
220
|
+
`<div>Move A/D or arrows. Jump Space. Dash Shift. Reset R.</div>`
|
|
221
|
+
].join("");
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function publishEvidence(state: ReturnType<typeof platformer.snapshot>): void {
|
|
225
|
+
const evidence = app.evidence({
|
|
226
|
+
input,
|
|
227
|
+
events: routeEvents,
|
|
228
|
+
hud,
|
|
229
|
+
appState: {
|
|
230
|
+
score: state.score,
|
|
231
|
+
lives: state.lives,
|
|
232
|
+
objective,
|
|
233
|
+
checkpoint: state.checkpointId,
|
|
234
|
+
events: routeEvents.events().map((event: { readonly label: string }) => event.label)
|
|
235
|
+
},
|
|
236
|
+
assets: {
|
|
237
|
+
typedAssets: Object.keys(assets).length,
|
|
238
|
+
missingAssets: []
|
|
239
|
+
},
|
|
240
|
+
source: { expectsGame: true }
|
|
241
|
+
});
|
|
242
|
+
window.__AURA3D_MINI_GAME__ = {
|
|
243
|
+
status: state.status,
|
|
244
|
+
frame: state.frame,
|
|
245
|
+
score: state.score,
|
|
246
|
+
deaths: state.deaths,
|
|
247
|
+
checkpointId: state.checkpointId,
|
|
248
|
+
collected: state.collected,
|
|
249
|
+
player: {
|
|
250
|
+
x: state.player.x,
|
|
251
|
+
y: state.player.y,
|
|
252
|
+
grounded: state.player.grounded
|
|
253
|
+
},
|
|
254
|
+
events: routeEvents.events().map((event: { readonly label: string }) => event.label),
|
|
255
|
+
evidence
|
|
256
|
+
};
|
|
257
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { expect, test } from "@playwright/test";
|
|
2
|
+
|
|
3
|
+
test.setTimeout(60_000);
|
|
4
|
+
|
|
5
|
+
type MiniGameState = {
|
|
6
|
+
readonly score: number;
|
|
7
|
+
readonly events: readonly string[];
|
|
8
|
+
readonly player: {
|
|
9
|
+
readonly x: number;
|
|
10
|
+
readonly y: number;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
function readMiniGameState(): MiniGameState | undefined {
|
|
15
|
+
return (window as unknown as { readonly __AURA3D_MINI_GAME__?: MiniGameState }).__AURA3D_MINI_GAME__;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
test("Aura3D mini game responds to keyboard input, scoring, and reset", async ({ page }) => {
|
|
19
|
+
await page.goto("/");
|
|
20
|
+
await expect.poll(() => page.locator("body").getAttribute("data-aura3d-ready"), { timeout: 45_000 }).toBe("true");
|
|
21
|
+
|
|
22
|
+
const initial = await page.evaluate(readMiniGameState);
|
|
23
|
+
expect(initial?.player.x).toBeLessThan(0.2);
|
|
24
|
+
|
|
25
|
+
await page.keyboard.down("ArrowRight");
|
|
26
|
+
await page.waitForTimeout(650);
|
|
27
|
+
await page.keyboard.up("ArrowRight");
|
|
28
|
+
|
|
29
|
+
const moved = await page.evaluate(readMiniGameState);
|
|
30
|
+
expect(moved?.player.x ?? 0).toBeGreaterThan((initial?.player.x ?? 0) + 1.2);
|
|
31
|
+
|
|
32
|
+
await page.keyboard.press("Space");
|
|
33
|
+
await page.waitForTimeout(180);
|
|
34
|
+
const jumped = await page.evaluate(readMiniGameState);
|
|
35
|
+
expect(jumped?.player.y ?? 0).toBeGreaterThan(moved?.player.y ?? 0);
|
|
36
|
+
|
|
37
|
+
await page.keyboard.down("ArrowRight");
|
|
38
|
+
await page.waitForTimeout(1600);
|
|
39
|
+
await page.keyboard.up("ArrowRight");
|
|
40
|
+
const progressed = await page.evaluate(readMiniGameState);
|
|
41
|
+
expect(progressed?.score ?? 0).toBeGreaterThanOrEqual(50);
|
|
42
|
+
expect(progressed?.events.length ?? 0).toBeGreaterThan(0);
|
|
43
|
+
|
|
44
|
+
await page.keyboard.press("KeyR");
|
|
45
|
+
await page.waitForTimeout(120);
|
|
46
|
+
const reset = await page.evaluate(readMiniGameState);
|
|
47
|
+
expect(reset?.player.x ?? 99).toBeLessThan(0.3);
|
|
48
|
+
expect(reset?.events.some((event) => event.includes("reset"))).toBe(true);
|
|
49
|
+
});
|
|
@@ -4,60 +4,65 @@ import { expect, test } from "@playwright/test";
|
|
|
4
4
|
|
|
5
5
|
test.setTimeout(60_000);
|
|
6
6
|
|
|
7
|
-
test("Aura3D mini game screenshot shows a playable
|
|
7
|
+
test("Aura3D mini game screenshot shows a readable playable scene", async ({ page }) => {
|
|
8
8
|
await page.goto("/");
|
|
9
9
|
await expect.poll(() => page.locator("body").getAttribute("data-aura3d-ready"), { timeout: 45_000 }).toBe("true");
|
|
10
|
+
|
|
11
|
+
await page.keyboard.down("ArrowRight");
|
|
12
|
+
await page.waitForTimeout(550);
|
|
13
|
+
await page.keyboard.up("ArrowRight");
|
|
14
|
+
|
|
15
|
+
const state = await page.evaluate(() =>
|
|
16
|
+
(window as unknown as {
|
|
17
|
+
readonly __AURA3D_MINI_GAME__?: {
|
|
18
|
+
readonly score: number;
|
|
19
|
+
readonly player: { readonly x: number };
|
|
20
|
+
};
|
|
21
|
+
}).__AURA3D_MINI_GAME__
|
|
22
|
+
);
|
|
23
|
+
expect(state?.player.x ?? 0).toBeGreaterThan(0.8);
|
|
24
|
+
|
|
10
25
|
const canvas = page.locator("canvas");
|
|
11
26
|
const profile = await canvas.evaluate((element) => {
|
|
12
27
|
const target = element as HTMLCanvasElement;
|
|
13
28
|
const gl = target.getContext("webgl2", { preserveDrawingBuffer: true });
|
|
14
|
-
if (!gl) return { error: "missing-webgl2",
|
|
29
|
+
if (!gl) return { error: "missing-webgl2", brightPixels: 0, warmPixels: 0, cyanPixels: 0, redPixels: 0, uniqueBuckets: 0 };
|
|
15
30
|
const pixels = new Uint8Array(target.width * target.height * 4);
|
|
16
31
|
gl.readPixels(0, 0, target.width, target.height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
|
|
17
32
|
const buckets = new Set<string>();
|
|
18
|
-
let
|
|
19
|
-
let
|
|
20
|
-
let
|
|
21
|
-
let
|
|
22
|
-
let hazardPixels = 0;
|
|
23
|
-
let portalPixels = 0;
|
|
24
|
-
let cyanTrailPixels = 0;
|
|
25
|
-
let arenaPixels = 0;
|
|
33
|
+
let brightPixels = 0;
|
|
34
|
+
let warmPixels = 0;
|
|
35
|
+
let cyanPixels = 0;
|
|
36
|
+
let redPixels = 0;
|
|
26
37
|
for (let y = 0; y < target.height; y += 4) {
|
|
27
38
|
for (let x = 0; x < target.width; x += 4) {
|
|
28
|
-
if (x > target.width * 0.76 && y > target.height * 0.74) continue;
|
|
29
39
|
const offset = (y * target.width + x) * 4;
|
|
30
40
|
const r = pixels[offset] ?? 0;
|
|
31
41
|
const g = pixels[offset + 1] ?? 0;
|
|
32
42
|
const b = pixels[offset + 2] ?? 0;
|
|
33
43
|
const luminance = r * 0.2126 + g * 0.7152 + b * 0.0722;
|
|
34
|
-
if (luminance >
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (
|
|
39
|
-
if (
|
|
40
|
-
if (r >
|
|
41
|
-
if (r > 165 && g > 95 && b < 125) portalPixels += 1;
|
|
42
|
-
if (g > 140 && b > 150 && r < 150) cyanTrailPixels += 1;
|
|
43
|
-
if (g > 42 && b > 50 && b > r * 1.08 && luminance > 24 && luminance < 100) arenaPixels += 1;
|
|
44
|
+
if (luminance > 30) {
|
|
45
|
+
brightPixels += 1;
|
|
46
|
+
buckets.add(`${r >> 5}-${g >> 5}-${b >> 5}`);
|
|
47
|
+
}
|
|
48
|
+
if (r > 150 && g > 110 && b < 110) warmPixels += 1;
|
|
49
|
+
if (g > 120 && b > 130 && r < 150) cyanPixels += 1;
|
|
50
|
+
if (r > 145 && g < 115 && b < 140) redPixels += 1;
|
|
44
51
|
}
|
|
45
52
|
}
|
|
46
|
-
return {
|
|
53
|
+
return { brightPixels, warmPixels, cyanPixels, redPixels, uniqueBuckets: buckets.size };
|
|
47
54
|
});
|
|
55
|
+
|
|
48
56
|
const screenshot = await page.screenshot({ fullPage: false });
|
|
49
57
|
mkdirSync(resolve("tests/reports"), { recursive: true });
|
|
50
58
|
writeFileSync(resolve("tests/reports/screenshot.png"), screenshot);
|
|
51
|
-
writeFileSync(resolve("tests/reports/screenshot.json"), `${JSON.stringify({ bytes: screenshot.byteLength, profile }, null, 2)}\n`);
|
|
59
|
+
writeFileSync(resolve("tests/reports/screenshot.json"), `${JSON.stringify({ bytes: screenshot.byteLength, profile, state }, null, 2)}\n`);
|
|
60
|
+
|
|
52
61
|
expect(profile.error).toBeUndefined();
|
|
53
|
-
expect(profile.
|
|
54
|
-
expect(profile.
|
|
55
|
-
expect(profile.
|
|
56
|
-
expect(profile.
|
|
57
|
-
expect(profile.
|
|
58
|
-
expect(profile.portalPixels).toBeGreaterThan(45);
|
|
59
|
-
expect(profile.cyanTrailPixels).toBeGreaterThan(90);
|
|
60
|
-
expect(profile.arenaPixels).toBeGreaterThan(600);
|
|
61
|
-
expect(profile.uniqueBuckets).toBeGreaterThan(22);
|
|
62
|
+
expect(profile.brightPixels).toBeGreaterThan(900);
|
|
63
|
+
expect(profile.cyanPixels).toBeGreaterThan(20);
|
|
64
|
+
expect(profile.warmPixels).toBeGreaterThan(10);
|
|
65
|
+
expect(profile.redPixels).toBeGreaterThan(5);
|
|
66
|
+
expect(profile.uniqueBuckets).toBeGreaterThan(10);
|
|
62
67
|
expect(screenshot.byteLength).toBeGreaterThan(1000);
|
|
63
68
|
});
|