create-aura3d 3.0.0 → 4.0.0
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 +1 -1
- package/dist/agent-skills.d.ts +38 -0
- package/dist/agent-skills.d.ts.map +1 -0
- package/dist/agent-skills.js +103 -0
- package/dist/agent-skills.js.map +1 -0
- package/dist/cli.js +32 -5
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +32 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +52 -10
- package/dist/index.js.map +1 -1
- package/dist/showcase-spec-artifacts.d.ts +1 -1
- package/dist/showcase-spec-game-geometry-extractor.js +8 -11
- package/dist/showcase-spec-game-geometry-extractor.js.map +1 -1
- package/dist/template-hdri.d.ts +12 -0
- package/dist/template-hdri.d.ts.map +1 -0
- package/dist/template-hdri.js +49 -0
- package/dist/template-hdri.js.map +1 -0
- package/hdri/ATTRIBUTION.md +8 -0
- package/hdri/autumn_field_puresky_1k.hdr +0 -0
- package/hdri/kloppenheim_06_puresky_1k.hdr +0 -0
- package/hdri/night-2k.hdr +0 -0
- package/hdri/studio_small_08_1k.hdr +0 -0
- package/package.json +14 -10
- package/skills/agent-files/AGENTS.md +3 -0
- package/skills/aura3d-animation-studio/SKILL.md +153 -0
- package/skills/aura3d-animation-studio/references/shot-looks.md +26 -0
- package/skills/aura3d-art-direction/SKILL.md +84 -0
- package/skills/aura3d-art-direction/references/failure-gallery.md +64 -0
- package/skills/aura3d-art-direction/references/framing-and-shots.md +45 -0
- package/skills/aura3d-art-direction/references/look-recipes.md +32 -0
- package/skills/aura3d-art-direction/references/quality-bar.md +103 -0
- package/skills/aura3d-art-direction/references/reference-frames.md +82 -0
- package/skills/aura3d-assets/SKILL.md +132 -0
- package/skills/aura3d-assets/references/preview-under-look.md +26 -0
- package/skills/aura3d-browser-game/SKILL.md +127 -0
- package/skills/aura3d-browser-game/references/genre-looks.md +52 -0
- package/skills/aura3d-character-animation/SKILL.md +129 -0
- package/skills/aura3d-character-animation/references/stage-and-lighting.md +31 -0
- package/skills/aura3d-core/SKILL.md +121 -0
- package/skills/aura3d-core/references/boundaries.md +91 -0
- package/skills/aura3d-evidence-review/SKILL.md +106 -0
- package/skills/aura3d-game-art/SKILL.md +118 -0
- package/skills/aura3d-game-art/references/sheet-check.mjs +58 -0
- package/skills/aura3d-game-art/references/sprite-palettes.md +25 -0
- package/skills/aura3d-materials-environments/SKILL.md +139 -0
- package/skills/aura3d-performance/SKILL.md +97 -0
- package/skills/aura3d-retexture/SKILL.md +115 -0
- package/skills/aura3d-retexture/references/geometry-hash.mjs +89 -0
- package/skills/aura3d-scene-authoring/SKILL.md +132 -0
- package/skills/aura3d-scene-authoring/references/look-by-family.md +28 -0
- package/skills/aura3d-threejs-migration/SKILL.md +125 -0
- package/skills/aura3d-threejs-migration/references/look-mapping.md +27 -0
- package/skills/llms.txt +117 -0
- package/skills/manifest.json +163 -0
- package/skills/meshy-cli/SKILL.md +133 -0
- package/templates/animation-channel/.claude/CLAUDE.md +3 -0
- package/templates/animation-channel/.github/workflows/aura3d-lookdev.yml +67 -0
- package/templates/animation-channel/AGENTS.md +3 -0
- package/templates/animation-channel/package.json +4 -3
- package/templates/animation-channel/src/main.ts +5 -6
- package/templates/animation-channel/src/render-plan.ts +5 -3
- package/templates/animation-channel/tests/look-floor.ts +270 -0
- package/templates/animation-channel/tests/route-health.spec.ts +13 -0
- package/templates/animation-channel/tests/screenshot.spec.ts +10 -5
- package/templates/animation-channel/vite.config.ts +7 -0
- package/templates/animation-studio/.claude/CLAUDE.md +3 -0
- package/templates/animation-studio/.github/workflows/aura3d-lookdev.yml +67 -0
- package/templates/animation-studio/AGENTS.md +2 -70
- package/templates/animation-studio/package.json +5 -4
- package/templates/animation-studio/public/aura-assets/luma.thumb.svg +1 -1
- package/templates/animation-studio/public/aura-assets/miko.thumb.svg +1 -1
- package/templates/{falling-blocks-starter/public/aura-assets/showcaseBlockfallCabinet.thumb.svg → animation-studio/public/aura-assets/moonGarden.thumb.svg} +1 -1
- package/templates/animation-studio/scripts/build-clip-library.ts +6 -5
- package/templates/animation-studio/scripts/resolve-asset.ts +7 -4
- package/templates/animation-studio/src/asset-contract.ts +19 -0
- package/templates/animation-studio/src/aura-assets.ts +651 -54
- package/templates/animation-studio/src/scene-player.ts +6 -6
- package/templates/animation-studio/src/set-templates.ts +13 -9
- package/templates/animation-studio/tests/look-floor.ts +270 -0
- package/templates/animation-studio/tests/route-health.spec.ts +2 -2
- package/templates/animation-studio/tests/screenshot.spec.ts +18 -10
- package/templates/animation-studio/vite.config.ts +2 -0
- package/templates/architecture-interior/.claude/CLAUDE.md +3 -0
- package/templates/architecture-interior/.github/workflows/aura3d-lookdev.yml +67 -0
- package/templates/architecture-interior/AGENTS.md +3 -0
- package/templates/architecture-interior/README.md +16 -0
- package/templates/architecture-interior/aura.assets.json +24 -0
- package/templates/architecture-interior/package.json +24 -0
- package/templates/architecture-interior/public/aura-assets/kenneyModularDungeonRoomSmall.a7e74a5f.glb +0 -0
- package/templates/architecture-interior/src/aura-assets.ts +16 -0
- package/templates/architecture-interior/src/main.ts +23 -0
- package/templates/architecture-interior/tests/look-floor.ts +270 -0
- package/templates/{three-compat-architecture-interior → architecture-interior}/tests/route-health.spec.ts +3 -3
- package/templates/architecture-interior/tests/screenshot.spec.ts +21 -0
- package/templates/architecture-interior/vite.config.ts +7 -0
- package/templates/arena-shooter/.claude/CLAUDE.md +3 -0
- package/templates/arena-shooter/.github/workflows/aura3d-lookdev.yml +67 -0
- package/templates/arena-shooter/AGENTS.md +3 -0
- package/templates/arena-shooter/README.md +45 -0
- package/templates/arena-shooter/aura.assets.json +62 -0
- package/templates/arena-shooter/index.html +32 -0
- package/templates/arena-shooter/package.json +23 -0
- package/templates/arena-shooter/playwright.config.ts +15 -0
- package/templates/arena-shooter/public/aura-assets/craft_miner.de323205.glb +0 -0
- package/templates/arena-shooter/public/aura-assets/craft_racer.bce8cb3d.glb +0 -0
- package/templates/arena-shooter/public/aura-assets/meteor_detailed.f30379ab.glb +0 -0
- package/templates/arena-shooter/src/aura-assets.ts +56 -0
- package/templates/arena-shooter/src/main.ts +616 -0
- package/templates/arena-shooter/tests/look-floor.ts +270 -0
- package/templates/arena-shooter/tests/playable.spec.ts +56 -0
- package/templates/arena-shooter/tests/route-health.spec.ts +87 -0
- package/templates/arena-shooter/tests/screenshot.spec.ts +22 -0
- package/templates/arena-shooter/tsconfig.json +15 -0
- package/templates/arena-shooter/vite.config.ts +7 -0
- package/templates/asset-inspector/.claude/CLAUDE.md +3 -0
- package/templates/asset-inspector/.github/workflows/aura3d-lookdev.yml +67 -0
- package/templates/asset-inspector/AGENTS.md +3 -0
- package/templates/asset-inspector/README.md +13 -0
- package/templates/asset-inspector/aura.assets.json +24 -0
- package/templates/{three-compat-custom-threejs-migration → asset-inspector}/package.json +6 -4
- package/templates/asset-inspector/public/aura-assets/kenneyCarKitSedanSports.2889c428.glb +0 -0
- package/templates/asset-inspector/src/aura-assets.ts +16 -0
- package/templates/asset-inspector/src/main.ts +23 -0
- package/templates/asset-inspector/tests/look-floor.ts +270 -0
- package/templates/{three-compat-character-viewer → asset-inspector}/tests/route-health.spec.ts +3 -3
- package/templates/asset-inspector/tests/screenshot.spec.ts +21 -0
- package/templates/asset-inspector/vite.config.ts +7 -0
- package/templates/character-controller/.claude/CLAUDE.md +3 -0
- package/templates/character-controller/.github/workflows/aura3d-lookdev.yml +67 -0
- package/templates/character-controller/AGENTS.md +3 -0
- package/templates/character-controller/README.md +7 -1
- package/templates/character-controller/aura.assets.json +29 -22
- package/templates/character-controller/index.html +4 -5
- package/templates/character-controller/package.json +6 -5
- package/templates/character-controller/playwright.config.ts +1 -0
- package/templates/character-controller/public/aura-assets/auraclash-player-rig.glb +0 -0
- package/templates/character-controller/src/aura-assets.ts +25 -7
- package/templates/character-controller/src/main.ts +190 -47
- package/templates/character-controller/tests/certified-rig.spec.ts +2 -2
- package/templates/character-controller/tests/look-floor.ts +270 -0
- package/templates/character-controller/tests/route-health.spec.ts +49 -4
- package/templates/character-controller/tests/screenshot.spec.ts +17 -5
- package/templates/character-controller/vite.config.ts +7 -0
- package/templates/character-viewer/.claude/CLAUDE.md +3 -0
- package/templates/character-viewer/.github/workflows/aura3d-lookdev.yml +67 -0
- package/templates/character-viewer/AGENTS.md +3 -0
- package/templates/character-viewer/README.md +13 -0
- package/templates/character-viewer/aura.assets.json +24 -0
- package/templates/{three-compat-asset-inspector → character-viewer}/package.json +6 -4
- package/templates/character-viewer/public/aura-assets/kenneyMiniForestCharacterArcher.0fd0f92e.glb +0 -0
- package/templates/character-viewer/src/aura-assets.ts +16 -0
- package/templates/character-viewer/src/main.ts +21 -0
- package/templates/character-viewer/tests/look-floor.ts +270 -0
- package/templates/{three-compat-custom-threejs-migration → character-viewer}/tests/route-health.spec.ts +3 -3
- package/templates/character-viewer/tests/screenshot.spec.ts +21 -0
- package/templates/character-viewer/vite.config.ts +7 -0
- package/templates/cinematic-scene/.claude/CLAUDE.md +3 -0
- package/templates/cinematic-scene/.github/workflows/aura3d-lookdev.yml +67 -0
- package/templates/cinematic-scene/AGENTS.md +3 -0
- package/templates/cinematic-scene/README.md +11 -2
- package/templates/cinematic-scene/package.json +4 -3
- package/templates/cinematic-scene/src/main.ts +46 -11
- package/templates/cinematic-scene/tests/look-floor.ts +270 -0
- package/templates/cinematic-scene/tests/route-health.spec.ts +31 -3
- package/templates/cinematic-scene/tests/screenshot.spec.ts +34 -45
- package/templates/cinematic-scene/vite.config.ts +7 -0
- package/templates/custom-scene/.claude/CLAUDE.md +3 -0
- package/templates/custom-scene/.github/workflows/aura3d-lookdev.yml +67 -0
- package/templates/custom-scene/AGENTS.md +3 -0
- package/templates/custom-scene/README.md +13 -0
- package/templates/custom-scene/aura.assets.json +24 -0
- package/templates/{three-compat-character-viewer → custom-scene}/package.json +6 -4
- package/templates/custom-scene/public/aura-assets/kenneyPirateKitShipMedium.279ea019.glb +0 -0
- package/templates/custom-scene/src/aura-assets.ts +16 -0
- package/templates/custom-scene/src/main.ts +23 -0
- package/templates/custom-scene/tests/look-floor.ts +270 -0
- package/templates/{three-compat-asset-inspector → custom-scene}/tests/route-health.spec.ts +3 -3
- package/templates/custom-scene/tests/screenshot.spec.ts +21 -0
- package/templates/custom-scene/vite.config.ts +7 -0
- package/templates/episode-builder/.claude/CLAUDE.md +3 -0
- package/templates/episode-builder/.github/workflows/aura3d-lookdev.yml +67 -0
- package/templates/episode-builder/AGENTS.md +3 -0
- package/templates/episode-builder/package.json +4 -3
- package/templates/episode-builder/src/main.ts +5 -3
- package/templates/episode-builder/src/render-plan.ts +5 -3
- package/templates/episode-builder/tests/look-floor.ts +270 -0
- package/templates/episode-builder/tests/route-health.spec.ts +11 -0
- package/templates/episode-builder/tests/screenshot.spec.ts +10 -4
- package/templates/episode-builder/vite.config.ts +7 -0
- package/templates/falling-blocks-starter/.claude/CLAUDE.md +3 -0
- package/templates/falling-blocks-starter/.github/workflows/aura3d-lookdev.yml +67 -0
- package/templates/falling-blocks-starter/AGENTS.md +3 -0
- package/templates/falling-blocks-starter/README.md +10 -1
- package/templates/falling-blocks-starter/aura.assets.json +40 -23
- package/templates/falling-blocks-starter/package.json +4 -3
- package/templates/falling-blocks-starter/public/aura-assets/quaternius-cube-crate.glb +0 -0
- package/templates/falling-blocks-starter/public/aura-assets/quaternius-wall-modular.glb +0 -0
- package/templates/falling-blocks-starter/src/aura-assets.ts +33 -10
- package/templates/falling-blocks-starter/src/main.ts +317 -96
- package/templates/falling-blocks-starter/tests/look-floor.ts +270 -0
- package/templates/falling-blocks-starter/tests/playable.spec.ts +51 -18
- package/templates/falling-blocks-starter/tests/route-health.spec.ts +17 -7
- package/templates/falling-blocks-starter/tests/screenshot.spec.ts +21 -0
- package/templates/falling-blocks-starter/vite.config.ts +7 -0
- package/templates/fighting-game/.claude/CLAUDE.md +3 -0
- package/templates/fighting-game/.github/workflows/aura3d-lookdev.yml +67 -0
- package/templates/fighting-game/AGENTS.md +3 -0
- package/templates/fighting-game/README.md +2 -0
- package/templates/fighting-game/aura.assets.json +56 -46
- package/templates/fighting-game/package.json +5 -3
- package/templates/fighting-game/public/aura-assets/auraclash-player-rig.glb +0 -0
- package/templates/fighting-game/public/aura-assets/auraclash-rival-rig.glb +0 -0
- package/templates/fighting-game/src/aura-assets.ts +54 -20
- package/templates/fighting-game/src/game/fighters.ts +57 -12
- package/templates/fighting-game/src/main.ts +135 -53
- package/templates/fighting-game/tests/certified-rig.spec.ts +1 -1
- package/templates/fighting-game/tests/gameplay-smoke.spec.ts +25 -33
- package/templates/fighting-game/tests/look-floor.ts +270 -0
- package/templates/fighting-game/tests/route-health.spec.ts +23 -4
- package/templates/fighting-game/tests/screenshot.spec.ts +10 -4
- package/templates/fighting-game/vite.config.ts +7 -0
- package/templates/large-scene/.claude/CLAUDE.md +3 -0
- package/templates/large-scene/.github/workflows/aura3d-lookdev.yml +67 -0
- package/templates/large-scene/AGENTS.md +3 -0
- package/templates/large-scene/README.md +13 -0
- package/templates/large-scene/aura.assets.json +40 -0
- package/templates/{three-compat-architecture-interior → large-scene}/package.json +6 -4
- package/templates/large-scene/public/aura-assets/kenneyMiniForestRocksHigh.226728a0.glb +0 -0
- package/templates/large-scene/public/aura-assets/kenneyMiniForestTree.0075d505.glb +0 -0
- package/templates/large-scene/src/aura-assets.ts +28 -0
- package/templates/large-scene/src/main.ts +43 -0
- package/templates/large-scene/tests/look-floor.ts +270 -0
- package/templates/large-scene/tests/route-health.spec.ts +16 -0
- package/templates/large-scene/tests/screenshot.spec.ts +21 -0
- package/templates/large-scene/vite.config.ts +7 -0
- package/templates/material-authoring/.claude/CLAUDE.md +3 -0
- package/templates/material-authoring/.github/workflows/aura3d-lookdev.yml +67 -0
- package/templates/material-authoring/AGENTS.md +3 -0
- package/templates/material-authoring/README.md +15 -0
- package/templates/material-authoring/aura.assets.json +24 -0
- package/templates/material-authoring/package.json +24 -0
- package/templates/material-authoring/public/aura-assets/kenneyCarKitSedanSports.2889c428.glb +0 -0
- package/templates/material-authoring/src/aura-assets.ts +16 -0
- package/templates/material-authoring/src/main.ts +78 -0
- package/templates/material-authoring/tests/look-floor.ts +270 -0
- package/templates/material-authoring/tests/route-health.spec.ts +16 -0
- package/templates/material-authoring/tests/screenshot.spec.ts +21 -0
- package/templates/material-authoring/vite.config.ts +7 -0
- package/templates/mini-game/.claude/CLAUDE.md +3 -0
- package/templates/mini-game/.github/workflows/aura3d-lookdev.yml +67 -0
- package/templates/mini-game/AGENTS.md +3 -0
- package/templates/mini-game/README.md +9 -6
- package/templates/mini-game/aura.assets.json +177 -36
- package/templates/mini-game/package.json +4 -2
- package/templates/mini-game/public/aura-assets/kaykit-barbarian.glb +0 -0
- package/templates/mini-game/public/aura-assets/kenneyPlatformerKitKey.2e930961.glb +0 -0
- package/templates/mini-game/public/aura-assets/kenneyPlatformerKitStar.a102a1b9.glb +0 -0
- package/templates/mini-game/public/aura-assets/quaternius-crate.glb +0 -0
- package/templates/mini-game/public/aura-assets/quaternius-cube-crate.glb +0 -0
- package/templates/mini-game/src/aura-assets.ts +140 -32
- package/templates/mini-game/src/main.ts +204 -71
- package/templates/mini-game/tests/certified-rig.spec.ts +2 -2
- package/templates/mini-game/tests/look-floor.ts +270 -0
- package/templates/mini-game/tests/playable.spec.ts +23 -2
- package/templates/mini-game/tests/route-health.spec.ts +2 -2
- package/templates/mini-game/tests/screenshot.spec.ts +44 -53
- package/templates/mini-game/vite.config.ts +7 -0
- package/templates/postprocess-scene/.claude/CLAUDE.md +3 -0
- package/templates/postprocess-scene/.github/workflows/aura3d-lookdev.yml +67 -0
- package/templates/postprocess-scene/AGENTS.md +3 -0
- package/templates/postprocess-scene/README.md +17 -0
- package/templates/postprocess-scene/aura.assets.json +38 -0
- package/templates/postprocess-scene/package.json +24 -0
- package/templates/postprocess-scene/public/aura-assets/showcaseLuma.ef389217.glb +0 -0
- package/templates/postprocess-scene/public/aura-assets/showcaseMiko.fcdc2b75.glb +0 -0
- package/templates/postprocess-scene/src/aura-assets.ts +28 -0
- package/templates/postprocess-scene/src/main.ts +29 -0
- package/templates/postprocess-scene/tests/look-floor.ts +270 -0
- package/templates/postprocess-scene/tests/route-health.spec.ts +16 -0
- package/templates/postprocess-scene/tests/screenshot.spec.ts +21 -0
- package/templates/postprocess-scene/vite.config.ts +7 -0
- package/templates/premium-product-viewer/.claude/CLAUDE.md +3 -0
- package/templates/premium-product-viewer/.github/workflows/aura3d-lookdev.yml +67 -0
- package/templates/premium-product-viewer/AGENTS.md +3 -0
- package/templates/premium-product-viewer/README.md +18 -0
- package/templates/premium-product-viewer/aura.assets.json +24 -0
- package/templates/premium-product-viewer/package.json +24 -0
- package/templates/premium-product-viewer/public/aura-assets/khronosToyCar.01a60862.glb +0 -0
- package/templates/premium-product-viewer/src/aura-assets.ts +16 -0
- package/templates/premium-product-viewer/src/main.ts +33 -0
- package/templates/premium-product-viewer/tests/look-floor.ts +270 -0
- package/templates/premium-product-viewer/tests/route-health.spec.ts +16 -0
- package/templates/premium-product-viewer/tests/screenshot.spec.ts +21 -0
- package/templates/premium-product-viewer/vite.config.ts +7 -0
- package/templates/product-viewer/.claude/CLAUDE.md +3 -0
- package/templates/product-viewer/.github/workflows/aura3d-lookdev.yml +67 -0
- package/templates/product-viewer/AGENTS.md +3 -0
- package/templates/product-viewer/README.md +10 -8
- package/templates/product-viewer/package.json +4 -2
- package/templates/product-viewer/src/aura-assets.ts +1 -1
- package/templates/product-viewer/src/main.ts +78 -19
- package/templates/product-viewer/tests/look-floor.ts +270 -0
- package/templates/product-viewer/tests/route-health.spec.ts +19 -1
- package/templates/product-viewer/tests/screenshot.spec.ts +35 -41
- package/templates/product-viewer/vite.config.ts +7 -0
- package/templates/prompt-animation-channel/.claude/CLAUDE.md +3 -0
- package/templates/prompt-animation-channel/.github/workflows/aura3d-lookdev.yml +67 -0
- package/templates/prompt-animation-channel/AGENTS.md +3 -0
- package/templates/prompt-animation-channel/package.json +4 -3
- package/templates/prompt-animation-channel/src/main.ts +5 -3
- package/templates/prompt-animation-channel/src/render-plan.ts +5 -3
- package/templates/prompt-animation-channel/tests/look-floor.ts +270 -0
- package/templates/prompt-animation-channel/tests/route-health.spec.ts +12 -1
- package/templates/prompt-animation-channel/tests/screenshot.spec.ts +10 -4
- package/templates/prompt-animation-channel/tests/storyboard-playback.spec.ts +1 -1
- package/templates/prompt-animation-channel/vite.config.ts +7 -0
- package/templates/racing-starter/.claude/CLAUDE.md +3 -0
- package/templates/racing-starter/.github/workflows/aura3d-lookdev.yml +67 -0
- package/templates/racing-starter/AGENTS.md +3 -0
- package/templates/racing-starter/README.md +8 -6
- package/templates/racing-starter/package.json +4 -3
- package/templates/racing-starter/src/main.ts +169 -123
- package/templates/racing-starter/tests/geometry-certification.json +34 -0
- package/templates/racing-starter/tests/look-floor.ts +270 -0
- package/templates/racing-starter/tests/playable.spec.ts +63 -80
- package/templates/racing-starter/tests/route-health.spec.ts +14 -12
- package/templates/racing-starter/tests/screenshot.spec.ts +21 -0
- package/templates/racing-starter/vite.config.ts +7 -0
- package/templates/character-controller/public/aura-assets/showcaseWalkAnimatedGirl.93872fc2.glb +0 -0
- package/templates/character-controller/public/aura-assets/showcaseWalkAnimatedGirl.thumb.svg +0 -1
- package/templates/falling-blocks-starter/public/aura-assets/showcaseBlockfallCabinet.679d52fe.glb +0 -0
- package/templates/fighting-game/public/aura-assets/showcaseRunnerRobot.252b3a16.glb +0 -0
- package/templates/fighting-game/public/aura-assets/showcaseRunnerRobot.thumb.svg +0 -1
- package/templates/fighting-game/public/aura-assets/showcaseWalkAnimatedGirl.93872fc2.glb +0 -0
- package/templates/fighting-game/public/aura-assets/showcaseWalkAnimatedGirl.thumb.svg +0 -1
- package/templates/mini-game/public/aura-assets/showcaseKenneyOobiPlatformerHero.3f821141.glb +0 -0
- package/templates/mini-game/public/aura-assets/showcaseKenneyOobiPlatformerHero.thumb.svg +0 -1
- package/templates/three-compat-architecture-interior/aura.assets.json +0 -7
- package/templates/three-compat-architecture-interior/src/aura-assets.ts +0 -3
- package/templates/three-compat-architecture-interior/src/main.ts +0 -27
- package/templates/three-compat-architecture-interior/tests/screenshot.spec.ts +0 -15
- package/templates/three-compat-asset-inspector/aura.assets.json +0 -7
- package/templates/three-compat-asset-inspector/src/aura-assets.ts +0 -3
- package/templates/three-compat-asset-inspector/src/main.ts +0 -17
- package/templates/three-compat-asset-inspector/tests/screenshot.spec.ts +0 -15
- package/templates/three-compat-character-viewer/aura.assets.json +0 -7
- package/templates/three-compat-character-viewer/src/aura-assets.ts +0 -3
- package/templates/three-compat-character-viewer/src/main.ts +0 -17
- package/templates/three-compat-character-viewer/tests/screenshot.spec.ts +0 -15
- package/templates/three-compat-custom-threejs-migration/aura.assets.json +0 -7
- package/templates/three-compat-custom-threejs-migration/src/aura-assets.ts +0 -3
- package/templates/three-compat-custom-threejs-migration/src/main.ts +0 -16
- package/templates/three-compat-custom-threejs-migration/tests/screenshot.spec.ts +0 -15
- package/templates/three-compat-large-scene/aura.assets.json +0 -7
- package/templates/three-compat-large-scene/package.json +0 -22
- package/templates/three-compat-large-scene/src/aura-assets.ts +0 -3
- package/templates/three-compat-large-scene/src/main.ts +0 -31
- package/templates/three-compat-large-scene/tests/route-health.spec.ts +0 -16
- package/templates/three-compat-large-scene/tests/screenshot.spec.ts +0 -15
- package/templates/three-compat-material-authoring/aura.assets.json +0 -7
- package/templates/three-compat-material-authoring/package.json +0 -22
- package/templates/three-compat-material-authoring/src/aura-assets.ts +0 -3
- package/templates/three-compat-material-authoring/src/main.ts +0 -33
- package/templates/three-compat-material-authoring/tests/route-health.spec.ts +0 -16
- package/templates/three-compat-material-authoring/tests/screenshot.spec.ts +0 -15
- package/templates/three-compat-postprocess-scene/aura.assets.json +0 -7
- package/templates/three-compat-postprocess-scene/package.json +0 -22
- package/templates/three-compat-postprocess-scene/src/aura-assets.ts +0 -3
- package/templates/three-compat-postprocess-scene/src/main.ts +0 -17
- package/templates/three-compat-postprocess-scene/tests/route-health.spec.ts +0 -16
- package/templates/three-compat-postprocess-scene/tests/screenshot.spec.ts +0 -15
- package/templates/three-compat-premium-product-viewer/aura.assets.json +0 -7
- package/templates/three-compat-premium-product-viewer/package.json +0 -22
- package/templates/three-compat-premium-product-viewer/src/aura-assets.ts +0 -3
- package/templates/three-compat-premium-product-viewer/src/main.ts +0 -18
- package/templates/three-compat-premium-product-viewer/tests/route-health.spec.ts +0 -16
- package/templates/three-compat-premium-product-viewer/tests/screenshot.spec.ts +0 -15
- /package/templates/{three-compat-architecture-interior → architecture-interior}/index.html +0 -0
- /package/templates/{three-compat-architecture-interior → architecture-interior}/playwright.config.ts +0 -0
- /package/templates/{three-compat-architecture-interior → architecture-interior}/tsconfig.json +0 -0
- /package/templates/{three-compat-asset-inspector → asset-inspector}/index.html +0 -0
- /package/templates/{three-compat-asset-inspector → asset-inspector}/playwright.config.ts +0 -0
- /package/templates/{three-compat-asset-inspector → asset-inspector}/tsconfig.json +0 -0
- /package/templates/{three-compat-character-viewer → character-viewer}/index.html +0 -0
- /package/templates/{three-compat-character-viewer → character-viewer}/playwright.config.ts +0 -0
- /package/templates/{three-compat-character-viewer → character-viewer}/tsconfig.json +0 -0
- /package/templates/{three-compat-custom-threejs-migration → custom-scene}/index.html +0 -0
- /package/templates/{three-compat-custom-threejs-migration → custom-scene}/playwright.config.ts +0 -0
- /package/templates/{three-compat-custom-threejs-migration → custom-scene}/tsconfig.json +0 -0
- /package/templates/{three-compat-large-scene → large-scene}/index.html +0 -0
- /package/templates/{three-compat-large-scene → large-scene}/playwright.config.ts +0 -0
- /package/templates/{three-compat-large-scene → large-scene}/tsconfig.json +0 -0
- /package/templates/{three-compat-material-authoring → material-authoring}/index.html +0 -0
- /package/templates/{three-compat-material-authoring → material-authoring}/playwright.config.ts +0 -0
- /package/templates/{three-compat-material-authoring → material-authoring}/tsconfig.json +0 -0
- /package/templates/{three-compat-postprocess-scene → postprocess-scene}/index.html +0 -0
- /package/templates/{three-compat-postprocess-scene → postprocess-scene}/playwright.config.ts +0 -0
- /package/templates/{three-compat-postprocess-scene → postprocess-scene}/tsconfig.json +0 -0
- /package/templates/{three-compat-premium-product-viewer → premium-product-viewer}/index.html +0 -0
- /package/templates/{three-compat-premium-product-viewer → premium-product-viewer}/playwright.config.ts +0 -0
- /package/templates/{three-compat-premium-product-viewer → premium-product-viewer}/tsconfig.json +0 -0
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
2
|
camera,
|
|
3
|
-
createAuraApp,
|
|
4
3
|
game,
|
|
5
|
-
|
|
4
|
+
gameFeel,
|
|
5
|
+
instances,
|
|
6
|
+
looks,
|
|
6
7
|
material,
|
|
7
8
|
model,
|
|
8
|
-
primitives,
|
|
9
9
|
scene,
|
|
10
|
-
type
|
|
10
|
+
type AuraColor,
|
|
11
|
+
type AuraNodeInput,
|
|
12
|
+
type AuraRuntimeNodeHandle,
|
|
13
|
+
type AuraTransformSpec
|
|
11
14
|
} from "@aura3d/engine";
|
|
15
|
+
// PRD-09: mounted via the shared runtime — createGame owns mount/lifecycle,
|
|
16
|
+
// the §7.7 arcade-neon HUD theme, the §6.11 dpad-2btn touch preset,
|
|
17
|
+
// game-sfx-core cues, and the juice event map (no route-local hit-stop).
|
|
18
|
+
import { createGame, sfxUrl } from "@aura3d/engine/game";
|
|
12
19
|
import { assets } from "./aura-assets";
|
|
13
20
|
|
|
14
21
|
declare global {
|
|
@@ -19,6 +26,8 @@ declare global {
|
|
|
19
26
|
|
|
20
27
|
type Piece = "I" | "J" | "L" | "O" | "S" | "T" | "Z";
|
|
21
28
|
type Cell = Piece | null;
|
|
29
|
+
type Board = readonly (readonly Cell[])[];
|
|
30
|
+
type KitState = ReturnType<typeof falling.snapshot>;
|
|
22
31
|
|
|
23
32
|
interface FallingBlocksStarterEvidence {
|
|
24
33
|
readonly frame: number;
|
|
@@ -29,28 +38,53 @@ interface FallingBlocksStarterEvidence {
|
|
|
29
38
|
readonly hold: Piece | null;
|
|
30
39
|
readonly gameOver: boolean;
|
|
31
40
|
readonly events: readonly string[];
|
|
32
|
-
readonly
|
|
33
|
-
|
|
34
|
-
readonly
|
|
35
|
-
readonly
|
|
41
|
+
readonly look: { readonly id: string; readonly category: string };
|
|
42
|
+
readonly board: {
|
|
43
|
+
readonly width: number;
|
|
44
|
+
readonly height: number;
|
|
45
|
+
readonly visibleRows: number;
|
|
46
|
+
readonly filledCells: number;
|
|
47
|
+
readonly rendering: "instanced-model";
|
|
48
|
+
readonly cellAsset: { readonly id: string; readonly url: string; readonly metres: readonly [number, number, number] };
|
|
49
|
+
readonly drawCalls: number;
|
|
36
50
|
};
|
|
51
|
+
readonly flash: { readonly modelBased: boolean; readonly activeRows: readonly number[] };
|
|
37
52
|
readonly evidence: unknown;
|
|
38
53
|
}
|
|
39
54
|
|
|
55
|
+
const LOOK_ID = "neon-arcade" as const;
|
|
40
56
|
const boardWidth = 10;
|
|
41
57
|
const boardHeight = 22;
|
|
42
58
|
const hiddenRows = 2;
|
|
59
|
+
const visibleRows = boardHeight - hiddenRows;
|
|
43
60
|
const cellSize = 0.24;
|
|
44
61
|
const boardOrigin = { x: -1.2, y: -2.18 };
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
62
|
+
const boardTop = boardOrigin.y + visibleRows * cellSize;
|
|
63
|
+
const boardCenterY = (boardOrigin.y + boardTop) / 2;
|
|
64
|
+
|
|
65
|
+
// quaternius-cube-crate is a 2.021 m cube vs the retired 1.082 m block; the
|
|
66
|
+
// scale literals below were authored against the old cube, so RENORM keeps
|
|
67
|
+
// every rendered size identical. CELL_SCALE brings the crate to one
|
|
68
|
+
// 0.24 m board cell; the slight fill reduction keeps a visible bevel gap.
|
|
69
|
+
const RENORM = 1.082 / assets.quaterniusCubeCrate.bounds[1];
|
|
70
|
+
const bs = (n: number) => n * RENORM;
|
|
71
|
+
const CELL_SCALE = (cellSize / 2) * RENORM;
|
|
72
|
+
const CELL_FILL_SCALE = 0.112 * RENORM;
|
|
73
|
+
const FLASH_MS = 280;
|
|
74
|
+
|
|
75
|
+
// Per-piece colours stay inside the neon-arcade palette family: the cyan
|
|
76
|
+
// accent plus its complementary saturated neon hues over the dark base.
|
|
77
|
+
const pieceColors: Record<Piece, AuraColor> = {
|
|
78
|
+
I: "#4de8ff",
|
|
79
|
+
J: "#7d9dd4",
|
|
80
|
+
L: "#f4a259",
|
|
81
|
+
O: "#ffd166",
|
|
82
|
+
S: "#4ce8b0",
|
|
51
83
|
T: "#b987d0",
|
|
52
|
-
Z: "#
|
|
84
|
+
Z: "#ff5d7d"
|
|
53
85
|
};
|
|
86
|
+
const FRAME_COLOR: AuraColor = "#232c4d";
|
|
87
|
+
const FRAME_ACCENT: AuraColor = "#4de8ff";
|
|
54
88
|
const activeShapes: Record<Piece, readonly (readonly { readonly x: number; readonly y: number }[])[]> = {
|
|
55
89
|
I: [
|
|
56
90
|
[{ x: 0, y: 1 }, { x: 1, y: 1 }, { x: 2, y: 1 }, { x: 3, y: 1 }],
|
|
@@ -67,7 +101,7 @@ const activeShapes: Record<Piece, readonly (readonly { readonly x: number; reado
|
|
|
67
101
|
L: [
|
|
68
102
|
[{ x: 2, y: 0 }, { x: 0, y: 1 }, { x: 1, y: 1 }, { x: 2, y: 1 }],
|
|
69
103
|
[{ x: 1, y: 0 }, { x: 1, y: 1 }, { x: 1, y: 2 }, { x: 2, y: 2 }],
|
|
70
|
-
[{ x: 0, y: 1 }, { x: 1, y: 1 }, { x: 2, y: 1 }, { x:
|
|
104
|
+
[{ x: 0, y: 1 }, { x: 1, y: 1 }, { x: 2, y: 1 }, { x: 1, y: 2 }],
|
|
71
105
|
[{ x: 0, y: 0 }, { x: 1, y: 0 }, { x: 1, y: 1 }, { x: 1, y: 2 }]
|
|
72
106
|
],
|
|
73
107
|
O: [
|
|
@@ -89,14 +123,14 @@ const activeShapes: Record<Piece, readonly (readonly { readonly x: number; reado
|
|
|
89
123
|
[{ x: 1, y: 0 }, { x: 0, y: 1 }, { x: 1, y: 1 }, { x: 1, y: 2 }]
|
|
90
124
|
],
|
|
91
125
|
Z: [
|
|
92
|
-
[{ x: 0, y: 0 }, { x: 1, y: 0 }, { x: 1, y: 1 }, { x:
|
|
126
|
+
[{ x: 0, y: 0 }, { x: 1, y: 0 }, { x: 1, y: 1 }, { x: 1, y: 2 }],
|
|
93
127
|
[{ x: 2, y: 0 }, { x: 1, y: 1 }, { x: 2, y: 1 }, { x: 1, y: 2 }],
|
|
94
128
|
[{ x: 0, y: 1 }, { x: 1, y: 1 }, { x: 1, y: 2 }, { x: 2, y: 2 }],
|
|
95
129
|
[{ x: 1, y: 0 }, { x: 0, y: 1 }, { x: 1, y: 1 }, { x: 0, y: 2 }]
|
|
96
130
|
]
|
|
97
131
|
};
|
|
98
132
|
|
|
99
|
-
const
|
|
133
|
+
const inputOptions = {
|
|
100
134
|
actions: {
|
|
101
135
|
left: ["KeyA", "ArrowLeft"],
|
|
102
136
|
right: ["KeyD", "ArrowRight"],
|
|
@@ -108,7 +142,7 @@ const input = game.input({
|
|
|
108
142
|
reset: ["KeyR"]
|
|
109
143
|
},
|
|
110
144
|
bufferMs: 100
|
|
111
|
-
}
|
|
145
|
+
} as const;
|
|
112
146
|
|
|
113
147
|
const falling = game.fallingBlocks({
|
|
114
148
|
width: boardWidth,
|
|
@@ -119,33 +153,85 @@ const falling = game.fallingBlocks({
|
|
|
119
153
|
lockDelayFrames: 18
|
|
120
154
|
});
|
|
121
155
|
const routeEvents = game.eventLog({ label: "falling blocks starter events", maxEvents: 18 });
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
game
|
|
126
|
-
|
|
127
|
-
|
|
156
|
+
// HUD bindings as descriptor literals (the deprecated game.hud.* helpers are
|
|
157
|
+
// replaced by the createGame `hud` option + evidence channel sections).
|
|
158
|
+
const hudBindings = [
|
|
159
|
+
{ kind: "aura-game-hud-binding", owner: "app", binding: "score", id: "hud:score", label: "score", source: "app-state", valuePath: "appState.score", format: "number", a11yLabel: "score" },
|
|
160
|
+
{ kind: "aura-game-hud-binding", owner: "app", binding: "objective", id: "hud:objective", label: "objective", source: "app-state", valuePath: "appState.objective", format: "text", a11yLabel: "current objective" },
|
|
161
|
+
{ kind: "aura-game-hud-binding", owner: "app", binding: "event-log", id: "hud:event-log", label: "event log", source: "app-state", valuePath: "appState.events", format: "text", a11yLabel: "game event log", debugOnly: true }
|
|
162
|
+
] as const;
|
|
128
163
|
|
|
129
164
|
setupPracticeBoard();
|
|
130
165
|
|
|
131
|
-
const
|
|
166
|
+
const blockfallGame = createGame({
|
|
167
|
+
id: "falling-blocks-starter",
|
|
168
|
+
target: "#app",
|
|
132
169
|
diagnostics: { overlay: true, performancePanel: true },
|
|
133
|
-
scene: buildScene()
|
|
170
|
+
scene: () => buildScene(falling.snapshot().board),
|
|
171
|
+
input: inputOptions,
|
|
172
|
+
hud: { theme: "arcade-neon", widgets: [] },
|
|
173
|
+
touch: {
|
|
174
|
+
preset: "dpad-2btn",
|
|
175
|
+
bindings: { left: "left", right: "right", dash: "softDrop", jump: "rotateRight", attack: "hardDrop" }
|
|
176
|
+
},
|
|
177
|
+
sound: {
|
|
178
|
+
cues: {
|
|
179
|
+
move: { id: "move", asset: { url: sfxUrl("ui.toggle.00") }, volume: 0.3 },
|
|
180
|
+
rotate: { id: "rotate", asset: { url: sfxUrl("ui.toggle.01") }, volume: 0.35 },
|
|
181
|
+
"hard-drop": { id: "hard-drop", asset: { url: sfxUrl("impact.wood.medium.00") }, volume: 0.6 },
|
|
182
|
+
"line-clear": { id: "line-clear", asset: { url: sfxUrl("pickup.coin.00") }, volume: 0.8 },
|
|
183
|
+
"game-over": { id: "game-over", asset: { url: sfxUrl("stinger.lose.00") }, volume: 0.8 }
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
juice: {
|
|
187
|
+
"hard-drop": { hitStop: 0.03, shake: 0.25, rumble: { strong: 0.4, ms: 120 } },
|
|
188
|
+
"line-clear": { flash: { color: "#5ed7df", peak: 0.22, ms: 240 }, punch: { fovDeg: 1.8, ms: 220 }, rumble: { weak: 0.5, ms: 200 } },
|
|
189
|
+
"game-over": { flash: { color: "#d88791", peak: 0.3, ms: 400 }, vignette: { amount: 0.6, ms: 900 } }
|
|
190
|
+
},
|
|
191
|
+
qualityRebuild: { flags: ["game"] },
|
|
192
|
+
evidence: {
|
|
193
|
+
schema: 1,
|
|
194
|
+
sections: { fallingBlocksStarter: () => window.__AURA3D_FALLING_BLOCKS_STARTER__ ?? { status: "unbound" } }
|
|
195
|
+
}
|
|
134
196
|
});
|
|
197
|
+
const app = blockfallGame.app;
|
|
198
|
+
blockfallGame.start();
|
|
199
|
+
const input = blockfallGame.input;
|
|
200
|
+
if (!input) throw new Error("create-aura3d falling-blocks-starter failed to create runtime-owned input.");
|
|
135
201
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
202
|
+
// Runtime handles are re-required after every setScene rebuild because the
|
|
203
|
+
// instanced settled board is mount-time data, not a mutable runtime spec.
|
|
204
|
+
let activeNodes: AuraRuntimeNodeHandle[] = [];
|
|
205
|
+
let flashNodes: AuraRuntimeNodeHandle[] = [];
|
|
206
|
+
let holdNode: AuraRuntimeNodeHandle | undefined;
|
|
207
|
+
mountRuntimeHandles();
|
|
141
208
|
const hudRoot = createHud();
|
|
142
209
|
let objective = "Clear the prepared line. Move, rotate, hold, or hard drop.";
|
|
143
210
|
let tickAccumulator = 0;
|
|
211
|
+
let settledSignature = settledCellsSignature(falling.snapshot().board);
|
|
212
|
+
let previousBoard: Board = falling.snapshot().board;
|
|
213
|
+
let flashRows: { readonly rows: readonly number[]; readonly until: number } = { rows: [], until: 0 };
|
|
214
|
+
let activeKind: Piece | null = null;
|
|
215
|
+
let holdKind: Piece | null = null;
|
|
144
216
|
|
|
145
|
-
|
|
146
|
-
|
|
217
|
+
// F-08-1: a static rig presents the board framing, pitched ~10° about X off
|
|
218
|
+
// the authored spec (flag-off mounts the no-op stub controller; that spec
|
|
219
|
+
// stays the fallback). F-08-5: feel bus + GameFeel attach through app.time.
|
|
220
|
+
app.camera?.use(
|
|
221
|
+
camera.rigs.static({
|
|
222
|
+
position: [0.35, boardCenterY + 0.81, 4.6],
|
|
223
|
+
target: [0, boardCenterY, 0],
|
|
224
|
+
orthographicSize: 2.9
|
|
225
|
+
})
|
|
226
|
+
);
|
|
227
|
+
const feel = gameFeel.create({ app, time: app.time });
|
|
228
|
+
app.feel?.preset("puzzle");
|
|
229
|
+
|
|
230
|
+
app.onFrame(({ dt }) => {
|
|
231
|
+
feel.update(dt * 1000);
|
|
147
232
|
if (input.pressed("reset")) {
|
|
148
233
|
setupPracticeBoard();
|
|
234
|
+
flashRows = { rows: [], until: 0 };
|
|
149
235
|
routeEvents.push({ type: "reset", label: "reset" });
|
|
150
236
|
objective = "Clear the prepared line. Move, rotate, hold, or hard drop.";
|
|
151
237
|
}
|
|
@@ -164,16 +250,19 @@ app.onFrame(({ dt }: { readonly dt: number }) => {
|
|
|
164
250
|
}
|
|
165
251
|
|
|
166
252
|
const state = falling.snapshot();
|
|
253
|
+
rebuildSettledCells(state);
|
|
167
254
|
renderBoard(state);
|
|
168
255
|
renderHud(state);
|
|
169
256
|
publishEvidence(state);
|
|
257
|
+
previousBoard = state.board;
|
|
170
258
|
});
|
|
171
259
|
|
|
172
260
|
renderBoard(falling.snapshot());
|
|
173
261
|
renderHud(falling.snapshot());
|
|
174
262
|
publishEvidence(falling.snapshot());
|
|
175
263
|
|
|
176
|
-
|
|
264
|
+
|
|
265
|
+
function recordKitEvents(state: KitState): void {
|
|
177
266
|
for (const event of state.events) {
|
|
178
267
|
routeEvents.push({
|
|
179
268
|
type: event.type,
|
|
@@ -181,10 +270,21 @@ function recordKitEvents(state: ReturnType<typeof falling.snapshot>): void {
|
|
|
181
270
|
severity: event.type === "line-clear" ? "success" : event.type === "game-over" ? "warning" : "info",
|
|
182
271
|
frame: event.frame
|
|
183
272
|
});
|
|
184
|
-
if (event.type === "line-clear")
|
|
273
|
+
if (event.type === "line-clear") {
|
|
274
|
+
objective = `Line clear. ${state.lines} line cleared. Press R to replay.`;
|
|
275
|
+
// The kit reports the count, not the rows: the cleared rows are exactly
|
|
276
|
+
// the rows that were full in the previous snapshot's board.
|
|
277
|
+
const cleared = fullRows(previousBoard).filter((row) => row >= hiddenRows);
|
|
278
|
+
flashRows = { rows: cleared, until: performance.now() + FLASH_MS };
|
|
279
|
+
}
|
|
185
280
|
if (event.type === "hold") objective = "Held piece. Press R or continue.";
|
|
186
281
|
if (event.type === "rotate") objective = "Rotation accepted.";
|
|
187
282
|
if (event.type === "move") objective = "Move accepted.";
|
|
283
|
+
if (event.type === "move" || event.type === "rotate") void blockfallGame.sound?.cue(event.type);
|
|
284
|
+
if (event.type === "hard-drop" || event.type === "line-clear" || event.type === "game-over") {
|
|
285
|
+
blockfallGame.juice.fire(event.type);
|
|
286
|
+
void blockfallGame.sound?.cue(event.type);
|
|
287
|
+
}
|
|
188
288
|
}
|
|
189
289
|
}
|
|
190
290
|
|
|
@@ -202,85 +302,207 @@ function createPracticeBoard(): Cell[][] {
|
|
|
202
302
|
return board;
|
|
203
303
|
}
|
|
204
304
|
|
|
205
|
-
function buildScene() {
|
|
305
|
+
function buildScene(board: Board) {
|
|
206
306
|
const nodes: AuraNodeInput[] = [
|
|
207
|
-
|
|
208
|
-
|
|
307
|
+
// Modular wall panel stands in for the arcade cabinet silhouette
|
|
308
|
+
// (library approximation, #481 mapping); scale keeps the old height.
|
|
309
|
+
model(assets.quaterniusWallModular, { name: "typed arcade cabinet", castShadow: true })
|
|
310
|
+
.position(1.9, 0.2, -0.7)
|
|
209
311
|
.scale(0.2),
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
.
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
...boardCellNodes(),
|
|
312
|
+
// Dark glossy board backing sourced from the same typed block GLB.
|
|
313
|
+
model(assets.quaterniusCubeCrate, { name: "board glossy backplate", material: material.pbr({ color: "#0b0e18", roughness: 0.18, metalness: 0.55 }) })
|
|
314
|
+
.position(0, boardCenterY, -0.16)
|
|
315
|
+
.scale([bs(1.42), bs(2.5), bs(0.03)]),
|
|
316
|
+
...boardFrameNodes(),
|
|
317
|
+
...settledCellsNode(board),
|
|
217
318
|
...activeCellNodes(),
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
.
|
|
319
|
+
...flashRowNodes(),
|
|
320
|
+
model(assets.quaterniusCubeCrate, { name: "hold preview", material: material.neon({ color: "#b987d0", emissive: "#b987d0", emissiveIntensity: 0.5 }) })
|
|
321
|
+
.position(-2.05, 1.92, 0.1)
|
|
322
|
+
.scale(bs(0.09))
|
|
221
323
|
.runtime(game.runtimeNode("hold-preview", { tags: ["hold", "runtime"] }))
|
|
222
324
|
];
|
|
223
325
|
|
|
326
|
+
// The neon-arcade look supplies the night-city sky gradient, key light,
|
|
327
|
+
// fog and grade — no ambient fill, background override or debug overlay.
|
|
224
328
|
return scene()
|
|
225
|
-
.
|
|
329
|
+
.add(looks.preset(LOOK_ID))
|
|
226
330
|
.addMany(nodes)
|
|
227
|
-
.
|
|
228
|
-
.add(lights.directional({ name: "blockfall key", position: [3.8, 6.2, 5], intensity: 1.15, color: "#ffffff" }))
|
|
229
|
-
.camera(camera.perspective({ position: [0.25, 1.2, 7.2], target: [0.1, 0.1, 0], fov: 38 }));
|
|
331
|
+
.camera(camera.orthographic({ position: [0.35, 0.75, 4.6], target: [0, boardCenterY, 0], orthographicSize: 2.9 }));
|
|
230
332
|
}
|
|
231
333
|
|
|
232
|
-
function
|
|
233
|
-
const
|
|
334
|
+
function boardFrameNodes(): AuraNodeInput[] {
|
|
335
|
+
const rail = material.pbr({ color: FRAME_COLOR, roughness: 0.3, metalness: 0.5, emissive: FRAME_ACCENT, emissiveIntensity: 0.22 });
|
|
336
|
+
const railThickness = 0.045; // 0.09 m rails around the 2.4 × 4.8 m well
|
|
337
|
+
const railHeight = (visibleRows * cellSize) / 2 + railThickness;
|
|
338
|
+
return [
|
|
339
|
+
model(assets.quaterniusCubeCrate, { name: "board frame left rail", material: rail })
|
|
340
|
+
.position(boardOrigin.x - railThickness, boardCenterY, 0)
|
|
341
|
+
.scale([bs(railThickness), bs(railHeight), bs(0.09)]),
|
|
342
|
+
model(assets.quaterniusCubeCrate, { name: "board frame right rail", material: rail })
|
|
343
|
+
.position(-boardOrigin.x + railThickness, boardCenterY, 0)
|
|
344
|
+
.scale([bs(railThickness), bs(railHeight), bs(0.09)]),
|
|
345
|
+
model(assets.quaterniusCubeCrate, { name: "board frame bottom rail", material: rail })
|
|
346
|
+
.position(0, boardOrigin.y - railThickness, 0)
|
|
347
|
+
.scale([bs(0.69), bs(railThickness), bs(0.09)]),
|
|
348
|
+
model(assets.quaterniusCubeCrate, { name: "board frame top rail", material: rail })
|
|
349
|
+
.position(0, boardTop + railThickness, 0)
|
|
350
|
+
.scale([bs(0.69), bs(railThickness), bs(0.09)])
|
|
351
|
+
];
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// The settled board renders as ONE instanced bevelled-cube mesh: every filled
|
|
355
|
+
// cell is an instance of the typed block GLB tinted to its piece colour.
|
|
356
|
+
function settledCellsNode(board: Board): AuraNodeInput[] {
|
|
357
|
+
const transforms: AuraTransformSpec[] = [];
|
|
358
|
+
const colors: AuraColor[] = [];
|
|
234
359
|
for (let y = hiddenRows; y < boardHeight; y += 1) {
|
|
235
360
|
for (let x = 0; x < boardWidth; x += 1) {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
);
|
|
361
|
+
const cell = board[y]?.[x];
|
|
362
|
+
if (!cell) continue;
|
|
363
|
+
const [px, py] = cellPosition(x, y);
|
|
364
|
+
transforms.push({ position: [px, py, 0], scale: CELL_FILL_SCALE });
|
|
365
|
+
colors.push(pieceColors[cell]);
|
|
242
366
|
}
|
|
243
367
|
}
|
|
244
|
-
|
|
368
|
+
if (transforms.length === 0) {
|
|
369
|
+
// instances.* requires at least one transform; park a scale-0 dummy.
|
|
370
|
+
transforms.push({ position: [0, -50, 0], scale: 0 });
|
|
371
|
+
colors.push("#141828");
|
|
372
|
+
}
|
|
373
|
+
return [
|
|
374
|
+
instances.model(assets.quaterniusCubeCrate, {
|
|
375
|
+
name: "settled board cells",
|
|
376
|
+
transforms,
|
|
377
|
+
colors,
|
|
378
|
+
material: material.pbr({ color: "#ffffff", roughness: 0.22, metalness: 0.3 }),
|
|
379
|
+
instancingAware: true
|
|
380
|
+
})
|
|
381
|
+
];
|
|
245
382
|
}
|
|
246
383
|
|
|
247
384
|
function activeCellNodes(): AuraNodeInput[] {
|
|
248
385
|
return Array.from({ length: 4 }, (_, index) =>
|
|
249
|
-
|
|
250
|
-
.position(
|
|
251
|
-
.scale(
|
|
386
|
+
model(assets.quaterniusCubeCrate, { name: `active piece cell ${index}`, material: material.neon({ color: "#4de8ff", emissive: "#4de8ff", emissiveIntensity: 0.45 }) })
|
|
387
|
+
.position(0, -50, 0.14)
|
|
388
|
+
.scale(CELL_SCALE)
|
|
252
389
|
.runtime(game.runtimeNode(`active-cell-${index}`, { tags: ["active-cell", "runtime"] }))
|
|
253
390
|
);
|
|
254
391
|
}
|
|
255
392
|
|
|
256
|
-
|
|
393
|
+
// Line-clear flash is a model surface, not a particle pool: four instanced-GLB
|
|
394
|
+
// bars stretch across the board and pulse emissive while a clear animates.
|
|
395
|
+
function flashRowNodes(): AuraNodeInput[] {
|
|
396
|
+
return Array.from({ length: 4 }, (_, index) =>
|
|
397
|
+
model(assets.quaterniusCubeCrate, { name: `line clear flash ${index}`, material: material.neon({ color: FRAME_ACCENT, emissive: FRAME_ACCENT, emissiveIntensity: 1.6 }) })
|
|
398
|
+
.position(0, -50, 0.16)
|
|
399
|
+
.scale([bs(0.66), CELL_FILL_SCALE, bs(0.05)])
|
|
400
|
+
.runtime(game.runtimeNode(`flash-row-${index}`, { tags: ["flash", "runtime"] }))
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
function mountRuntimeHandles(): void {
|
|
405
|
+
activeNodes = Array.from({ length: 4 }, (_, index) => app.nodes.require(`active-cell-${index}`));
|
|
406
|
+
flashNodes = Array.from({ length: 4 }, (_, index) => app.nodes.require(`flash-row-${index}`));
|
|
407
|
+
holdNode = app.nodes.require("hold-preview");
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// The instanced settled mesh is mount-time data: rebuild the scene only when
|
|
411
|
+
// the settled board signature changes (lock, line clear, reset) — never on
|
|
412
|
+
// per-frame motion of the active piece.
|
|
413
|
+
function rebuildSettledCells(state: KitState): void {
|
|
414
|
+
const signature = settledCellsSignature(state.board);
|
|
415
|
+
if (signature === settledSignature) return;
|
|
416
|
+
try {
|
|
417
|
+
app.setScene(buildScene(state.board));
|
|
418
|
+
} catch {
|
|
419
|
+
// Frame submission can be pending during a mid-frame rebuild; retry on the
|
|
420
|
+
// next frame instead of tearing down the gameplay callback.
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
settledSignature = signature;
|
|
424
|
+
mountRuntimeHandles();
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function settledCellsSignature(board: Board): string {
|
|
428
|
+
const cells: string[] = [];
|
|
429
|
+
for (let y = hiddenRows; y < boardHeight; y += 1) {
|
|
430
|
+
for (let x = 0; x < boardWidth; x += 1) {
|
|
431
|
+
const cell = board[y]?.[x];
|
|
432
|
+
if (cell) cells.push(`${x}:${y}:${cell}`);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
return cells.join("|");
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
function fullRows(board: Board): number[] {
|
|
439
|
+
const rows: number[] = [];
|
|
440
|
+
for (let y = hiddenRows; y < boardHeight; y += 1) {
|
|
441
|
+
if (board[y]?.every((cell) => cell !== null)) rows.push(y);
|
|
442
|
+
}
|
|
443
|
+
return rows;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
function filledCellCount(board: Board): number {
|
|
447
|
+
let count = 0;
|
|
257
448
|
for (let y = hiddenRows; y < boardHeight; y += 1) {
|
|
258
449
|
for (let x = 0; x < boardWidth; x += 1) {
|
|
259
|
-
|
|
260
|
-
const cell = state.board[y][x];
|
|
261
|
-
node.setVisible(Boolean(cell)).setPosition(...cellPosition(x, y), 0);
|
|
450
|
+
if (board[y]?.[x]) count += 1;
|
|
262
451
|
}
|
|
263
452
|
}
|
|
453
|
+
return count;
|
|
454
|
+
}
|
|
264
455
|
|
|
265
|
-
|
|
456
|
+
function renderBoard(state: KitState): void {
|
|
266
457
|
if (state.active) {
|
|
267
|
-
const
|
|
268
|
-
|
|
458
|
+
const kind = state.active.kind;
|
|
459
|
+
if (kind !== activeKind) {
|
|
460
|
+
const activeMaterial = material.neon({ color: pieceColors[kind], emissive: pieceColors[kind], emissiveIntensity: 0.45 });
|
|
461
|
+
activeNodes.forEach((node) => node.setMaterial(activeMaterial));
|
|
462
|
+
activeKind = kind;
|
|
463
|
+
}
|
|
464
|
+
const cells = activeShapes[kind][state.active.rotation] ?? activeShapes[kind][0];
|
|
465
|
+
activeNodes.forEach((node, index) => {
|
|
466
|
+
const cell = cells[index];
|
|
467
|
+
if (!cell) {
|
|
468
|
+
node.setVisible(false);
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
269
471
|
const x = state.active!.x + cell.x;
|
|
270
472
|
const y = state.active!.y + cell.y;
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
.setPosition(...cellPosition(x, y), 0.14)
|
|
274
|
-
.setScale([cellSize * 0.94, cellSize * 0.94, 0.16]);
|
|
473
|
+
const [px, py] = cellPosition(x, y);
|
|
474
|
+
node.setVisible(y >= hiddenRows).setPosition(px, py, 0.14).setScale(CELL_SCALE);
|
|
275
475
|
});
|
|
476
|
+
} else {
|
|
477
|
+
activeNodes.forEach((node) => node.setVisible(false));
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
const flashing = performance.now() < flashRows.until;
|
|
481
|
+
flashNodes.forEach((node, index) => {
|
|
482
|
+
const row = flashRows.rows[index];
|
|
483
|
+
if (!flashing || row === undefined) {
|
|
484
|
+
node.setVisible(false);
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
const [, py] = cellPosition(0, row);
|
|
488
|
+
node.setVisible(true).setPosition(0, py, 0.16);
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
if (state.hold) {
|
|
492
|
+
if (state.hold !== holdKind) {
|
|
493
|
+
holdKind = state.hold;
|
|
494
|
+
holdNode?.setMaterial(material.neon({ color: pieceColors[holdKind], emissive: pieceColors[holdKind], emissiveIntensity: 0.5 }));
|
|
495
|
+
}
|
|
496
|
+
holdNode?.setVisible(true);
|
|
497
|
+
} else {
|
|
498
|
+
holdNode?.setVisible(false);
|
|
276
499
|
}
|
|
277
|
-
holdNode.setVisible(Boolean(state.hold));
|
|
278
500
|
}
|
|
279
501
|
|
|
280
502
|
function cellPosition(x: number, y: number): [number, number] {
|
|
281
503
|
return [
|
|
282
504
|
boardOrigin.x + (x + 0.5) * cellSize,
|
|
283
|
-
boardOrigin.y + (
|
|
505
|
+
boardOrigin.y + (visibleRows - (y - hiddenRows) - 0.5) * cellSize
|
|
284
506
|
];
|
|
285
507
|
}
|
|
286
508
|
|
|
@@ -295,8 +517,8 @@ function createHud(): HTMLElement {
|
|
|
295
517
|
"min-width:310px",
|
|
296
518
|
"font:600 13px/1.35 Inter, system-ui, sans-serif",
|
|
297
519
|
"color:#f5fbff",
|
|
298
|
-
"background:rgba(
|
|
299
|
-
"border:1px solid rgba(
|
|
520
|
+
"background:rgba(8,10,22,0.72)",
|
|
521
|
+
"border:1px solid rgba(77,232,255,0.34)",
|
|
300
522
|
"border-radius:8px",
|
|
301
523
|
"padding:12px",
|
|
302
524
|
"pointer-events:none"
|
|
@@ -305,7 +527,7 @@ function createHud(): HTMLElement {
|
|
|
305
527
|
return root;
|
|
306
528
|
}
|
|
307
529
|
|
|
308
|
-
function renderHud(state:
|
|
530
|
+
function renderHud(state: KitState): void {
|
|
309
531
|
hudRoot.innerHTML = [
|
|
310
532
|
`<strong>Aura3D Falling Blocks Starter</strong>`,
|
|
311
533
|
`<div>Score ${state.score} | Lines ${state.lines} | Level ${state.level}</div>`,
|
|
@@ -315,11 +537,11 @@ function renderHud(state: ReturnType<typeof falling.snapshot>): void {
|
|
|
315
537
|
].join("");
|
|
316
538
|
}
|
|
317
539
|
|
|
318
|
-
function publishEvidence(state:
|
|
540
|
+
function publishEvidence(state: KitState): void {
|
|
319
541
|
const evidence = app.evidence({
|
|
320
542
|
input,
|
|
321
543
|
events: routeEvents,
|
|
322
|
-
hud,
|
|
544
|
+
hud: hudBindings,
|
|
323
545
|
appState: {
|
|
324
546
|
score: state.score,
|
|
325
547
|
objective,
|
|
@@ -331,6 +553,7 @@ function publishEvidence(state: ReturnType<typeof falling.snapshot>): void {
|
|
|
331
553
|
},
|
|
332
554
|
source: { expectsGame: true }
|
|
333
555
|
});
|
|
556
|
+
const diagnostics = app.diagnostics();
|
|
334
557
|
window.__AURA3D_FALLING_BLOCKS_STARTER__ = {
|
|
335
558
|
frame: state.frame,
|
|
336
559
|
score: state.score,
|
|
@@ -340,19 +563,17 @@ function publishEvidence(state: ReturnType<typeof falling.snapshot>): void {
|
|
|
340
563
|
hold: state.hold,
|
|
341
564
|
gameOver: state.gameOver,
|
|
342
565
|
events: routeEvents.events().map((event: { readonly label: string }) => event.label),
|
|
343
|
-
|
|
566
|
+
look: { id: LOOK_ID, category: "studio" },
|
|
567
|
+
board: {
|
|
568
|
+
width: boardWidth,
|
|
569
|
+
height: boardHeight,
|
|
570
|
+
visibleRows,
|
|
571
|
+
filledCells: filledCellCount(state.board),
|
|
572
|
+
rendering: "instanced-model",
|
|
573
|
+
cellAsset: { id: "quaterniusCubeCrate", url: assets.quaterniusCubeCrate.url, metres: assets.quaterniusCubeCrate.bounds },
|
|
574
|
+
drawCalls: diagnostics.drawCalls
|
|
575
|
+
},
|
|
576
|
+
flash: { modelBased: true, activeRows: performance.now() < flashRows.until ? flashRows.rows : [] },
|
|
344
577
|
evidence
|
|
345
578
|
};
|
|
346
579
|
}
|
|
347
|
-
|
|
348
|
-
function createLineClearProof(): FallingBlocksStarterEvidence["lineClearProof"] {
|
|
349
|
-
const proof = game.fallingBlocks({ width: boardWidth, height: boardHeight, hiddenRows, seed: 7, gravityFrames: 999 });
|
|
350
|
-
proof.setBoard(createPracticeBoard());
|
|
351
|
-
proof.setActive({ kind: "I", x: 3, y: boardHeight - 3, rotation: 0 });
|
|
352
|
-
const cleared = proof.hardDrop();
|
|
353
|
-
return {
|
|
354
|
-
lines: cleared.lines,
|
|
355
|
-
events: cleared.events.map((event) => event.piece ? `${event.type}:${event.piece}` : event.type),
|
|
356
|
-
checksum: cleared.checksum
|
|
357
|
-
};
|
|
358
|
-
}
|