@inneranimalmedia/agentsam-sdk 2.6.5 → 2.6.7
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/AGENTSAM.md +29 -0
- package/apps/README.md +5 -0
- package/apps/cad-creator/README.md +4 -4
- package/apps/cad-creator/shared/cad/package.json +1 -1
- package/apps/client-cms-editor/AGENTS.md +12 -7
- package/apps/client-cms-editor/README.md +76 -48
- package/apps/client-cms-editor/agentsam.app.json +26 -9
- package/apps/client-cms-editor/backend/package.json +20 -3
- package/apps/client-cms-editor/backend/src/api/client.ts +134 -101
- package/apps/client-cms-editor/backend/src/index.ts +1 -1
- package/apps/client-cms-editor/backend/src/model.ts +11 -115
- package/apps/client-cms-editor/backend/src/preview/bridge.ts +1 -1
- package/apps/client-cms-editor/backend/tsconfig.json +6 -1
- package/apps/client-cms-editor/bin/agentsam-cms.js +262 -0
- package/apps/client-cms-editor/bin/agentsam-cms.mjs +2 -228
- package/apps/client-cms-editor/frontend/package.json +16 -7
- package/apps/client-cms-editor/frontend/src/AgentSamDrawer.tsx +9 -41
- package/apps/client-cms-editor/frontend/src/CmsAgentSurface.tsx +19 -174
- package/apps/client-cms-editor/frontend/src/adapters/heuristic.ts +29 -0
- package/apps/client-cms-editor/frontend/src/adapters/http.ts +628 -0
- package/apps/client-cms-editor/frontend/src/adapters/memory.ts +510 -0
- package/apps/client-cms-editor/frontend/src/editor/CmsEditor.tsx +213 -0
- package/apps/client-cms-editor/frontend/src/editor/CmsEditorProvider.tsx +20 -0
- package/apps/client-cms-editor/frontend/src/editor/canvas/PreviewCanvas.tsx +53 -0
- package/apps/client-cms-editor/frontend/src/{CmsEditor.tsx → editor/legacy/CmsEditorPrototype.tsx} +52 -23
- package/apps/client-cms-editor/frontend/src/editor/useCmsEditorController.ts +218 -0
- package/apps/client-cms-editor/frontend/src/index.ts +19 -5
- package/apps/client-cms-editor/frontend/src/lib/agent-host.ts +24 -0
- package/apps/client-cms-editor/frontend/src/main.tsx +82 -8
- package/apps/client-cms-editor/frontend/src/mount.tsx +92 -30
- package/apps/client-cms-editor/frontend/src/styles/agentsam-drawer.css +1 -1
- package/apps/client-cms-editor/frontend/src/styles/cmsShell.css +8 -8
- package/apps/client-cms-editor/frontend/src/styles/studio.css +55 -3
- package/apps/client-cms-editor/frontend/tsconfig.json +12 -1
- package/apps/client-cms-editor/frontend/vite.config.ts +12 -0
- package/apps/client-cms-editor/package-lock.json +973 -134
- package/apps/client-cms-editor/package.json +118 -6
- package/apps/client-cms-editor/reference/harvest/HARVEST_RECEIPT.json +201 -0
- package/apps/client-cms-editor/reference/harvest/PROVENANCE_HISTORY.txt +10 -0
- package/apps/client-cms-editor/reference/harvest/README.md +8 -0
- package/apps/client-cms-editor/reference/harvest/plans/ARCHIVE-INTAKE.md +135 -0
- package/apps/client-cms-editor/reference/harvest/plans/CHATGPT-IDENTITY-HARVEST.md +83 -0
- package/apps/client-cms-editor/reference/harvest/plans/CMS-EDITOR-HARVEST.md +166 -0
- package/apps/client-cms-editor/reference/harvest/plans/HARVEST-INDEX.md +196 -0
- package/apps/client-cms-editor/reference/harvest/plans/INNERANIMALS-CONTENT-001.md +137 -0
- package/apps/client-cms-editor/reference/harvest/plans/NO-IMPLICIT-SIDE-EFFECTS.md +87 -0
- package/apps/client-cms-editor/reference/harvest/plans/STOREFRONT-SURFACE-MAP.md +140 -0
- package/apps/client-cms-editor/reference/harvest/plans/THEME-INNERANIMALS-HARVEST.md +137 -0
- package/apps/client-cms-editor/reference/harvest/plans/TOOLING-LAB.md +63 -0
- package/apps/client-cms-editor/reference/harvest/plans/harvest-manifest.json +97 -0
- package/apps/client-cms-editor/reference/harvest/plans/local-cms-harvest-schema.sql +328 -0
- package/apps/client-cms-editor/shared/cms/package.json +17 -7
- package/apps/client-cms-editor/shared/cms/src/adapter.ts +204 -0
- package/apps/client-cms-editor/shared/cms/src/agent-context.ts +7 -5
- package/apps/client-cms-editor/shared/cms/src/editor-types.ts +32 -0
- package/apps/client-cms-editor/shared/cms/src/host.ts +82 -0
- package/apps/client-cms-editor/shared/cms/src/index.ts +4 -0
- package/apps/client-cms-editor/shared/cms/src/map.ts +115 -0
- package/apps/client-cms-editor/shared/cms/src/starter-pack.ts +158 -0
- package/contracts/source-types.v1.json +353 -0
- package/docs/CMS_CONTEXTUAL_COMPOSER.md +1 -1
- package/docs/PRODUCT_LIFECYCLE.md +566 -0
- package/docs/THEME_REFINERY.md +2 -2
- package/docs/architecture/AGENTSAM_RUNTIME_PROTOCOL.md +40 -20
- package/docs/content-studio/REVISION_GATE_2026-09-27.md +1 -1
- package/docs/plans/LOCAL_STUDIO_DESKTOP_RELEASE_2026-09-29.md +150 -0
- package/migrations/d1/0017_identity_native_oauth.sql +21 -0
- package/native/agentsam-machine/Cargo.lock +426 -0
- package/native/agentsam-machine/Cargo.toml +9 -0
- package/native/agentsam-machine/cli/Cargo.toml +14 -0
- package/native/agentsam-machine/cli/src/main.rs +77 -0
- package/native/agentsam-machine/core/Cargo.toml +15 -0
- package/native/agentsam-machine/core/src/assets.rs +790 -0
- package/native/agentsam-machine/core/src/bound.rs +298 -0
- package/native/agentsam-machine/core/src/enrich.rs +706 -0
- package/native/agentsam-machine/core/src/frontend.rs +442 -0
- package/native/agentsam-machine/core/src/lib.rs +1086 -0
- package/native/agentsam-machine/core/src/liquid.rs +528 -0
- package/native/agentsam-machine/core/src/source_types.rs +78 -0
- package/package.json +51 -21
- package/packages/agentsam-brand/README.md +1 -1
- package/packages/agentsam-brand/package.json +4 -4
- package/packages/agentsam-brand/src/index.js +1 -1
- package/packages/agentsam-contracts/package.json +13 -3
- package/packages/agentsam-contracts/src/tools.ts +22 -0
- package/packages/agentsam-errors/package.json +13 -3
- package/packages/agentsam-knowledge/package.json +18 -4
- package/packages/agentsam-knowledge/src/autorag/index.js +10 -3
- package/packages/agentsam-knowledge/src/backends/index.js +33 -1
- package/packages/agentsam-knowledge/test/autorag.test.mjs +60 -1
- package/packages/agentsam-nav/package.json +24 -6
- package/packages/agentsam-queue-control/README.md +1 -1
- package/packages/agentsam-queue-control/package.json +7 -2
- package/packages/agentsam-rapid-rust/src/main.rs +1 -1
- package/packages/agentsam-repository/package.json +13 -3
- package/packages/agentsam-repository/src/source-types.js +8 -0
- package/packages/agentsam-vault/package.json +14 -4
- package/packages/agentsam-workbench/package.json +15 -4
- package/packages/agentsam-workbench/src/agent/ToolPermissionRequest.tsx +94 -0
- package/packages/agentsam-workbench/src/agent/index.ts +2 -0
- package/packages/agentsam-workbench/src/agent/tool-permission.css +134 -0
- package/packages/connectors/cloudflare/package.json +13 -3
- package/packages/connectors/cloudflare/src/api-client.js +3 -2
- package/packages/connectors/cloudflare/src/families/vectorize.js +127 -0
- package/packages/connectors/cloudflare/src/index.js +1 -0
- package/packages/heuristic-theme/README.md +2 -2
- package/packages/heuristic-theme/package.json +8 -3
- package/packages/heuristic-theme/src/registry.js +2 -2
- package/packages/heuristic-theme/src/theme.js +1 -1
- package/packages/heuristic-theme/test/theme.test.mjs +1 -1
- package/packages/identity/.agentsam/features/oauth-login-portal/agentsam.feature.json +1 -1
- package/packages/identity/.agentsam/features/oauth-login-portal/providers.json +27 -7
- package/packages/identity/README.md +2 -2
- package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +18 -15
- package/packages/identity/migrations/apply-portable.js +109 -0
- package/packages/identity/migrations/sqlite/004_identity_oauth_consent_catalog.sql +1 -1
- package/packages/identity/migrations/sqlite/005_identity_company_native.sql +52 -0
- package/packages/identity/package.json +27 -6
- package/packages/identity/schema/agentsam.identity/manifest.json +101 -0
- package/packages/identity/scripts/local-identity-bridge.mjs +13 -7
- package/packages/identity/scripts/preview-auth-portal.mjs +6 -6
- package/packages/identity/src/adapters/cloudflare-d1/index.js +8 -401
- package/packages/identity/src/adapters/iam-compat/index.js +540 -0
- package/packages/identity/src/adapters/portable-d1/index.js +18 -0
- package/packages/identity/src/adapters/portable-store.js +479 -0
- package/packages/identity/src/adapters/sqlite/index.js +13 -312
- package/packages/identity/src/contracts/auth-config.js +0 -1
- package/packages/identity/src/contracts/identity-store.js +56 -5
- package/packages/identity/src/contracts/provider.js +1 -0
- package/packages/identity/src/contracts/sign-in-options.js +104 -0
- package/packages/identity/src/core/constants.js +1 -1
- package/packages/identity/src/core/session-policy.js +31 -0
- package/packages/identity/src/frontend/auth-portal/pages/login.html +6 -6
- package/packages/identity/src/frontend/auth-portal/pages/reset.html +5 -5
- package/packages/identity/src/frontend/auth-portal/pages/signup.html +5 -5
- package/packages/identity/src/frontend/auth-portal/shared/company-branding.js +1 -1
- package/packages/identity/src/frontend/auth-portal/shared/desktop-identity-bridge.js +6 -37
- package/packages/identity/src/index.js +28 -1
- package/packages/identity/src/migrations/README.md +23 -23
- package/packages/identity/src/oauth/README.md +1 -1
- package/packages/identity/src/oauth/credentials.js +10 -11
- package/packages/identity/src/oauth/google-desktop-exchange.js +195 -27
- package/packages/identity/src/oauth/iam-platform.js +21 -9
- package/packages/identity/src/oauth/native-handoff.js +136 -0
- package/packages/identity/src/providers/chatgpt/headers.js +65 -0
- package/packages/identity/src/providers/chatgpt/index.js +86 -0
- package/packages/identity/src/providers/chatgpt/mapper.js +43 -0
- package/packages/identity/src/providers/chatgpt/paths.js +45 -0
- package/packages/identity/src/providers/github/oauth.js +1 -2
- package/packages/identity/src/providers/github/profile.js +16 -2
- package/packages/identity/src/providers/index.js +11 -3
- package/packages/identity/src/server/identity-service.js +2 -1
- package/packages/identity/src/server/worker-router.js +71 -18
- package/packages/identity/tests/chatgpt-provider.test.mjs +75 -0
- package/packages/identity/tests/google-desktop-identity-login.test.mjs +210 -0
- package/packages/identity/tests/identity-init-scaffold.test.mjs +15 -4
- package/packages/identity/tests/lane1-identity-store-parity.test.mjs +527 -0
- package/packages/identity/tests/lane1-packed-consumer.test.mjs +175 -0
- package/packages/identity/tests/native-oauth-handoff.test.mjs +292 -0
- package/packages/identity/tests/oauth-credentials.test.mjs +4 -4
- package/packages/identity/tests/preview-auth-portal.test.mjs +4 -2
- package/packages/identity/tests/session-routes-policy.test.mjs +13 -1
- package/packages/identity/tests/worker-runtime-boundary.test.mjs +11 -0
- package/packages/providers/completeful/package.json +7 -2
- package/packages/theme-church-site/package.json +17 -6
- package/packages/theme-church-site/src/harvest.json +4 -2
- package/packages/theme-church-site/src/index.js +7 -3
- package/packages/theme-church-site/test/theme.test.mjs +4 -2
- package/packages/theme-companions-site/package.json +17 -6
- package/packages/theme-companions-site/src/harvest.json +4 -2
- package/packages/theme-companions-site/src/index.js +7 -3
- package/packages/theme-companions-site/test/theme.test.mjs +4 -2
- package/packages/theme-floors-site/package.json +17 -6
- package/packages/theme-floors-site/src/harvest.json +4 -2
- package/packages/theme-floors-site/src/index.js +7 -3
- package/packages/theme-floors-site/test/theme.test.mjs +4 -2
- package/packages/theme-fuelnfree-site/package.json +17 -6
- package/packages/theme-fuelnfree-site/src/harvest.json +4 -2
- package/packages/theme-fuelnfree-site/src/index.js +7 -3
- package/packages/theme-fuelnfree-site/test/theme.test.mjs +4 -2
- package/packages/theme-handyman-site/package.json +17 -6
- package/packages/theme-handyman-site/src/harvest.json +4 -2
- package/packages/theme-handyman-site/src/index.js +7 -3
- package/packages/theme-handyman-site/test/theme.test.mjs +4 -2
- package/packages/theme-insurance-site/package.json +17 -6
- package/packages/theme-insurance-site/src/harvest.json +4 -2
- package/packages/theme-insurance-site/src/index.js +7 -3
- package/packages/theme-insurance-site/test/theme.test.mjs +4 -2
- package/packages/theme-scenes/README.md +1 -1
- package/packages/theme-scenes/package.json +4 -3
- package/packages/theme-scenes/src/registry.js +187 -0
- package/packages/theme-shinshu-site/package.json +17 -6
- package/packages/theme-shinshu-site/src/harvest.json +4 -2
- package/packages/theme-shinshu-site/src/index.js +7 -3
- package/packages/theme-shinshu-site/test/theme.test.mjs +4 -2
- package/packages/work-graph/package.json +14 -4
- package/protocol/FILEMETA_V1.md +2 -2
- package/protocol/capabilities/manifest.json +1 -1
- package/protocol/database/agentsam.schema-pack.v1.schema.json +72 -0
- package/protocol/presets/catalog.json +2 -2
- package/protocol/theme-refinery/lineage-registry.json +105 -0
- package/protocol/theme-refinery/product-metadata.schema.json +21 -1
- package/skills/grok-auth/SKILL.md +110 -0
- package/skills/grok-auth/agentsam.skill.json +25 -0
- package/skills/grok-auth/references/grok-identity.md +64 -0
- package/skills/grok-auth/references/per-user-data.md +49 -0
- package/skills/grok-auth/references/prewired-and-env.md +54 -0
- package/skills/grok-auth/references/session-ui.md +133 -0
- package/skills/grok-auth/references/sign-in-methods.md +55 -0
- package/skills/grok-auth/references/wiring.md +71 -0
- package/skills/grok-building-games/SKILL.md +213 -0
- package/skills/grok-building-games/agentsam.skill.json +25 -0
- package/skills/grok-building-games/references/3d-libs.md +64 -0
- package/skills/grok-building-games/references/ai-pathfinding.md +122 -0
- package/skills/grok-building-games/references/audio.md +129 -0
- package/skills/grok-building-games/references/babylon.md +202 -0
- package/skills/grok-building-games/references/collision-physics.md +122 -0
- package/skills/grok-building-games/references/ecs-architecture.md +111 -0
- package/skills/grok-building-games/references/game-feel-juice.md +110 -0
- package/skills/grok-building-games/references/genres/board-card-chess.md +89 -0
- package/skills/grok-building-games/references/genres/endless-runner.md +83 -0
- package/skills/grok-building-games/references/genres/fps.md +105 -0
- package/skills/grok-building-games/references/genres/platformer-2d.md +97 -0
- package/skills/grok-building-games/references/genres/puzzle-match3-tetris.md +131 -0
- package/skills/grok-building-games/references/genres/racing-kart.md +106 -0
- package/skills/grok-building-games/references/genres/topdown-twin-stick.md +97 -0
- package/skills/grok-building-games/references/genres/tower-defense.md +84 -0
- package/skills/grok-building-games/references/genres/voxel-minecraft.md +89 -0
- package/skills/grok-building-games/references/input.md +139 -0
- package/skills/grok-building-games/references/phaser.md +277 -0
- package/skills/grok-building-games/references/procedural-generation.md +141 -0
- package/skills/grok-building-games/references/save-persistence.md +108 -0
- package/skills/grok-building-games/references/threejs-foundational.md +148 -0
- package/skills/grok-controls/SKILL.md +274 -0
- package/skills/grok-controls/agentsam.skill.json +25 -0
- package/skills/grok-design-ui/SKILL.md +122 -0
- package/skills/grok-design-ui/agentsam.skill.json +25 -0
- package/skills/grok-design-ui/references/animations.md +379 -0
- package/skills/grok-design-ui/references/performance.md +88 -0
- package/skills/grok-design-ui/references/refined-ui.md +384 -0
- package/skills/grok-design-ui/references/surfaces.md +247 -0
- package/skills/grok-design-ui/references/typography.md +123 -0
- package/skills/grok-game-animation-frames/SKILL.md +84 -0
- package/skills/grok-game-animation-frames/agentsam.skill.json +25 -0
- package/skills/grok-game-asset-core/SKILL.md +69 -0
- package/skills/grok-game-asset-core/agentsam.skill.json +25 -0
- package/skills/grok-game-character-consistency/SKILL.md +69 -0
- package/skills/grok-game-character-consistency/agentsam.skill.json +25 -0
- package/skills/grok-game-tilesets/SKILL.md +65 -0
- package/skills/grok-game-tilesets/agentsam.skill.json +25 -0
- package/skills/grok-game-ui-icons/SKILL.md +56 -0
- package/skills/grok-game-ui-icons/agentsam.skill.json +25 -0
- package/skills/grok-generate2dmap/LICENSE +21 -0
- package/skills/grok-generate2dmap/SKILL.md +120 -0
- package/skills/grok-generate2dmap/SOURCE.md +6 -0
- package/skills/grok-generate2dmap/agentsam.skill.json +25 -0
- package/skills/grok-generate2dmap/references/deliverables.md +101 -0
- package/skills/grok-generate2dmap/references/layered-map-contract.md +209 -0
- package/skills/grok-generate2dmap/references/map-strategies.md +341 -0
- package/skills/grok-generate2dmap/references/object-production-gate.md +24 -0
- package/skills/grok-generate2dmap/references/pipeline.md +149 -0
- package/skills/grok-generate2dmap/references/prop-pack-contract.md +174 -0
- package/skills/grok-generate2dmap/references/side-scroll-stages.md +29 -0
- package/skills/grok-generate2dmap/scripts/compose_layered_preview.py +157 -0
- package/skills/grok-generate2dmap/scripts/extract_prop_pack.py +369 -0
- package/skills/grok-generate2dsprite/LICENSE +21 -0
- package/skills/grok-generate2dsprite/SKILL.md +313 -0
- package/skills/grok-generate2dsprite/SOURCE.md +6 -0
- package/skills/grok-generate2dsprite/agentsam.skill.json +25 -0
- package/skills/grok-generate2dsprite/references/modes.md +124 -0
- package/skills/grok-generate2dsprite/references/prompt-rules.md +315 -0
- package/skills/grok-generate2dsprite/scripts/generate2dsprite.py +1031 -0
- package/skills/grok-generate2dsprite/scripts/make_layout_guide.py +109 -0
- package/skills/grok-imagine/SKILL.md +201 -0
- package/skills/grok-imagine/agentsam.skill.json +25 -0
- package/skills/grok-multiplayer-p2p/SKILL.md +111 -0
- package/skills/grok-multiplayer-p2p/agentsam.skill.json +25 -0
- package/skills/grok-multiplayer-p2p/references/react-binding.md +144 -0
- package/skills/grok-multiplayer-p2p/references/signaling-relay.md +269 -0
- package/skills/grok-neon/SKILL.md +157 -0
- package/skills/grok-neon/agentsam.skill.json +25 -0
- package/skills/grok-og/SKILL.md +102 -0
- package/skills/grok-og/agentsam.skill.json +25 -0
- package/skills/grok-og/references/brand-pass.md +53 -0
- package/skills/grok-og/references/custom-card.md +107 -0
- package/skills/grok-og/references/favicon-and-icons.md +48 -0
- package/skills/grok-og/references/og-type-contract.md +18 -0
- package/skills/grok-og/references/placeholder-card.md +21 -0
- package/skills/grok-og/references/x-banner.md +41 -0
- package/skills/grok-threejs/SKILL.md +67 -0
- package/skills/grok-threejs/agentsam.skill.json +25 -0
- package/skills/grok-threejs/references/llms-full.txt +2780 -0
- package/skills/grok-video2dsprite/LICENSE +21 -0
- package/skills/grok-video2dsprite/SKILL.md +236 -0
- package/skills/grok-video2dsprite/SOURCE.md +6 -0
- package/skills/grok-video2dsprite/agentsam.skill.json +25 -0
- package/skills/grok-video2dsprite/references/pipeline.md +90 -0
- package/skills/grok-video2dsprite/references/prompt-rules.md +63 -0
- package/skills/grok-video2dsprite/scripts/video2dsprite.py +490 -0
- package/skills/grok-xai-api/SKILL.md +152 -0
- package/skills/grok-xai-api/agentsam.skill.json +25 -0
- package/src/cli/command-catalog.js +46 -4
- package/src/cli/dispatch.js +1 -0
- package/src/cli.js +10 -0
- package/src/cloudflare/runtime-status.js +2 -1
- package/src/commands/autorag.js +67 -13
- package/src/commands/cheat-sheet.js +29 -4
- package/src/commands/codebaseindex.js +45 -2
- package/src/commands/knowledge.js +59 -2
- package/src/commands/machine-binary.js +103 -0
- package/src/commands/machine.js +137 -0
- package/src/commands/security.js +67 -4
- package/src/commands/setup.js +33 -16
- package/src/commands/status.js +8 -1
- package/src/features/resolve.js +1 -0
- package/src/knowledge/engine.js +21 -2
- package/src/knowledge/runtime-discovery.js +127 -0
- package/src/lib/identity-scaffold.js +53 -13
- package/src/lib/setup/recipes.js +1 -1
- package/src/models/discovery.js +40 -22
- package/src/models/inventory-core.d.ts +105 -0
- package/src/models/inventory-core.js +54 -6
- package/src/security/logs.js +3 -0
- package/src/ui/cli/help.js +41 -0
- package/test/apps-scaffold-contract.test.mjs +3 -2
- package/test/cli/api-key-env-whoami.test.mjs +2 -2
- package/test/cli/catalog-authority.test.mjs +64 -0
- package/test/cli/machine-command.test.mjs +34 -0
- package/test/fixtures/project-authority/customer-app/.agentsam/app.json +5 -0
- package/test/fixtures/project-authority/customer-app/apps/my-product/index.ts +1 -0
- package/test/fixtures/project-authority/customer-app/wrangler.toml +17 -0
- package/test/integration/autorag-project-authority.integration.test.mjs +51 -0
- package/test/integration/autorag-runtime-discovery.test.mjs +107 -0
- package/test/integration/cms-app-scaffold.test.mjs +37 -31
- package/test/integration/cms-site-tenancy-contract.test.mjs +28 -17
- package/test/integration/codebaseindex-ingest.test.mjs +41 -0
- package/test/integration/database-hosted-honesty.test.mjs +49 -0
- package/test/integration/desktop-keychain-boundary.test.mjs +45 -0
- package/test/integration/hosted-work-host-authority.test.mjs +47 -0
- package/test/integration/inventory-eligibility.test.mjs +59 -0
- package/test/integration/local-provider-bridge.test.mjs +65 -0
- package/test/integration/local-studio-settings-production.test.mjs +40 -0
- package/test/integration/lockfile-sync.test.mjs +26 -0
- package/test/integration/provider-env-cli.test.mjs +13 -3
- package/test/integration/runtime-status.integration.test.mjs +16 -1
- package/test/integration/theme-package-registry.test.mjs +31 -0
- package/test/repository-snapshot-view.test.mjs +2 -2
- package/test/security.test.mjs +14 -0
- package/test/terminal-machine-identity.test.mjs +2 -2
- package/apps/client-cms-editor/backend/src/demo-bootstrap.ts +0 -145
- package/packages/agentsam-nav/dist/Nav.d.ts +0 -43
- package/packages/agentsam-nav/dist/NavCollapsible.d.ts +0 -10
- package/packages/agentsam-nav/dist/NavContent.d.ts +0 -2
- package/packages/agentsam-nav/dist/NavFooter.d.ts +0 -2
- package/packages/agentsam-nav/dist/NavGroup.d.ts +0 -3
- package/packages/agentsam-nav/dist/NavHeader.d.ts +0 -2
- package/packages/agentsam-nav/dist/NavMenu.d.ts +0 -22
- package/packages/agentsam-nav/dist/NavProvider.d.ts +0 -35
- package/packages/agentsam-nav/dist/NavTrigger.d.ts +0 -2
- package/packages/agentsam-nav/dist/Surfaces.d.ts +0 -41
- package/packages/agentsam-nav/dist/browser.d.ts +0 -11
- package/packages/agentsam-nav/dist/browser.global.js +0 -132
- package/packages/agentsam-nav/dist/browser.js +0 -613
- package/packages/agentsam-nav/dist/contracts.d.ts +0 -76
- package/packages/agentsam-nav/dist/index.d.ts +0 -11
- package/packages/agentsam-nav/dist/index.js +0 -614
- package/packages/agentsam-nav/dist/legacy.css +0 -83
- package/packages/agentsam-nav/dist/shell.css +0 -113
- package/packages/agentsam-nav/dist/theme.css +0 -113
- package/packages/agentsam-nav/dist/utils.d.ts +0 -1
- package/packages/agentsam-repository/src/goap.js.bak-20260922011251 +0 -670
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Genre Playbook — Grid Puzzle (Match-3 & Tetris)
|
|
2
|
+
|
|
3
|
+
Grid-based puzzlers (Bejeweled/Candy Crush match-3, Tetris) live or die on **a clean grid data model** and **exactly-correct board logic**. Both are 2D — Canvas/Phaser/DOM all work; the board is data, the rendering is a thin view. Read `../threejs-foundational.md` first (delta time, pooling). This file gives the precise algorithms, including the full **SRS wall-kick tables** (verbatim from the Tetris wiki).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 0. The golden rule: separate model from view
|
|
8
|
+
|
|
9
|
+
**The board is a 2D array of ints/enums; rendering reads from it.** Never store game state in sprite positions or the DOM. All logic (matches, gravity, rotation, collision) runs on the array; then you sync visuals (tween pieces to their cell). This prevents the entire class of "the animation and the logic disagree" bugs.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Part A — Match-3 (Bejeweled / Candy Crush)
|
|
14
|
+
|
|
15
|
+
## A1. Core mechanics & minimal scope
|
|
16
|
+
1. A **grid** (e.g. 8×8) of colored gems (`grid[row][col] = colorId`).
|
|
17
|
+
2. **Swap two adjacent gems** (click-click or drag); the swap is only legal if it creates a match.
|
|
18
|
+
3. **Match detection** (3+ in a row/column) → clear.
|
|
19
|
+
4. **Gravity** (gems above fall into gaps) + **refill** (new gems drop from the top).
|
|
20
|
+
5. **Cascades** (chain reactions) scored with a multiplier, and a score/moves HUD.
|
|
21
|
+
|
|
22
|
+
That's a complete match-3. Add special gems, objectives, and levels later.
|
|
23
|
+
|
|
24
|
+
## A2. Match detection
|
|
25
|
+
- **Scan rows and columns for runs of ≥3 identical colors.** The simplest robust method: for each cell, count consecutive same-color horizontally and vertically; mark any run of length ≥3. Collect all marked cells into a set (so an L/T shape counts once).
|
|
26
|
+
- **Flood fill** is the right tool when matches aren't strictly lines (e.g. same-color blobs, or Puyo Puyo–style groups): from each unvisited cell, BFS/DFS to all 4-connected same-color neighbors; if the connected group size ≥ threshold, it's a match. Use flood fill for group-clear variants and for detecting connected clusters after cascades.
|
|
27
|
+
- **Swap validation:** perform the swap in the array, run match detection; if no match results, **swap back** (and animate the reversal). Only commit swaps that match.
|
|
28
|
+
- **Initial board must have no pre-existing matches** and should have at least one valid move — generate, then re-roll any accidental matches; optionally verify a move exists (shuffle if deadlocked).
|
|
29
|
+
|
|
30
|
+
## A3. Gravity, refill & cascades
|
|
31
|
+
- **Clear** matched cells (set to empty), award score.
|
|
32
|
+
- **Gravity:** for each column, compact non-empty cells downward (iterate from the bottom, pull the next non-empty cell down). Do this on the array first.
|
|
33
|
+
- **Refill:** fill the now-empty top cells with new random gems.
|
|
34
|
+
- **Cascade loop:** after gravity+refill, **run match detection again**; if new matches formed, clear/score them (with an increasing chain multiplier) and repeat until stable. This loop is the satisfying core — don't stop after one pass.
|
|
35
|
+
- **Animate after resolving:** compute the whole settled state, then tween gems to their new cells (falling animation). Lock input while the board is resolving.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
# Part B — Tetris
|
|
40
|
+
|
|
41
|
+
## B1. Core mechanics & minimal scope
|
|
42
|
+
1. A **playfield** (standard 10 wide × 20 visible, plus hidden rows above for spawning).
|
|
43
|
+
2. **7 tetrominoes** (I, O, T, S, Z, J, L) each with 4 rotation states.
|
|
44
|
+
3. **Gravity** (piece falls on a timer), **soft/hard drop**, **move left/right**, **rotate CW/CCW**.
|
|
45
|
+
4. **Line clears** (full rows removed, rows above shift down) + scoring.
|
|
46
|
+
5. **Spawn next piece; game over** when a new piece can't spawn.
|
|
47
|
+
|
|
48
|
+
Guideline-quality Tetris additionally needs: **7-bag randomizer**, **SRS rotation + wall kicks**, **lock delay**, ghost piece, hold, and a next-queue. Do these — they're what players expect.
|
|
49
|
+
|
|
50
|
+
## B2. Data model & collision
|
|
51
|
+
- Represent each piece as a set of 4 cell offsets for its current rotation state, plus a board position `(x, y)`. The board is `grid[row][col]`.
|
|
52
|
+
- **Collision test:** a move/rotation is valid iff every one of the piece's 4 cells is in-bounds and lands on an empty board cell. Check *before* committing any move.
|
|
53
|
+
- **Move/rotate = test the target; if valid, apply; else reject** (rotation additionally tries wall kicks, below).
|
|
54
|
+
- **Line clear:** find full rows, remove them, shift everything above down, and clear the freed top rows. Award by lines cleared at once (1=Single … 4=Tetris) — Tetris (4) scores far more, incentivizing well-building.
|
|
55
|
+
|
|
56
|
+
## B3. Randomizer, gravity, lock delay
|
|
57
|
+
- **7-bag randomizer (mandatory for modern feel):** shuffle a bag of all 7 pieces, deal them out, refill/reshuffle when empty. Guarantees no long droughts and no floods of one piece. Pure random feels bad.
|
|
58
|
+
- **Gravity:** drop one row every `fallInterval` (decreasing with level). **Soft drop** = faster fall; **hard drop** = instantly place at the lowest valid position (+ small score per cell).
|
|
59
|
+
- **Lock delay (~0.5s):** when a piece lands (can't fall further), don't lock it immediately — give a short window during which moving/rotating keeps it alive. Standard is a **move/rotation reset limited to ~15 resets** (so you can't stall forever). Without lock delay the game feels harsh; with an unlimited reset you can stall infinitely — cap the resets.
|
|
60
|
+
- **DAS/ARR:** delayed auto-shift (a pause before a held direction auto-repeats) + auto-repeat rate. Tune these — they define movement feel for skilled play.
|
|
61
|
+
|
|
62
|
+
## B4. SRS rotation & wall kicks (verbatim tables)
|
|
63
|
+
|
|
64
|
+
**Rotation states:** `0` = spawn, `R` = one CW from spawn, `L` = one CCW from spawn, `2` = 180°.
|
|
65
|
+
When a rotation is attempted, test **5 offsets in order**; use the first that fits; if none fit, the rotation fails entirely.
|
|
66
|
+
|
|
67
|
+
**⚠️ Coordinate convention:** these tables use **x = right positive, y = UP positive**. If your grid's row index increases *downward* (the usual case), **negate the y value** when applying kicks (a `+2` up becomes `row − 2`). Getting this sign wrong is the #1 SRS bug.
|
|
68
|
+
|
|
69
|
+
**J, L, S, T, Z kick data** (all share one table):
|
|
70
|
+
```
|
|
71
|
+
0->R: (0,0) (-1,0) (-1,+1) (0,-2) (-1,-2)
|
|
72
|
+
R->0: (0,0) (+1,0) (+1,-1) (0,+2) (+1,+2)
|
|
73
|
+
R->2: (0,0) (+1,0) (+1,-1) (0,+2) (+1,+2)
|
|
74
|
+
2->R: (0,0) (-1,0) (-1,+1) (0,-2) (-1,-2)
|
|
75
|
+
2->L: (0,0) (+1,0) (+1,+1) (0,-2) (+1,-2)
|
|
76
|
+
L->2: (0,0) (-1,0) (-1,-1) (0,+2) (-1,+2)
|
|
77
|
+
L->0: (0,0) (-1,0) (-1,-1) (0,+2) (-1,+2)
|
|
78
|
+
0->L: (0,0) (+1,0) (+1,+1) (0,-2) (+1,-2)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**I piece kick data** (its own table):
|
|
82
|
+
```
|
|
83
|
+
0->R: (0,0) (-2,0) (+1,0) (-2,-1) (+1,+2)
|
|
84
|
+
R->0: (0,0) (+2,0) (-1,0) (+2,+1) (-1,-2)
|
|
85
|
+
R->2: (0,0) (-1,0) (+2,0) (-1,+2) (+2,-1)
|
|
86
|
+
2->R: (0,0) (+1,0) (-2,0) (+1,-2) (-2,+1)
|
|
87
|
+
2->L: (0,0) (+2,0) (-1,0) (+2,+1) (-1,-2)
|
|
88
|
+
L->2: (0,0) (-2,0) (+1,0) (-2,-1) (+1,+2)
|
|
89
|
+
L->0: (0,0) (+1,0) (-2,0) (+1,-2) (-2,+1)
|
|
90
|
+
0->L: (0,0) (-1,0) (+2,0) (-1,+2) (+2,-1)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**O piece does not kick** (it never needs to — its rotation is trivial; only its rotation center appears to move).
|
|
94
|
+
|
|
95
|
+
**Algorithm:** to rotate, compute the piece cells in the target state (pure rotation about the piece center), then for each of the 5 `(dx, dy)` offsets for that specific `from->to` transition, test the piece translated by `(dx, -dy)` (if y is down); apply the first that fits. If all 5 fail, cancel. This is what enables T-spins and squeezing the I-piece into tight wells.
|
|
96
|
+
|
|
97
|
+
## B5. Match-3 & Tetris common bugs (checklist)
|
|
98
|
+
- **State stored in sprites/DOM instead of an array** → logic/animation desync. Model is the array.
|
|
99
|
+
- **(Match-3) Not swapping back on a non-matching swap** → illegal moves stick.
|
|
100
|
+
- **(Match-3) Cascade loop stops after one pass** → miss chain reactions; loop until stable.
|
|
101
|
+
- **(Match-3) Initial board has matches or no valid moves** → re-roll on generate; detect deadlock and shuffle.
|
|
102
|
+
- **(Tetris) Pure random piece order** → droughts feel awful; use a 7-bag.
|
|
103
|
+
- **(Tetris) SRS y-sign flipped** → wall kicks push pieces the wrong way; negate y for a downward-row grid.
|
|
104
|
+
- **(Tetris) Wrong/omitted kick table** → no T-spins, I-piece won't fit tight spots; use the exact 5-offset tables per transition (I has its own; O doesn't kick).
|
|
105
|
+
- **(Tetris) No lock delay, or unlimited reset** → either too harsh, or you can stall forever; cap resets (~15).
|
|
106
|
+
- **(Tetris) Line clear shifts rows incorrectly** → clear from the model, shift above down, clear freed top rows; test multi-line clears.
|
|
107
|
+
- **(Tetris) Collision checked after committing** → test the target position first, commit only if valid.
|
|
108
|
+
- **Timing tied to frame rate** → gravity/fall interval must use delta/real time.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Defaults to apply
|
|
113
|
+
|
|
114
|
+
1. **Model = 2D array; view is a thin renderer that tweens to cells.** Run all logic on the array, then animate. Lock input while resolving.
|
|
115
|
+
2. **Match-3: swap → detect → (if no match) swap back; clear → gravity → refill → re-detect in a cascade loop until stable.** Use line-scan for line matches and **flood fill** for connected-group/blob matches. Generate boards with no initial matches and at least one move.
|
|
116
|
+
3. **Tetris: implement the full guideline — 7-bag randomizer, SRS with the exact wall-kick tables above, lock delay with capped resets, hard/soft drop, ghost piece, hold, next queue.** Players expect all of it.
|
|
117
|
+
4. **SRS: mind the y-sign** (tables are y-up; negate for row-down grids). I-piece uses its own kick table; O doesn't kick.
|
|
118
|
+
5. **Always test a move/rotation against the model before committing; reject if any cell is out of bounds or occupied.**
|
|
119
|
+
6. **Both genres are timer-driven** — use delta/real time for fall speed and animations, never per-frame.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Sources
|
|
124
|
+
- Hard Drop Tetris Wiki — SRS (spawn, rotation, and the verbatim wall-kick tables above): https://harddrop.com/wiki/SRS
|
|
125
|
+
- Hard Drop Tetris Wiki — Wall kick: https://harddrop.com/wiki/Wall_kick
|
|
126
|
+
- Hard Drop Tetris Wiki — Lock delay: https://harddrop.com/wiki/Lock_delay
|
|
127
|
+
- Hard Drop Tetris Wiki — Random Generator (7-bag): https://harddrop.com/wiki/Random_Generator
|
|
128
|
+
- Tetris Guideline (official standard): https://tetris.wiki/Tetris_Guideline
|
|
129
|
+
- "Tetris" implementation guide (javidx9 / general): https://tetris.wiki/Tetris_(NES,_Nintendo)
|
|
130
|
+
- Wikipedia — Flood fill (BFS/DFS): https://en.wikipedia.org/wiki/Flood_fill
|
|
131
|
+
- Bejeweled/Candy Crush match-3 algorithm write-ups (match detection + cascade): https://www.emanueleferonato.com/2018/07/13/build-a-html5-match-3-game-using-phaser/
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Genre Playbook — Arcade Racing / Kart
|
|
2
|
+
|
|
3
|
+
Arcade racing (Mario Kart, not a sim) is about **forgiving, exciting handling**, satisfying **drift**, and correct **lap/checkpoint** logic. Default engine: **Three.js/Babylon.js** (3D) with a simple arcade car model — do **not** reach for a full rigid-body vehicle sim for a demo. Read `../threejs-foundational.md` first (delta time, follow camera, forward-axis convention, disposal).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Core mechanics (minimal-but-good scope for a demo)
|
|
8
|
+
|
|
9
|
+
1. **Arcade car handling** — accelerate, brake/reverse, steer; grippy but slidey (see §2).
|
|
10
|
+
2. **Drift** with a boost payoff (the fun core of kart racers).
|
|
11
|
+
3. **A looping track** with walls/boundaries and ground collision.
|
|
12
|
+
4. **Checkpoints + lap counting** that can't be cheated by cutting the course.
|
|
13
|
+
5. **A follow (chase) camera** and a HUD (speed, lap X/N, lap time).
|
|
14
|
+
|
|
15
|
+
One car, one track, 3 laps, a lap timer, and drift-boost is a complete game. Add opponents (even simple waypoint-followers), items, and multiple tracks later. **Handling feel + drift are the whole genre — tune them first.**
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 2. Arcade handling (pseudo-physics, not a sim)
|
|
20
|
+
|
|
21
|
+
Model the car as a point/box with a **heading (yaw)**, a **forward speed**, and a small amount of lateral slide. Avoid full tire-slip simulation.
|
|
22
|
+
|
|
23
|
+
- **Acceleration:** `speed += throttle * accel * delta`, clamp to `maxSpeed`. Reverse/brake applies negative accel with a lower cap.
|
|
24
|
+
- **Drag + rolling resistance:** each frame `speed *= (1 - drag*delta)` (and stronger when off throttle) so the car coasts to a stop. Add higher drag off-track (grass/sand) to punish going wide.
|
|
25
|
+
- **Steering scales with speed, not constant:** turn rate should be low at very low speed (can't turn a parked kart much) and taper at very high speed so it isn't twitchy. A common trick: `turn = steerInput * baseTurn * clamp(speed / someSpeed, 0, 1)`. Reverse the steering sign when moving backward.
|
|
26
|
+
- **Steer sign (must not invert):** full rules live in the **`controls` skill**
|
|
27
|
+
(`.grok/skills/controls/SKILL.md`) — open it for **any** vehicle, not only
|
|
28
|
+
karts. Summary: while `speed > 0` and the chase camera is behind the car,
|
|
29
|
+
**A / ← turns left**, **D / → turns right**. With
|
|
30
|
+
`forward = (-sin(yaw), 0, -cos(yaw))`, **KeyA must yield +yaw**
|
|
31
|
+
(`steer = +1` on A, then `yaw += steer * turnRate * …`). The classic bug is
|
|
32
|
+
`KeyA → steer = -1` with `yaw += steer * +rate` (A turns right). Run the
|
|
33
|
+
`controls` self-test before shipping; do **not** use FPS strafe as a steer test.
|
|
34
|
+
- **Apply yaw, then move along heading:** rotate the car by `turn * delta`, then translate along its forward vector by `speed * delta`. Keep a little **lateral velocity** that decays (grip) so the car feels weighty rather than on rails.
|
|
35
|
+
- **Grip model (simple):** split velocity into forward and sideways components; kill most of the sideways component each frame (high grip) — reducing how much you kill it is exactly what creates drift.
|
|
36
|
+
- **Keep the car on the ground:** raycast down to the track to set height/normal (handles hills/banking) rather than full suspension. Align the car's up to the surface normal for looks.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 3. Drift (the payoff mechanic)
|
|
41
|
+
|
|
42
|
+
- **Drift = temporarily reduce lateral grip** (let more sideways velocity survive) while the player holds a drift/handbrake button and steers, so the car slides through the corner with the nose pointing inward.
|
|
43
|
+
- **Hop-then-drift (kart style):** a small hop initiates the drift; holding it while turning builds a **drift charge** over time.
|
|
44
|
+
- **Mini-turbo / boost payoff:** the longer/tighter the drift, the bigger the speed boost on release (stage it: blue → orange sparks). This risk/reward loop *is* kart racing.
|
|
45
|
+
- **Visual/audio feedback:** tire-skid marks (decals), drift particles/sparks that change color with charge, tire-screech sound, and a slight camera FOV kick on boost. Feedback sells the drift.
|
|
46
|
+
- **Countersteer feel:** while drifting, let the player modulate the slide angle with steering; snap back to grip smoothly on release (don't instantly zero the lateral velocity — lerp it).
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 4. Checkpoints & laps (get this right or laps break)
|
|
51
|
+
|
|
52
|
+
- **Place ordered checkpoints around the track** (invisible trigger volumes/gates), including a start/finish line. Store the count `N`.
|
|
53
|
+
- **Require sequential passing:** track `nextCheckpoint`. A checkpoint only counts if it's the expected next one; passing them out of order (or driving backward) does nothing. This **prevents lap-skipping / reverse-cheesing** — the classic bug where crossing the finish line repeatedly racks up laps.
|
|
54
|
+
- **Count a lap** only when the player crosses the finish line *after* hitting all checkpoints for that lap; then reset `nextCheckpoint` to 0.
|
|
55
|
+
- **Detect crossing with trigger overlap** (AABB/sphere against the car), and for fast cars use a **swept/segment test** (did the car's path this frame cross the gate plane?) so you don't tunnel through a thin checkpoint at high speed.
|
|
56
|
+
- **Respawn / rescue:** if the car flips, leaves the track, or stalls, respawn it at the **last passed checkpoint** facing forward. Also use checkpoints for "wrong way" detection.
|
|
57
|
+
- **HUD:** current lap / total, current + best lap time, position. Freeze the timer at finish.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 5. Camera
|
|
62
|
+
|
|
63
|
+
- **Chase camera behind & slightly above the car**, following with **lerp/spring** (position and look-at both smoothed) so it lags a touch and swings on turns — this conveys speed. `camera.position.lerp(targetBehindCar, k)`; `camera.lookAt(carPosition + lookAhead)`.
|
|
64
|
+
- **Speed FOV:** widen FOV slightly at high speed / on boost and narrow when slow — a strong, cheap sense of speed.
|
|
65
|
+
- **Don't rigidly parent the camera to the car** or it feels stiff and induces motion sickness; smoothing is essential. Add a tiny bit of positional damping, not rotational snapping.
|
|
66
|
+
- Offer a couple of views (chase / hood) if easy. Add motion lines / ground blur / roadside object density for speed sensation.
|
|
67
|
+
- Mind the forward-axis convention (camera looks down −Z; car "front" should be +Z or handled via `lookAt`).
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## 6. Common bugs to avoid (checklist)
|
|
72
|
+
|
|
73
|
+
- **Lap counter increments on any finish-line crossing** → require all checkpoints in order before counting a lap.
|
|
74
|
+
- **Player skips/cuts the track to cheat laps** → sequential-checkpoint gating + wrong-way detection.
|
|
75
|
+
- **Car tunnels through walls/checkpoints at speed** → swept/segment collision, not just per-frame overlap; consider fixed timestep.
|
|
76
|
+
- **Steering identical at all speeds** → twitchy when fast, unturnable when slow; scale turn rate by speed and flip sign in reverse.
|
|
77
|
+
- **A/D reversed while driving forward** → `steerInput` sign disagrees with the
|
|
78
|
+
`forward`/`yaw` basis; re-check the vehicle self-test (A turns left at speed > 0),
|
|
79
|
+
not the FPS D→+X strafe test.
|
|
80
|
+
- **Car feels on rails or uncontrollably slidey** → tune the grip (how much lateral velocity you kill per frame); drift = temporarily reduce that.
|
|
81
|
+
- **Camera stiff / nausea-inducing** → smooth (lerp/spring) both position and look-at; don't hard-parent.
|
|
82
|
+
- **Movement/steer not delta-scaled** → frame-rate dependent handling.
|
|
83
|
+
- **Car floats above/sinks into hills** → raycast to ground for height + surface normal each frame.
|
|
84
|
+
- **No off-track penalty** → add drag/slowdown on grass so cutting corners costs speed.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Defaults to apply
|
|
89
|
+
|
|
90
|
+
1. **Use arcade pseudo-physics, not a rigid-body sim:** heading + forward speed + decaying lateral velocity; drag for coasting; steering that scales with speed. Grippy-but-slidey.
|
|
91
|
+
2. **Ship drift with a boost payoff** (reduce lateral grip while held + charge → mini-turbo on release, with sparks/skid feedback). This is the genre's hook.
|
|
92
|
+
3. **Lap logic MUST use ordered checkpoints:** a lap counts only after all checkpoints are passed in sequence, then the finish line. Prevents skip/reverse cheating. Respawn at last checkpoint.
|
|
93
|
+
4. **Use swept collision for walls and checkpoint gates** so fast cars don't tunnel.
|
|
94
|
+
5. **Chase camera with smoothing + speed-based FOV** for the sense of speed; never hard-parent.
|
|
95
|
+
6. **Minimal scope:** one car, one looping track with checkpoints/laps/timer, drift-boost, HUD. Opponents/items come later.
|
|
96
|
+
7. **Steer self-test before done:** `speed > 0`, hold A → turns left; hold D → turns right (chase cam). Fail = not done.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Sources
|
|
101
|
+
- "How to make an arcade car / kart handling model" (community write-ups, e.g. Kenney/CodinGame arcade car): https://github.com/spacejack/carphysics2d and demo https://spacejack.github.io/carphysics2d/
|
|
102
|
+
- Marco Monster — "Car Physics for Games" (classic arcade/sim reference): https://asawicki.info/Mirror/Car%20Physics%20for%20Games/Car%20Physics%20for%20Games.html
|
|
103
|
+
- Three.js — chase/follow camera & `Object3D.lookAt`: https://threejs.org/docs/#api/en/core/Object3D.lookAt
|
|
104
|
+
- Three.js — `Raycaster` (ground/height sampling): https://threejs.org/docs/#api/en/core/Raycaster
|
|
105
|
+
- Gaffer On Games — Fix Your Timestep (stable vehicle integration / no tunneling): https://gafferongames.com/post/fix_your_timestep/
|
|
106
|
+
- Red Blob Games — line-segment intersection (checkpoint crossing tests): https://www.redblobgames.com/
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Genre Playbook — Top-Down / Twin-Stick Shooter
|
|
2
|
+
|
|
3
|
+
Top-down action where you **move with one input and aim with another** (mouse+WASD on desktop, two virtual sticks on mobile, or left/right stick on gamepad). Think Enter the Gungeon, Nuclear Throne, Vampire Survivors, .io shooters. Default engine: **Phaser** (2D) or Three.js with an orthographic/top camera. Read `../threejs-foundational.md` first (delta time, pooling, mobile joysticks).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Core mechanics (minimal-but-good scope for a demo)
|
|
8
|
+
|
|
9
|
+
1. **Decoupled move + aim** (the defining feature — see §2).
|
|
10
|
+
2. **A shooting weapon** with pooled bullets and a fire-rate cooldown.
|
|
11
|
+
3. **Enemies that spawn and chase** the player (simple seek/steering), with hit + death.
|
|
12
|
+
4. **Collision:** player↔walls, bullets↔enemies, enemies↔player (damage), plus screen/arena bounds.
|
|
13
|
+
5. **HUD:** health + score/wave; a game-over + restart.
|
|
14
|
+
|
|
15
|
+
A single weapon + one enemy type spawning in waves + juicy hit feedback is already a fun loop (Vampire Survivors shipped on essentially this). Add pickups/upgrades only after the core loop is fun.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 2. Controls & aiming (the twin-stick core)
|
|
20
|
+
|
|
21
|
+
- **Movement is independent of facing.** Move on a normalized vector; aim on a separate vector. This is *the* genre feature — never couple them (that's a tank/first-person control scheme, not twin-stick).
|
|
22
|
+
- **Desktop:** WASD/arrows → move vector; mouse position → aim. Aim angle = `Math.atan2(mouse.y - player.y, mouse.x - player.x)` **in world space** (convert screen→world with the camera scroll/zoom, not raw clientX/Y). Left click = fire.
|
|
23
|
+
- **Gamepad:** left stick = move, right stick = aim/fire (fire when the right stick is deflected past a deadzone). Apply a **radial deadzone** (`if (len < 0.2) zero it`) and optionally re-scale so the edge maps to full speed.
|
|
24
|
+
- **Mobile:** two virtual joysticks (e.g. nipplejs) — left = move, right = aim/fire. Auto-fire while the aim stick is held is friendlier than a separate button.
|
|
25
|
+
- **Normalize the movement vector** before applying speed so diagonal movement isn't ~1.41× faster (the classic "faster on diagonals" bug). `vec.normalize().scale(speed * delta)`.
|
|
26
|
+
- **Rotate the sprite/mesh to the aim angle**, not the move angle. In Phaser remember sprites face "right" (0 rad) by default; offset art accordingly. In Three.js top-down, rotate around the up axis and mind the +Z/−Z forward convention.
|
|
27
|
+
- **Optional auto-aim / aim-assist** (snap to nearest enemy) is great on mobile and for accessibility.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 3. Camera
|
|
32
|
+
|
|
33
|
+
- **Follow the player centered**, ideally with a small deadzone and **look-ahead toward the aim/mouse** (offset the camera partway toward the cursor) so you see more of where you're shooting.
|
|
34
|
+
- **Clamp to level bounds**; for arena games, a fixed camera showing the whole arena is also fine.
|
|
35
|
+
- Keep it smooth (lerp) but not laggy; snap on teleport/respawn.
|
|
36
|
+
- Phaser: `cameras.main.startFollow(player, true, 0.1, 0.1)` + `setBounds` + `setDeadzone`.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 4. Bullets, enemies & performance
|
|
41
|
+
|
|
42
|
+
- **Pool everything.** Twin-stick games spawn hundreds of bullets and enemies. Use object pools (Phaser Groups with `maxSize`, or a preallocated array) — never create/destroy per shot. Recycle by toggling `active/visible`.
|
|
43
|
+
- **Bullets:** move by velocity·delta; despawn on wall hit, enemy hit, or when off-screen/out of range/TTL. Prefer circle-vs-circle overlap for bullet↔enemy (cheap and forgiving).
|
|
44
|
+
- **Enemy steering:** simplest good-enough is **seek** — velocity toward `(player - enemy).normalize() * speed`. Add **separation** (push apart from nearby enemies) so they don't stack into one blob. For walls, either use physics colliders or simple flow-field/grid pathfinding for larger maps.
|
|
45
|
+
- **Broad-phase collision** when counts are high: spatial hash / uniform grid so you only test nearby pairs, not O(n²). Phaser Arcade has a grid/tree internally; hand-rolled Canvas needs its own.
|
|
46
|
+
- **Spawn waves** with a timer + difficulty curve (rate and enemy count rising over time). Spawn off-screen at the arena edge, not on top of the player.
|
|
47
|
+
- **Cap concurrent entities** to protect frame rate; degrade gracefully (fewer particles) on mobile.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 5. Genre-specific "feel" (the juice)
|
|
52
|
+
|
|
53
|
+
- **Screen shake** on shooting and explosions (small, decaying).
|
|
54
|
+
- **Hit flash** (tint enemy white for 1–2 frames) + **knockback** + **hit-stop** (freeze the game for a few ms on a big hit) — hit-stop is a huge, cheap feel win.
|
|
55
|
+
- **Muzzle flash, bullet tracers, and impact particles.**
|
|
56
|
+
- **Enemy death**: pop into particles/gibs + a sound + score popup + occasional slow-mo on a big kill.
|
|
57
|
+
- **Weapon feel:** spread/recoil for shotguns, fast tiny bullets for SMGs; controller rumble if available.
|
|
58
|
+
- **Readable bullets:** player bullets and enemy bullets must be visually distinct (color/size) so the player can dodge — critical in bullet-hell density.
|
|
59
|
+
- **Sound** for fire, hit, death, pickup; unlock audio on first gesture.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## 6. Common bugs to avoid (checklist)
|
|
64
|
+
|
|
65
|
+
- **Faster movement on diagonals** → normalize the move vector before scaling by speed.
|
|
66
|
+
- **Coupling aim to movement** → they must be independent (that's the whole genre).
|
|
67
|
+
- **Aiming off by camera offset/zoom** → convert screen coords to world coords using the camera; don't use raw clientX/Y.
|
|
68
|
+
- **Sprite faces wrong direction** → account for the engine's default facing (Phaser sprites face +X/0 rad) and 3D forward-axis convention.
|
|
69
|
+
- **No radial deadzone on gamepad** → stick drift makes the player spin/creep.
|
|
70
|
+
- **Creating/destroying bullets & enemies each frame** → GC stutter; pool them.
|
|
71
|
+
- **O(n²) collision with many entities** → use a spatial grid/hash for broad-phase.
|
|
72
|
+
- **Enemies stacking into one sprite** → add separation steering.
|
|
73
|
+
- **Enemies spawning on top of the player** → spawn at arena edges/off-screen.
|
|
74
|
+
- **Bullets living forever** → give them a TTL/range and despawn off-screen.
|
|
75
|
+
- **Movement not delta-scaled** → frame-rate dependent speed.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Defaults to apply
|
|
80
|
+
|
|
81
|
+
1. **Decouple move and aim by default** — WASD/left-stick move + mouse/right-stick aim; auto-fire on mobile. This one choice defines the genre.
|
|
82
|
+
2. **Always normalize the movement vector** so diagonals aren't faster; apply a **radial deadzone** for sticks; convert mouse→world coords for aim angle.
|
|
83
|
+
3. **Pool bullets and enemies; use a spatial grid for collision** when counts get high; cap entities on mobile.
|
|
84
|
+
4. **Enemy AI = seek + separation** (+ simple wave spawner at edges). Good enough to be fun without pathfinding.
|
|
85
|
+
5. **Feel = hit flash + hit-stop + screen shake + score popups + distinct player/enemy bullet colors.** Cheap, huge payoff.
|
|
86
|
+
6. **Minimal scope:** one weapon, one enemy type, wave spawner, health/score HUD, game-over/restart. That's a complete loop.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Sources
|
|
91
|
+
- MDN — 2D collision detection (circle/AABB): https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection
|
|
92
|
+
- Red Blob Games — 2D visibility, grids, pathfinding, and vector math: https://www.redblobgames.com/
|
|
93
|
+
- Steering Behaviors (Reynolds — seek/flee/separation), classic reference: https://www.red3d.com/cwr/steer/
|
|
94
|
+
- Phaser — cameras (follow, deadzone, bounds): https://docs.phaser.io/phaser/concepts/cameras
|
|
95
|
+
- Phaser — Groups & object pooling: https://docs.phaser.io/phaser/concepts/gameobjects/group
|
|
96
|
+
- nipplejs (mobile virtual joysticks): https://github.com/yoannmoinet/nipplejs
|
|
97
|
+
- MDN — Gamepad API (deadzones, axes): https://developer.mozilla.org/en-US/docs/Web/API/Gamepad_API
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Genre Playbook — Tower Defense
|
|
2
|
+
|
|
3
|
+
Place towers on a grid to stop waves of enemies walking a path to your base. The genre is fundamentally about **a grid, pathfinding, targeting, and economy**. 2D (Phaser/Canvas) or 3D top-down (Three.js). Read `../threejs-foundational.md` first (delta time, pooling, top-down camera).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Core mechanics (minimal-but-good scope for a demo)
|
|
8
|
+
|
|
9
|
+
1. **A grid map** with a defined enemy **path** from spawn to the base.
|
|
10
|
+
2. **Enemies that walk the path** in timed **waves**, with HP and speed.
|
|
11
|
+
3. **Tower placement** on buildable cells, costing money.
|
|
12
|
+
4. **Towers that target + shoot** enemies in range (projectile or hitscan), dealing damage.
|
|
13
|
+
5. **Economy + lives:** kills give gold; leaks cost lives; game over at 0 lives. Wave counter + "start next wave" button.
|
|
14
|
+
|
|
15
|
+
One tower type, one enemy type, a fixed path, 5–10 escalating waves, gold, and lives is a complete game. Add tower types/upgrades, enemy variety (fast/armored/flying), and maze-building later. **Fixed-path TD is much simpler and less bug-prone than maze/free-build TD — default to it for demos.**
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 2. Map, path & pathfinding
|
|
20
|
+
|
|
21
|
+
- **Two flavors — pick deliberately:**
|
|
22
|
+
- **Fixed path (recommended default):** the path is authored (a polyline / ordered list of waypoints). Enemies just follow waypoints. No runtime pathfinding, no way to trap enemies — far fewer bugs.
|
|
23
|
+
- **Maze / free-build:** players place towers anywhere and enemies pathfind around them (Bloons-style is fixed; Desktop TD is maze). Requires **A\*** re-pathing and a critical rule: **never allow a placement that fully blocks the path** — validate with a pathfinding check before committing, and reject if no route remains.
|
|
24
|
+
- **Grid model:** a 2D array of cells with types (path / buildable / blocked / spawn / base). Convert world↔grid with `floor(pos / cellSize)`. Snap tower placement to cell centers.
|
|
25
|
+
- **A\* (maze TD):** grid neighbors (4- or 8-connected), Manhattan/octile heuristic. Recompute affected enemies' paths when a tower is placed/sold. Cache the path; only recompute on change. See Red Blob Games' A* guide (canonical).
|
|
26
|
+
- **Waypoint following (fixed path):** each enemy stores its target waypoint index; move toward it by `speed*delta`; when within a small epsilon, advance to the next; reaching the end = a "leak" (lose a life, despawn).
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 3. Towers: targeting, range & firing
|
|
31
|
+
|
|
32
|
+
- **Range check:** distance (squared, to avoid sqrt) from tower to enemy ≤ range². Use a **spatial grid/quadtree** for broad-phase if there are many enemies — don't test every tower against every enemy each frame (O(towers×enemies)).
|
|
33
|
+
- **Targeting policy (make it explicit & selectable):** common options — **First** (furthest along the path, the usual default), **Last**, **Closest**, **Strongest (most HP)**, **Weakest**. "First" is the standard because it stops leaks best. Ambiguous/implicit targeting is a common complaint — pick and document one.
|
|
34
|
+
- **Fire rate:** cooldown timer per tower (`if (now - lastFire >= 1/fireRate) fire()`), delta-based, not per-frame.
|
|
35
|
+
- **Projectiles vs hitscan:** projectiles (pooled) that travel and can **home** on the target or aim at a **lead/predicted position** feel better and enable "miss if enemy dies mid-flight." Hitscan (instant damage + a drawn beam) is simpler and fine for lasers. Pool projectiles.
|
|
36
|
+
- **Damage types & AoE:** splash damage hits enemies within a radius of impact; slow/poison apply timed status effects. Even one splash tower adds a lot of depth.
|
|
37
|
+
- **Rotate the tower/turret to face its target** (mind facing conventions). Show range as a ring on hover/selection.
|
|
38
|
+
- **Upgrades/selling:** click a tower → upgrade (more damage/range/rate) or sell for partial refund.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 4. Waves & economy (the balance core)
|
|
43
|
+
|
|
44
|
+
- **Wave data as configuration**, not hardcoded logic: a list of waves, each a list of `{enemyType, count, spawnInterval, delay}`. Easy to tune and extend.
|
|
45
|
+
- **Escalation:** later waves have more/tougher/faster enemies; introduce armored (reduce non-piercing damage), fast, and flying (only certain towers hit) types over time.
|
|
46
|
+
- **Economy loop:** enemies give gold on death; towers/upgrades cost gold; a leak costs a life. Tune so the player is always a little short — that tension is the game. Give inter-wave prep time and optionally a bonus for starting the next wave early.
|
|
47
|
+
- **Lives + win/lose:** lose a life per leak, game over at 0; win by surviving all waves (or endless mode with scaling).
|
|
48
|
+
- **Boss waves** for pacing spikes.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 5. Common bugs to avoid (checklist)
|
|
53
|
+
|
|
54
|
+
- **(Maze TD) Placement that fully blocks the path** → always run a pathfinding validity check before allowing placement; reject if no route to base remains.
|
|
55
|
+
- **Enemies overshoot/orbit waypoints** → advance when within an epsilon distance and clamp the final step so they don't jitter around the point.
|
|
56
|
+
- **O(towers×enemies) targeting each frame** → use squared-distance checks + a spatial grid/quadtree for broad-phase.
|
|
57
|
+
- **Ambiguous targeting** → choose an explicit policy (default "First"), make it consistent and ideally player-selectable.
|
|
58
|
+
- **Projectiles chasing dead enemies / never expiring** → give projectiles a target ref + TTL; on target death, either retarget, continue to last position, or despawn.
|
|
59
|
+
- **Fire rate frame-rate dependent** → cooldown by delta time, not per frame.
|
|
60
|
+
- **Building on path/occupied cells** → validate cell type + occupancy before placing; snap to grid.
|
|
61
|
+
- **Economy exploits** → full-refund sell + rebuild loops; use partial refunds; validate gold on every transaction.
|
|
62
|
+
- **Not pooling enemies/projectiles** → GC stutter in big waves.
|
|
63
|
+
- **Enemies overlapping into one blob** → optional separation, or just accept single-file on a fixed path.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Defaults to apply
|
|
68
|
+
|
|
69
|
+
1. **Default to fixed-path (waypoint) TD** for demos — no runtime pathfinding, dramatically fewer bugs. Offer maze/A* only when explicitly wanted.
|
|
70
|
+
2. **If maze/free-build: NEVER allow a tower placement that fully blocks the path** — validate with an A* reachability check before committing.
|
|
71
|
+
3. **Grid-based map + snap placement; validate cell buildability + gold before placing.**
|
|
72
|
+
4. **Explicit, selectable targeting policy (default "First"); squared-distance range checks + spatial grid** for performance. Pool projectiles/enemies.
|
|
73
|
+
5. **Wave and enemy stats as data/config, not code** — makes balancing and expansion trivial.
|
|
74
|
+
6. **Tune the economy tight** (gold from kills, cost of towers, lives from leaks) — the shortage-driven tension is the fun. Minimal scope: 1 tower, 1 enemy, fixed path, escalating waves, gold + lives.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Sources
|
|
79
|
+
- Red Blob Games — Introduction to A* / pathfinding (the canonical grid pathfinding reference): https://www.redblobgames.com/pathfinding/a-star/introduction.html
|
|
80
|
+
- Red Blob Games — Grids, hexagons, and tile math: https://www.redblobgames.com/grids/
|
|
81
|
+
- MDN — 2D collision / distance checks: https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection
|
|
82
|
+
- Phaser — Groups & pooling (projectiles/enemies): https://docs.phaser.io/phaser/concepts/gameobjects/group
|
|
83
|
+
- "Tower Defense targeting priorities" (Bloons/Desktop TD community references): https://bloons.fandom.com/wiki/Targeting_Priority
|
|
84
|
+
- Amit Patel / Red Blob — implementation notes on flow fields for many-agent pathing: https://www.redblobgames.com/pathfinding/tower-defense/
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Genre Playbook — Voxel / Minecraft-like
|
|
2
|
+
|
|
3
|
+
Block worlds you can walk, build, and mine. In the browser this is a **Three.js/WebGL performance problem first, game second** — the naive approach (one cube mesh per block) melts instantly. The whole genre is about **chunking, face culling, greedy meshing, and voxel raycasting**. Read `../threejs-foundational.md` first (draw calls, disposal, instancing, first-person controls).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Core mechanics (minimal-but-good scope for a demo)
|
|
8
|
+
|
|
9
|
+
1. **A voxel world** stored as data (block IDs in a 3D grid), rendered as merged chunk meshes.
|
|
10
|
+
2. **First-person movement + collision** against blocks (AABB vs voxels).
|
|
11
|
+
3. **Break and place blocks** via a voxel raycast (crosshair targets a block/face).
|
|
12
|
+
4. **A few block types** with distinct textures (atlas).
|
|
13
|
+
5. **Some world generation** (flat, or simple noise terrain) and chunk streaming around the player.
|
|
14
|
+
|
|
15
|
+
Flat world + walk + place/break + 3–4 block types is already recognizably "Minecraft." Skip inventory depth, lighting/AO, water, and mobs until the core render + edit loop is solid. **If you render each block as its own mesh, nothing else matters — you'll be at single-digit FPS.**
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 2. Chunking (the foundational structure)
|
|
20
|
+
|
|
21
|
+
- **Divide the world into chunks** (commonly 16×16×256, or 16×16×16 sub-chunks). Store each chunk's blocks in a **flat typed array** (`Uint8Array` indexed `x + y*SX + z*SX*SY`), not nested objects — cache-friendly and memory-light.
|
|
22
|
+
- **One merged mesh per chunk** (a single `BufferGeometry` built from all visible faces), not one mesh per block. This is the single most important rule — it turns thousands of draw calls into one per chunk.
|
|
23
|
+
- **Rebuild a chunk's mesh only when its blocks change** (place/break), not every frame. Cache the geometry; dispose the old one on rebuild.
|
|
24
|
+
- **Stream chunks** around the player: load/generate + build meshes for chunks within a radius; unload (and **dispose geometry/material/textures**) chunks that fall out of range. Do meshing off the main thread (**Web Workers**) to avoid frame hitches; transfer the typed arrays.
|
|
25
|
+
- **Neighbor awareness:** meshing a chunk needs to know the blocks in adjacent chunks (to cull faces at chunk borders correctly) — pass neighbor data or a padded copy.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 3. Face culling & greedy meshing (the performance core)
|
|
30
|
+
|
|
31
|
+
- **Face culling first (mandatory):** only emit a block face if the neighboring block in that direction is **empty/transparent**. Interior faces between two solid blocks are never seen — skipping them removes the vast majority of geometry. This alone makes voxel worlds viable.
|
|
32
|
+
- **Greedy meshing (big win):** after culling, **merge adjacent coplanar faces of the same block type into larger quads.** Instead of one quad per block face, a flat 16×16 grass top becomes (ideally) one quad. Algorithm (per 0fps.net "Meshing in a Minecraft Game"): for each of the 6 face directions, sweep the volume slice-by-slice, build a 2D mask of visible faces of each type, then greedily expand rectangles over the mask (grow width, then height while cells match), emitting one quad per merged rectangle. Cuts vertex count and draw work dramatically.
|
|
33
|
+
- **Trade-off:** greedy meshing complicates per-face texturing/UVs and lighting/AO (merged quads span multiple blocks). For a demo, culled per-face meshing is acceptable; add greedy meshing when you need scale. Use a **texture atlas** (or a texture array) so all block textures share one material → one draw call per chunk. Set atlas textures to `NearestFilter` and mind bleeding at atlas tile edges (add padding or use a texture array).
|
|
34
|
+
- **Don't use `InstancedMesh` of cubes for terrain** — it still submits all 6 faces per block and per-face culling/greedy meshing wins massively. Instancing is fine for sparse identical props.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 4. Voxel raycasting: place & break blocks
|
|
39
|
+
|
|
40
|
+
- **Use a grid-DDA voxel traversal (Amanatides & Woo), not `Raycaster.intersectObjects` against block meshes.** Step the ray cell-by-cell through the voxel grid: track `tMax`/`tDelta` per axis, advance to whichever axis boundary is nearest, and check the block at each visited cell until you hit a solid block or reach max distance. This is exact, cheap, and independent of how the mesh is built.
|
|
41
|
+
- **Break:** set the hit cell to empty; rebuild that chunk's mesh (and any neighbor chunk if the block was on a border).
|
|
42
|
+
- **Place:** place the new block in the cell **adjacent to the hit face** — you must track *which face* you crossed to enter the solid cell (the last step axis + direction gives the face normal). Place at `hitCell + faceNormal`. Reject placement if that cell is non-empty or overlaps the player's AABB (don't let the player entomb themselves).
|
|
43
|
+
- **Highlight** the targeted block/face (wireframe or overlay) so the player sees what they'll hit.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 5. Collision, feel & world gen
|
|
48
|
+
|
|
49
|
+
- **Collision = AABB vs voxels:** resolve the player capsule/box against the blocks it overlaps, axis-separated (X, then Y, then Z), like a 3D version of tile collision. Sub-step fast movement to avoid tunneling through thin walls at high speed/low FPS.
|
|
50
|
+
- **First-person feel:** pointer lock, gravity + jump, step-up over 1-block ledges optional; block-break should have a short "mining" delay + crack overlay + particle burst for satisfaction; place/break sounds.
|
|
51
|
+
- **World gen:** simplex/Perlin noise for heightmaps (e.g. `simplex-noise`), layered (base terrain + caves via 3D noise) — keep it cheap and run in the worker with meshing.
|
|
52
|
+
- **Ambient occlusion** (darkening block corners) adds huge visual quality but complicates greedy meshing; add later.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 6. Common bugs to avoid (checklist)
|
|
57
|
+
|
|
58
|
+
- **One mesh per block** → thousands of draw calls, instant death. Merge into one mesh per chunk.
|
|
59
|
+
- **No face culling** → 6× the geometry, most of it hidden. Cull faces against neighbors (including across chunk borders).
|
|
60
|
+
- **Rebuilding chunk meshes every frame** → rebuild only on edit; cache geometry.
|
|
61
|
+
- **Not disposing unloaded chunk geometry/materials/textures** → memory leak/crash while exploring (Three.js doesn't GC GPU resources).
|
|
62
|
+
- **Meshing on the main thread** → frame hitches when chunks stream; use Web Workers + transferable typed arrays.
|
|
63
|
+
- **Chunk-border faces wrong** (missing or double faces at seams) → meshing must see neighbor chunk blocks.
|
|
64
|
+
- **Using `intersectObjects` for block picking** → slow/fragile; use grid-DDA voxel traversal and track the entry face for placement.
|
|
65
|
+
- **Placing blocks on the wrong side / inside the player** → place at hitCell + face normal; reject if occupied or overlapping the player AABB.
|
|
66
|
+
- **Texture atlas bleeding** between tiles → padding or texture arrays, `NearestFilter`.
|
|
67
|
+
- **Collision tunneling at speed** → axis-separated AABB resolution + sub-stepping.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Defaults to apply
|
|
72
|
+
|
|
73
|
+
1. **One merged mesh per chunk, never one mesh per block.** Store blocks in flat typed arrays; chunk the world (e.g. 16³). This is non-negotiable for browser performance.
|
|
74
|
+
2. **Always do face culling** (skip faces adjacent to solid blocks, across chunk borders too). Add **greedy meshing** (0fps.net algorithm) for scale; culled-per-face is OK for a small demo.
|
|
75
|
+
3. **Use a texture atlas / texture array so each chunk is one draw call.**
|
|
76
|
+
4. **Rebuild chunk meshes only on edit; stream and dispose chunks by distance; mesh + generate in Web Workers.**
|
|
77
|
+
5. **Break/place via grid-DDA voxel raycast (Amanatides & Woo), tracking the entered face** so placement goes on the correct adjacent cell; reject placements inside the player or occupied cells.
|
|
78
|
+
6. **Minimal scope:** flat/simple-noise world, FP movement + AABB voxel collision, place/break, a few atlas-textured block types. Get render + edit solid before AO, water, lighting, or mobs.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Sources
|
|
83
|
+
- 0fps.net — "Meshing in a Minecraft Game" (greedy meshing, part 1): https://0fps.net/2012/06/30/meshing-in-a-minecraft-game/
|
|
84
|
+
- 0fps.net — "Meshing in a Minecraft Game" (part 2, texturing/AO trade-offs): https://0fps.net/2012/07/07/meshing-minecraft-part-2/
|
|
85
|
+
- Amanatides & Woo — "A Fast Voxel Traversal Algorithm for Ray Tracing" (grid-DDA block picking): http://www.cse.yorku.ca/~amana/research/grid.pdf
|
|
86
|
+
- Three.js — voxel/Minecraft-style tutorial (chunk geometry, raycast place/break): https://threejs.org/manual/#en/voxel-geometry
|
|
87
|
+
- Three.js — disposing objects (chunk unload): https://threejs.org/manual/#en/cleanup
|
|
88
|
+
- MDN — Web Workers (off-thread meshing/gen): https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
|
|
89
|
+
- "Let's make a voxel engine" community wiki (chunking patterns): https://sites.google.com/site/letsmakeavoxelengine/home
|