@inneranimalmedia/agentsam-sdk 2.6.7 → 2.6.8

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.
Files changed (318) hide show
  1. package/README.md +37 -0
  2. package/docs/REPO_FILE_MAP.txt +132 -0
  3. package/migrations/d1/0018_goap_control_plane_remaster.sql +40 -0
  4. package/migrations/d1/0019_agentsam_agent_run_plan_todo.sql +14 -0
  5. package/migrations/d1/README_PORTABLE_CONTROL_PLANE.md +20 -9
  6. package/migrations/runtime/0002_goap_blackboard_v1.sql +15 -0
  7. package/migrations/runtime/0004_agent_run_plan_linkage.sql +8 -0
  8. package/native/agentsam-machine/cli/Cargo.toml +8 -1
  9. package/native/agentsam-machine/cli/README.md +21 -0
  10. package/native/agentsam-machine/core/Cargo.toml +7 -0
  11. package/native/agentsam-machine/core/README.md +14 -0
  12. package/native/agentsam-machine/core/build.rs +33 -0
  13. package/native/agentsam-machine/core/contracts/source-types.v1.json +353 -0
  14. package/native/agentsam-machine/core/src/lib.rs +6 -0
  15. package/native/agentsam-machine/core/src/source_types.rs +2 -2
  16. package/package.json +16 -6
  17. package/packages/agentsam-errors/package.json +1 -1
  18. package/packages/agentsam-errors/src/index.js +1 -0
  19. package/packages/agentsam-errors/src/tool.js +56 -0
  20. package/packages/agentsam-errors/test/tool.test.mjs +58 -0
  21. package/packages/agentsam-goap/README.md +52 -0
  22. package/packages/agentsam-goap/package.json +37 -0
  23. package/packages/agentsam-goap/src/adapters/d1-sqlite.js +570 -0
  24. package/packages/agentsam-goap/src/adapters/memory.js +199 -0
  25. package/packages/agentsam-goap/src/contracts.js +226 -0
  26. package/packages/agentsam-goap/src/control-plane.js +112 -0
  27. package/packages/agentsam-goap/src/errors.js +157 -0
  28. package/packages/agentsam-goap/src/index.js +5 -0
  29. package/packages/agentsam-goap/src/world.js +202 -0
  30. package/packages/agentsam-goap/test/goap-control-plane.test.mjs +245 -0
  31. package/packages/agentsam-goap/test/world.test.mjs +79 -0
  32. package/packages/agentsam-nav/dist/Nav.d.ts +43 -0
  33. package/packages/agentsam-nav/dist/NavCollapsible.d.ts +10 -0
  34. package/packages/agentsam-nav/dist/NavContent.d.ts +2 -0
  35. package/packages/agentsam-nav/dist/NavFooter.d.ts +2 -0
  36. package/packages/agentsam-nav/dist/NavGroup.d.ts +3 -0
  37. package/packages/agentsam-nav/dist/NavHeader.d.ts +2 -0
  38. package/packages/agentsam-nav/dist/NavMenu.d.ts +22 -0
  39. package/packages/agentsam-nav/dist/NavProvider.d.ts +35 -0
  40. package/packages/agentsam-nav/dist/NavTrigger.d.ts +2 -0
  41. package/packages/agentsam-nav/dist/Surfaces.d.ts +41 -0
  42. package/packages/agentsam-nav/dist/browser.d.ts +11 -0
  43. package/packages/agentsam-nav/dist/browser.global.js +135 -0
  44. package/packages/agentsam-nav/dist/browser.js +7290 -0
  45. package/packages/agentsam-nav/dist/contracts.d.ts +76 -0
  46. package/packages/agentsam-nav/dist/index.d.ts +11 -0
  47. package/packages/agentsam-nav/dist/index.js +7291 -0
  48. package/packages/agentsam-nav/dist/legacy.css +83 -0
  49. package/packages/agentsam-nav/dist/shell.css +113 -0
  50. package/packages/agentsam-nav/dist/theme.css +113 -0
  51. package/packages/agentsam-nav/dist/utils.d.ts +1 -0
  52. package/packages/agentsam-repository/src/goap.js +13 -14
  53. package/packages/agentsam-repository/src/goap.js.bak-20260922011251 +670 -0
  54. package/packages/agentsam-repository/src/tickets.js +15 -22
  55. package/packages/agentsam-repository/test/goap-tickets-workspace-state.test.mjs +19 -8
  56. package/packages/connectors/cloudflare/package.json +3 -1
  57. package/packages/identity/tests/lane1-packed-consumer.test.mjs +1 -1
  58. package/python/agentsam_sdk/repository/intelligence/discovery.py +27 -2
  59. package/python/agentsam_sdk/repository/intelligence/git.py +4 -0
  60. package/python/tests/test_repository_intelligence.py +30 -0
  61. package/src/cli/command-catalog.js +2 -1
  62. package/src/cli.js +10 -1
  63. package/src/commands/goap-world.js +134 -0
  64. package/src/commands/goap.js +11 -4
  65. package/src/commands/machine-binary.js +33 -27
  66. package/src/commands/machine-runtime.js +266 -0
  67. package/src/commands/machine.js +122 -51
  68. package/src/commands/package.js +530 -0
  69. package/src/commands/plan-ledger.js +370 -0
  70. package/src/commands/plan.js +183 -0
  71. package/src/commands/skill.js +78 -17
  72. package/src/knowledge/source.js +1 -1
  73. package/src/lib/slash-commands.js +1 -1
  74. package/src/local/runtime-store.js +24 -2
  75. package/src/local/sqlite.js +17 -0
  76. package/src/sam/operations/package-audit.js +41 -0
  77. package/src/sam/seed.js +2 -0
  78. package/skills/grok-auth/SKILL.md +0 -110
  79. package/skills/grok-auth/agentsam.skill.json +0 -25
  80. package/skills/grok-auth/references/grok-identity.md +0 -64
  81. package/skills/grok-auth/references/per-user-data.md +0 -49
  82. package/skills/grok-auth/references/prewired-and-env.md +0 -54
  83. package/skills/grok-auth/references/session-ui.md +0 -133
  84. package/skills/grok-auth/references/sign-in-methods.md +0 -55
  85. package/skills/grok-auth/references/wiring.md +0 -71
  86. package/skills/grok-building-games/SKILL.md +0 -213
  87. package/skills/grok-building-games/agentsam.skill.json +0 -25
  88. package/skills/grok-building-games/references/3d-libs.md +0 -64
  89. package/skills/grok-building-games/references/ai-pathfinding.md +0 -122
  90. package/skills/grok-building-games/references/audio.md +0 -129
  91. package/skills/grok-building-games/references/babylon.md +0 -202
  92. package/skills/grok-building-games/references/collision-physics.md +0 -122
  93. package/skills/grok-building-games/references/ecs-architecture.md +0 -111
  94. package/skills/grok-building-games/references/game-feel-juice.md +0 -110
  95. package/skills/grok-building-games/references/genres/board-card-chess.md +0 -89
  96. package/skills/grok-building-games/references/genres/endless-runner.md +0 -83
  97. package/skills/grok-building-games/references/genres/fps.md +0 -105
  98. package/skills/grok-building-games/references/genres/platformer-2d.md +0 -97
  99. package/skills/grok-building-games/references/genres/puzzle-match3-tetris.md +0 -131
  100. package/skills/grok-building-games/references/genres/racing-kart.md +0 -106
  101. package/skills/grok-building-games/references/genres/topdown-twin-stick.md +0 -97
  102. package/skills/grok-building-games/references/genres/tower-defense.md +0 -84
  103. package/skills/grok-building-games/references/genres/voxel-minecraft.md +0 -89
  104. package/skills/grok-building-games/references/input.md +0 -139
  105. package/skills/grok-building-games/references/phaser.md +0 -277
  106. package/skills/grok-building-games/references/procedural-generation.md +0 -141
  107. package/skills/grok-building-games/references/save-persistence.md +0 -108
  108. package/skills/grok-building-games/references/threejs-foundational.md +0 -148
  109. package/skills/grok-controls/SKILL.md +0 -274
  110. package/skills/grok-controls/agentsam.skill.json +0 -25
  111. package/skills/grok-design-ui/SKILL.md +0 -122
  112. package/skills/grok-design-ui/agentsam.skill.json +0 -25
  113. package/skills/grok-design-ui/references/animations.md +0 -379
  114. package/skills/grok-design-ui/references/performance.md +0 -88
  115. package/skills/grok-design-ui/references/refined-ui.md +0 -384
  116. package/skills/grok-design-ui/references/surfaces.md +0 -247
  117. package/skills/grok-design-ui/references/typography.md +0 -123
  118. package/skills/grok-game-animation-frames/SKILL.md +0 -84
  119. package/skills/grok-game-animation-frames/agentsam.skill.json +0 -25
  120. package/skills/grok-game-asset-core/SKILL.md +0 -69
  121. package/skills/grok-game-asset-core/agentsam.skill.json +0 -25
  122. package/skills/grok-game-character-consistency/SKILL.md +0 -69
  123. package/skills/grok-game-character-consistency/agentsam.skill.json +0 -25
  124. package/skills/grok-game-tilesets/SKILL.md +0 -65
  125. package/skills/grok-game-tilesets/agentsam.skill.json +0 -25
  126. package/skills/grok-game-ui-icons/SKILL.md +0 -56
  127. package/skills/grok-game-ui-icons/agentsam.skill.json +0 -25
  128. package/skills/grok-generate2dmap/LICENSE +0 -21
  129. package/skills/grok-generate2dmap/SKILL.md +0 -120
  130. package/skills/grok-generate2dmap/SOURCE.md +0 -6
  131. package/skills/grok-generate2dmap/agentsam.skill.json +0 -25
  132. package/skills/grok-generate2dmap/references/deliverables.md +0 -101
  133. package/skills/grok-generate2dmap/references/layered-map-contract.md +0 -209
  134. package/skills/grok-generate2dmap/references/map-strategies.md +0 -341
  135. package/skills/grok-generate2dmap/references/object-production-gate.md +0 -24
  136. package/skills/grok-generate2dmap/references/pipeline.md +0 -149
  137. package/skills/grok-generate2dmap/references/prop-pack-contract.md +0 -174
  138. package/skills/grok-generate2dmap/references/side-scroll-stages.md +0 -29
  139. package/skills/grok-generate2dmap/scripts/compose_layered_preview.py +0 -157
  140. package/skills/grok-generate2dmap/scripts/extract_prop_pack.py +0 -369
  141. package/skills/grok-generate2dsprite/LICENSE +0 -21
  142. package/skills/grok-generate2dsprite/SKILL.md +0 -313
  143. package/skills/grok-generate2dsprite/SOURCE.md +0 -6
  144. package/skills/grok-generate2dsprite/agentsam.skill.json +0 -25
  145. package/skills/grok-generate2dsprite/references/modes.md +0 -124
  146. package/skills/grok-generate2dsprite/references/prompt-rules.md +0 -315
  147. package/skills/grok-generate2dsprite/scripts/generate2dsprite.py +0 -1031
  148. package/skills/grok-generate2dsprite/scripts/make_layout_guide.py +0 -109
  149. package/skills/grok-imagine/SKILL.md +0 -201
  150. package/skills/grok-imagine/agentsam.skill.json +0 -25
  151. package/skills/grok-multiplayer-p2p/SKILL.md +0 -111
  152. package/skills/grok-multiplayer-p2p/agentsam.skill.json +0 -25
  153. package/skills/grok-multiplayer-p2p/references/react-binding.md +0 -144
  154. package/skills/grok-multiplayer-p2p/references/signaling-relay.md +0 -269
  155. package/skills/grok-neon/SKILL.md +0 -157
  156. package/skills/grok-neon/agentsam.skill.json +0 -25
  157. package/skills/grok-og/SKILL.md +0 -102
  158. package/skills/grok-og/agentsam.skill.json +0 -25
  159. package/skills/grok-og/references/brand-pass.md +0 -53
  160. package/skills/grok-og/references/custom-card.md +0 -107
  161. package/skills/grok-og/references/favicon-and-icons.md +0 -48
  162. package/skills/grok-og/references/og-type-contract.md +0 -18
  163. package/skills/grok-og/references/placeholder-card.md +0 -21
  164. package/skills/grok-og/references/x-banner.md +0 -41
  165. package/skills/grok-threejs/SKILL.md +0 -67
  166. package/skills/grok-threejs/agentsam.skill.json +0 -25
  167. package/skills/grok-threejs/references/llms-full.txt +0 -2780
  168. package/skills/grok-video2dsprite/LICENSE +0 -21
  169. package/skills/grok-video2dsprite/SKILL.md +0 -236
  170. package/skills/grok-video2dsprite/SOURCE.md +0 -6
  171. package/skills/grok-video2dsprite/agentsam.skill.json +0 -25
  172. package/skills/grok-video2dsprite/references/pipeline.md +0 -90
  173. package/skills/grok-video2dsprite/references/prompt-rules.md +0 -63
  174. package/skills/grok-video2dsprite/scripts/video2dsprite.py +0 -490
  175. package/skills/grok-xai-api/SKILL.md +0 -152
  176. package/skills/grok-xai-api/agentsam.skill.json +0 -25
  177. package/test/account-session.test.mjs +0 -101
  178. package/test/agent-capabilities.test.mjs +0 -67
  179. package/test/app-authority-context.test.mjs +0 -32
  180. package/test/app-building-skills.test.mjs +0 -61
  181. package/test/apps-scaffold-contract.test.mjs +0 -115
  182. package/test/blender-cad.test.mjs +0 -146
  183. package/test/cad-docker.test.mjs +0 -96
  184. package/test/capabilities.test.mjs +0 -133
  185. package/test/cli/api-key-env-whoami.test.mjs +0 -129
  186. package/test/cli/catalog-authority.test.mjs +0 -64
  187. package/test/cli/codebaseindex-plan-ux.test.mjs +0 -37
  188. package/test/cli/eval-live.test.mjs +0 -219
  189. package/test/cli/go.test.mjs +0 -128
  190. package/test/cli/local-vault-and-provider-setup.test.mjs +0 -268
  191. package/test/cli/machine-command.test.mjs +0 -34
  192. package/test/cli/mcp-client.test.mjs +0 -256
  193. package/test/cli/preferences-runtime.test.mjs +0 -11
  194. package/test/cli/runtime-persist.test.mjs +0 -56
  195. package/test/cli/runtime-ui.test.mjs +0 -141
  196. package/test/cli/rust-command.test.mjs +0 -21
  197. package/test/cli/skill-npm-and-env.test.mjs +0 -52
  198. package/test/cli/status-actions.test.mjs +0 -88
  199. package/test/cli/wireframes-go-registry.test.mjs +0 -139
  200. package/test/cli-preferences.test.mjs +0 -46
  201. package/test/cloudflare-connector.test.mjs +0 -93
  202. package/test/cloudflare-runtime.test.mjs +0 -82
  203. package/test/context.test.mjs +0 -159
  204. package/test/credentials-audit.test.mjs +0 -113
  205. package/test/deploy-health-scan.test.mjs +0 -95
  206. package/test/deploy-receipt.test.mjs +0 -91
  207. package/test/dockerize.test.mjs +0 -93
  208. package/test/error-diagnostics.test.mjs +0 -124
  209. package/test/eval-context.test.mjs +0 -37
  210. package/test/execution-approvals.test.mjs +0 -27
  211. package/test/fixtures/cad/courtyard-house.json +0 -208
  212. package/test/fixtures/knowledge-rpc-worker.mjs +0 -16
  213. package/test/fixtures/project-authority/customer-app/.agentsam/app.json +0 -5
  214. package/test/fixtures/project-authority/customer-app/apps/my-product/index.ts +0 -1
  215. package/test/fixtures/project-authority/customer-app/wrangler.toml +0 -17
  216. package/test/gcloud-auth.test.mjs +0 -111
  217. package/test/go/build-source-identity.test.mjs +0 -31
  218. package/test/go/cloudflare-probe.test.mjs +0 -317
  219. package/test/go/distribution.test.mjs +0 -28
  220. package/test/google-cloud-connection.test.mjs +0 -83
  221. package/test/google-cloud-inventory.test.mjs +0 -64
  222. package/test/indexing-provider.test.mjs +0 -29
  223. package/test/init-options.test.mjs +0 -35
  224. package/test/integration/ai-access-onboarding.test.mjs +0 -47
  225. package/test/integration/app-command.test.mjs +0 -85
  226. package/test/integration/autorag-project-authority.integration.test.mjs +0 -51
  227. package/test/integration/autorag-runtime-discovery.test.mjs +0 -107
  228. package/test/integration/cad-discovery.test.mjs +0 -158
  229. package/test/integration/cad-docker-executor.test.mjs +0 -249
  230. package/test/integration/cad-execution.test.mjs +0 -184
  231. package/test/integration/cad-project-app.test.mjs +0 -31
  232. package/test/integration/cad-project-d1.test.mjs +0 -25
  233. package/test/integration/cad-project-native.test.mjs +0 -24
  234. package/test/integration/cad-project-workflow.test.mjs +0 -9
  235. package/test/integration/cad-project.test.mjs +0 -85
  236. package/test/integration/cli-help.test.mjs +0 -41
  237. package/test/integration/cms-app-scaffold.test.mjs +0 -77
  238. package/test/integration/cms-site-tenancy-contract.test.mjs +0 -268
  239. package/test/integration/codebaseindex-ingest.test.mjs +0 -255
  240. package/test/integration/core-client.integration.test.mjs +0 -55
  241. package/test/integration/database-hosted-honesty.test.mjs +0 -49
  242. package/test/integration/desktop-keychain-boundary.test.mjs +0 -45
  243. package/test/integration/error-runtime-rpc.test.mjs +0 -71
  244. package/test/integration/features-resolve.test.mjs +0 -147
  245. package/test/integration/hosted-work-host-authority.test.mjs +0 -47
  246. package/test/integration/icon-registry.test.mjs +0 -67
  247. package/test/integration/ingest-discover-models.test.mjs +0 -30
  248. package/test/integration/inspect-path-cli.test.mjs +0 -46
  249. package/test/integration/install-script.test.mjs +0 -110
  250. package/test/integration/inventory-core.test.mjs +0 -53
  251. package/test/integration/inventory-eligibility.test.mjs +0 -59
  252. package/test/integration/inventory-evidence.test.mjs +0 -125
  253. package/test/integration/knowledge-rpc.test.mjs +0 -112
  254. package/test/integration/local-fs.test.mjs +0 -113
  255. package/test/integration/local-provider-bridge.test.mjs +0 -65
  256. package/test/integration/local-studio-settings-production.test.mjs +0 -40
  257. package/test/integration/lockfile-sync.test.mjs +0 -26
  258. package/test/integration/merkle-cli.test.mjs +0 -61
  259. package/test/integration/merkle-persistence-identity.test.mjs +0 -48
  260. package/test/integration/plugins-cloudflare.integration.test.mjs +0 -28
  261. package/test/integration/provider-env-cli.test.mjs +0 -60
  262. package/test/integration/provider-factory.test.mjs +0 -197
  263. package/test/integration/repository-company-graph.test.mjs +0 -90
  264. package/test/integration/runtime-migrations.test.mjs +0 -87
  265. package/test/integration/runtime-status.integration.test.mjs +0 -227
  266. package/test/integration/sam-activity-recovery.test.mjs +0 -147
  267. package/test/integration/sam-decision.test.mjs +0 -584
  268. package/test/integration/sam-kernel.test.mjs +0 -99
  269. package/test/integration/sam-planning-astar.test.mjs +0 -279
  270. package/test/integration/scaffold-cloudflare.test.mjs +0 -46
  271. package/test/integration/skill-runtime.test.mjs +0 -240
  272. package/test/integration/storage-architecture.test.mjs +0 -154
  273. package/test/integration/store-discovery.test.mjs +0 -44
  274. package/test/integration/studio-fs-pty-e2e.test.mjs +0 -294
  275. package/test/integration/terminal-exec.integration.test.mjs +0 -86
  276. package/test/integration/theme-package-registry.test.mjs +0 -31
  277. package/test/integration/tool-runtime.test.mjs +0 -124
  278. package/test/integration/tool-schema.test.mjs +0 -59
  279. package/test/jr-dev-skill.test.mjs +0 -26
  280. package/test/knowledge-context-pack.test.mjs +0 -19
  281. package/test/knowledge-postgres.test.mjs +0 -40
  282. package/test/knowledge-service.test.mjs +0 -110
  283. package/test/knowledge.test.mjs +0 -206
  284. package/test/live/terminal-transport.live.test.mjs +0 -24
  285. package/test/local-sessions.test.mjs +0 -57
  286. package/test/local-studio-deploy.test.mjs +0 -83
  287. package/test/loopback-oauth.test.mjs +0 -53
  288. package/test/merkle-render.test.mjs +0 -31
  289. package/test/mini.test.mjs +0 -140
  290. package/test/model-catalog.test.mjs +0 -70
  291. package/test/models.test.mjs +0 -309
  292. package/test/npm10-lock.test.mjs +0 -29
  293. package/test/ollama.test.mjs +0 -137
  294. package/test/open-url.test.mjs +0 -64
  295. package/test/openai-responses.test.mjs +0 -155
  296. package/test/portable-context.test.mjs +0 -94
  297. package/test/project-config.test.mjs +0 -81
  298. package/test/project-rules.test.mjs +0 -44
  299. package/test/provider-credentials.test.mjs +0 -106
  300. package/test/rehydrate.test.mjs +0 -25
  301. package/test/release-hygiene.test.mjs +0 -42
  302. package/test/repository-snapshot-view.test.mjs +0 -112
  303. package/test/responses-runner.test.mjs +0 -465
  304. package/test/runtime-activity.test.mjs +0 -98
  305. package/test/sdk-worker-contract.test.mjs +0 -72
  306. package/test/security.test.mjs +0 -266
  307. package/test/setup-planner.test.mjs +0 -74
  308. package/test/setup-runtime.test.mjs +0 -51
  309. package/test/shell.test.mjs +0 -281
  310. package/test/skills.test.mjs +0 -22
  311. package/test/smoke.mjs +0 -122
  312. package/test/telemetry.test.mjs +0 -79
  313. package/test/terminal/local-pty.mock.test.mjs +0 -153
  314. package/test/terminal-machine-identity.test.mjs +0 -88
  315. package/test/theme-portability.test.mjs +0 -14
  316. package/test/tools-search.test.mjs +0 -73
  317. package/test/unit/website-assets-bindings.test.mjs +0 -60
  318. package/test/whoami-resume.test.mjs +0 -157
@@ -1,202 +0,0 @@
1
- # Babylon.js — Deep Engine Guide (Havok physics, cameras, SceneOptimizer, WebGPU, assets, GUI, freezing)
2
-
3
- Babylon.js is the "batteries-included" 3D engine: built-in physics, inspector, GUI, node materials, camera behaviors, SceneOptimizer, and a first-class WebGPU backend. Use it when you want an integrated engine rather than assembling Three.js + libraries.
4
-
5
- This file assumes the general loop/orientation/perf rules and the short Babylon perf bullets in `threejs-foundational.md` and goes **much deeper** without repeating them.
6
-
7
- ---
8
-
9
- ## 1. Engine setup & the render loop
10
-
11
- ```js
12
- import { Engine, Scene, Vector3 } from "@babylonjs/core";
13
- const engine = new Engine(canvas, true, { preserveDrawingBuffer: false, stencil: true, powerPreference: "high-performance" });
14
- const scene = new Scene(engine);
15
- engine.runRenderLoop(() => scene.render());
16
- window.addEventListener("resize", () => engine.resize());
17
- ```
18
-
19
- - `engine.runRenderLoop` is Babylon's RAF loop; hook game logic into **`scene.onBeforeRenderObservable`** and read delta with **`engine.getDeltaTime()`** (ms) or `scene.getAnimationRatio()` (frame-rate compensation factor). Scale movement by delta as always.
20
- - Use **`scene.onBeforeRenderObservable.add(fn)`** for per-frame logic instead of stuffing everything in the render loop closure — it's observable, disposable, and composable.
21
- - `engine.setHardwareScalingLevel(n)` renders at 1/n resolution (n>1 = lower res, big mobile win; n<1 = supersample).
22
-
23
- ---
24
-
25
- ## 2. WebGPU (real, production-ready — prefer it with fallback)
26
-
27
- Babylon has a mature **`WebGPUEngine`** that dramatically cuts CPU-side draw-call overhead and enables compute shaders.
28
-
29
- ```js
30
- import { WebGPUEngine, Engine } from "@babylonjs/core";
31
- async function createEngine(canvas) {
32
- if (await WebGPUEngine.IsSupportedAsync) {
33
- const e = new WebGPUEngine(canvas, { antialias: true });
34
- await e.initAsync(); // REQUIRED before creating a Scene
35
- return e;
36
- }
37
- return new Engine(canvas, true, { powerPreference: "high-performance" }); // WebGL2 fallback
38
- }
39
- ```
40
-
41
- - `WebGPUEngine.initAsync()` **must be awaited** before you create the scene — a top setup bug.
42
- - **Snapshot rendering** (`engine.snapshotRendering = true`, WebGPU only) records the command stream for a static scene and replays it, slashing CPU cost for scenes whose draw list doesn't change. Set `snapshotRenderingMode` and refresh when the scene structure changes.
43
- - WebGPU supports **compute shaders** (particles, culling, GPU picking) — not available on WebGL.
44
-
45
- ---
46
-
47
- ## 3. Cameras & Camera Behaviors (free polish)
48
-
49
- - **ArcRotateCamera** — orbit/inspection. Set limits and inertia so it feels good: `lowerRadiusLimit`/`upperRadiusLimit`, `lowerBetaLimit`/`upperBetaLimit`, `wheelPrecision`, `panningSensibility`, `inertia`. `camera.attachControl(canvas, true)`.
50
- - **UniversalCamera** — FPS/free camera (WASD + mouse; combines FreeCamera + touch/gamepad). `camera.applyGravity`, `camera.checkCollisions`, `camera.ellipsoid` for simple capsule collision against meshes with `mesh.checkCollisions = true` (built-in, no physics engine needed).
51
- - **FollowCamera** — third-person chase; set `radius`, `heightOffset`, `rotationOffset`, `cameraAcceleration`, `maxCameraSpeed`.
52
- - **Keep `camera.maxZ` as small as practical** and `minZ` as large as practical — improves depth precision, culling, and overdraw.
53
-
54
- **Behaviors** attach polished motion for free (this is a Babylon differentiator):
55
- - **FramingBehavior** — auto-frames a target mesh nicely (`camera.useFramingBehavior = true`).
56
- - **BouncingBehavior** — soft bounce at radius limits.
57
- - **AutoRotationBehavior** — idle turntable spin (great for product/menu scenes).
58
- Enable via `camera.useAutoRotationBehavior = true` etc., then tune the behavior object.
59
-
60
- ---
61
-
62
- ## 4. Physics — Havok (V2 plugin, the current default)
63
-
64
- Havok is the recommended physics engine (WASM, fast, deterministic-ish). Use the **Physics V2** API (`PhysicsAggregate` / `PhysicsBody` / `PhysicsShape`).
65
-
66
- ```js
67
- import { HavokPlugin, PhysicsAggregate, PhysicsShapeType } from "@babylonjs/core";
68
- import HavokPhysics from "@babylonjs/havok";
69
-
70
- const havok = await HavokPhysics(); // MUST await — loads the .wasm
71
- scene.enablePhysics(new Vector3(0, -9.81, 0), new HavokPlugin(true, havok));
72
-
73
- // dynamic body:
74
- new PhysicsAggregate(sphere, PhysicsShapeType.SPHERE, { mass: 1, restitution: 0.6, friction: 0.5 }, scene);
75
- // static body: mass 0
76
- new PhysicsAggregate(ground, PhysicsShapeType.BOX, { mass: 0 }, scene);
77
- ```
78
-
79
- - **`await HavokPhysics()` is mandatory** and the #1 init error. First `HavokPlugin` arg (`_useDeltaForWorldStep`, usually `true`) makes physics use engine delta for smoother variable framerate.
80
- - **Bundler gotcha (Vite/webpack):** the `HavokPhysics.wasm` file must be served. Use `await HavokPhysics({ locateFile: f => \`/assets/${f}\` })` or configure the bundler to copy the wasm.
81
- - **PhysicsAggregate** is the easy path: it builds the matching `PhysicsShape` + `PhysicsBody` automatically. For fine control (compound shapes, sharing shapes across many bodies) build `PhysicsBody` + `PhysicsShape` yourself.
82
- - Read/write motion: `aggregate.body.setLinearVelocity(v)`, `applyImpulse`, `setMassProperties`, `body.setMotionType(PhysicsMotionType.ANIMATED/DYNAMIC/STATIC)`.
83
- - Collisions/triggers: `body.setCollisionCallbackEnabled(true)` + `body.getCollisionObservable().add(...)`; use `PhysicsShapeType.CONTAINER`/mesh shapes sparingly (mesh colliders are expensive — prefer primitives or convex hulls).
84
- - **glTF imports:** apply physics to the actual mesh, not the `__root__` transform node — often re-parent or use the child mesh; otherwise transforms get double-applied.
85
- - Debug: `new BABYLON.Debug.PhysicsViewer(scene).showBody(aggregate.body)`.
86
- - Older engines (Cannon, Ammo, Oimo) still exist via the V1 plugin, but **Havok V2 is the recommended choice** for new games. Ammo remains an option if you need its specific features/soft bodies.
87
-
88
- ---
89
-
90
- ## 5. Asset loading — containers & glTF (do it right for level switching)
91
-
92
- - **glTF/GLB is the format.** `import "@babylonjs/loaders";` then `await ImportMeshAsync("model.glb", scene)` (or `SceneLoader.ImportMeshAsync` / `AppendSceneAsync`). Use Draco + KTX2/Basis compression.
93
- - **AssetContainer is the key tool for reusable/levels:** `LoadAssetContainerAsync(url, scene)` loads meshes/materials/textures **without adding them to the scene**. Then `container.addAllToScene()` / `container.removeAllFromScene()` and, crucially, **`container.dispose()`** to fully free GPU resources when unloading a level. This gives clean load/unload cycles and lets you **instantiate** copies:
94
- - `container.instantiateModelsToScene(name => name, cloneMaterials)` clones a loaded model (with skeletons/animations) cheaply for spawning many enemies from one load.
95
- - **AssetsManager** gives progress-tracked batch loading with tasks (mesh, texture, binary) and `onProgress`/`onFinish` — good for a loading screen.
96
- - **Babylon does not GC GPU resources** any more than Three.js does — dispose meshes/materials/textures or (better) dispose the AssetContainer when leaving a level.
97
-
98
- ---
99
-
100
- ## 6. Materials & Node Material Editor
101
-
102
- - **PBRMaterial** for realistic; **StandardMaterial** for simpler/cheaper. Reuse material instances across meshes (shared material = fewer state changes).
103
- - **Node Material** — visual shader graph (Node Material Editor at nme.babylonjs.com). Export as JSON and load with `NodeMaterial.ParseFromSnippetAsync("snippetId", scene)` or from file. Great for custom effects (dissolve, water, force-fields) without writing GLSL/WGSL by hand, and it compiles to both WebGL and WebGPU.
104
- - **Material plugins** and `material.freeze()` (see freezing below) reduce per-frame shader/uniform recompute.
105
-
106
- ---
107
-
108
- ## 7. GUI (built-in — no DOM juggling)
109
-
110
- `import { AdvancedDynamicTexture, Button, ... } from "@babylonjs/gui";`
111
-
112
- - **Fullscreen UI:** `AdvancedDynamicTexture.CreateFullscreenUI("ui")` — a 2D overlay in screen space for HUD/menus (buttons, sliders, text, stack panels, grids). Resolution-independent, handles pointer input, works on mobile.
113
- - **In-world UI:** apply an ADT to a mesh's material for diegetic screens/labels; use `linkWithMesh` to attach floating labels/health bars that track 3D objects.
114
- - Prefer Babylon GUI over hand-rolled DOM overlays for game HUDs — it integrates with the scene, scales with the canvas, and doesn't fight CSS.
115
-
116
- ---
117
-
118
- ## 8. Performance — FREEZING is the Babylon superpower
119
-
120
- For anything static, tell Babylon to stop recomputing it. This is the highest-leverage Babylon optimization and under-used in generated code.
121
-
122
- - **`mesh.freezeWorldMatrix()`** — mesh never moves ⇒ skip world-matrix recompute each frame. Call `unfreezeWorldMatrix()` if it needs to move again. Also set `mesh.doNotSyncBoundingInfo = true` for static meshes.
123
- - **`material.freeze()`** — material params fixed ⇒ skip uniform/shader re-evaluation. `unfreeze()` to change it.
124
- - **`scene.freezeActiveMeshes()`** — locks the active-mesh (culling) list; use when the set of visible meshes doesn't change (e.g., fixed camera or after setup). `unfreezeActiveMeshes()` when it changes. Huge CPU savings on large static scenes.
125
- - **`scene.blockMaterialDirtyMechanism = true`** while bulk-creating materials to avoid repeated recompiles.
126
-
127
- Other big levers (deeper than the three.js file's bullets):
128
- - **`scene.performancePriority = ScenePerformancePriority.Intermediate` (or `Aggressive`)** — auto-applies a bundle of optimizations (freezes active meshes, skips some checks). `Aggressive` disables per-mesh picking/some features — verify nothing you need breaks.
129
- - **Thin instances** (`mesh.thinInstanceAdd(matrix)` / `thinInstanceSetBuffer`) for thousands of identical static objects → one draw call, cheaper than regular instances. Regular **instances** (`mesh.createInstance()`) when you need per-instance picking/parenting.
130
- - **`scene.autoClear = false`** (and `autoClearDepthAndStencil`) when the scene fully covers the viewport — skips the clear.
131
- - **`scene.skipPointerMovePicking = true`** if you don't need hover/move picking (picking on every pointer move is a silent CPU cost). Set `mesh.isPickable = false` on non-interactive meshes.
132
- - **`scene.skipFrustumClipping`**, `mesh.alwaysSelectAsActiveMesh` — micro-tune culling for known-visible meshes.
133
- - **Merge meshes** (`Mesh.MergeMeshes([...], true, true, undefined, false, true)`) for static geometry sharing a material.
134
- - **LOD:** `mesh.addLODLevel(distance, lowMesh)` and `addLODLevel(farDist, null)` to cull entirely far away.
135
- - Keep **`camera.maxZ` low**; limit lights (each real-time light multiplies shader cost); use **shadow generators sparingly** with small map sizes and `RefreshRate` for static lights.
136
- - Avoid per-frame allocations: use **`TmpVectors.Vector3[0]`** scratch vectors and the `...ToRef()` method variants (`addToRef`, `scaleToRef`) instead of returning new objects.
137
-
138
- ---
139
-
140
- ## 9. SceneOptimizer — adaptive quality to hit a target FPS
141
-
142
- Instead of guessing settings per device, let Babylon degrade quality until it reaches a target framerate.
143
-
144
- ```js
145
- import { SceneOptimizer, SceneOptimizerOptions } from "@babylonjs/core";
146
- // preset tiers try progressively harder optimizations to reach the target FPS:
147
- SceneOptimizer.OptimizeAsync(scene,
148
- SceneOptimizerOptions.HighDegradationAllowed(60), // target 60 fps
149
- () => console.log("reached target"),
150
- () => console.log("could not reach target"));
151
- ```
152
-
153
- - Presets: `LowDegradationAllowed`, `ModerateDegradationAllowed`, `HighDegradationAllowed(targetFps)`. They apply, in escalating order, optimizations like: reduce hardware scaling, merge meshes, disable shadows, reduce texture size, disable post-processes, cut particle counts.
154
- - You can build a custom `SceneOptimizerOptions` with specific `SceneOptimization` steps and priorities. Great for shipping one build that adapts from low-end mobile to desktop automatically.
155
-
156
- ---
157
-
158
- ## 10. Inspector & profiling
159
-
160
- - **`import "@babylonjs/inspector"; scene.debugLayer.show()`** — the in-browser inspector: scene tree, per-mesh stats, materials, textures, and a **Statistics/Performance** tab (draw calls, active meshes, frame breakdown, GPU/CPU time). This is the fastest way to find what's slow.
161
- - Watch **draw calls** and **active meshes** counts; use the profiler to see whether you're CPU-bound (draw calls, matrix updates → freeze/instance) or GPU-bound (overdraw, shader cost, texture size → LOD/compression/fewer lights).
162
-
163
- ---
164
-
165
- ## 11. Common Babylon pitfalls (checklist)
166
-
167
- - Forgetting `await WebGPUEngine.initAsync()` / `await HavokPhysics()` → cryptic init failures.
168
- - Havok `.wasm` not served by the bundler → physics silently absent; use `locateFile` / copy the wasm.
169
- - Not disposing meshes/materials/textures or the AssetContainer on level switch → GPU memory leak.
170
- - Applying physics to a glTF `__root__` node → double transforms / wrong positions.
171
- - Static scene running full cost because nothing is frozen → freeze world matrices, materials, active meshes.
172
- - Picking on every pointer move (`skipPointerMovePicking` not set; meshes left `isPickable`) → CPU drain.
173
- - Too many real-time lights / large shadow maps → shader + fill cost explosion.
174
- - Per-frame `new Vector3()`/`Matrix` allocations → GC churn; use `TmpVectors` + `...ToRef()`.
175
- - Huge `camera.maxZ` → z-fighting and wasted culling range.
176
- - Mesh colliders for everything instead of primitive/convex shapes → physics perf collapse.
177
-
178
- ---
179
-
180
- ## Defaults to apply
181
-
182
- - **Reach for Babylon when the game wants an integrated engine** (built-in physics, GUI, inspector, camera behaviors) rather than the assemble-it-yourself Three.js route.
183
- - **Always await `initAsync()` (WebGPU) and `HavokPhysics()`**, and wire the **WebGPU-with-WebGL2-fallback** pattern by default.
184
- - **Emit freezing by default for static content**: `freezeWorldMatrix()` on non-moving meshes, `material.freeze()` on static materials, and `scene.freezeActiveMeshes()` / `performancePriority` once the scene is set up. This is the single biggest Babylon win most generated code misses.
185
- - **Ship `SceneOptimizer.OptimizeAsync(scene, HighDegradationAllowed(60))`** so one build adapts from low-end mobile to desktop instead of hardcoding quality.
186
- - **Use AssetContainers** for level load/unload (`instantiateModelsToScene` to spawn many from one load; `dispose()` to free on unload) to avoid the memory leaks that plague generated 3D games.
187
- - **Use Babylon GUI** (fullscreen ADT) for HUDs/menus instead of DOM overlays; use **camera Behaviors** (Framing/AutoRotation) for free menu/product polish.
188
- - Set **`skipPointerMovePicking`, low `maxZ`, `isPickable=false`** on non-interactive meshes as defaults.
189
-
190
- ---
191
-
192
- ## Sources
193
- - Babylon.js docs — Optimizing your scene (freeze APIs, autoClear, performancePriority, active meshes): https://doc.babylonjs.com/features/featuresDeepDive/scene/optimize_your_scene
194
- - Babylon.js docs — Physics V2 / Havok (`enablePhysics`, `PhysicsAggregate`, `PhysicsBody/Shape`): https://doc.babylonjs.com/features/featuresDeepDive/physics/usingPhysicsEngine and https://github.com/BabylonJS/Documentation/blob/master/content/features/featuresDeepDive/physics/v2/usingPhysicsEngine.md
195
- - `@babylonjs/havok` npm (init pattern, `await HavokPhysics()`, `locateFile`): https://www.npmjs.com/package/@babylonjs/havok
196
- - Babylon.js docs — WebGPU (`WebGPUEngine`, `initAsync`, snapshot rendering): https://doc.babylonjs.com/setup/support/webGPU
197
- - Babylon.js docs — Cameras & Camera Behaviors: https://doc.babylonjs.com/features/featuresDeepDive/cameras/camera_introduction and https://doc.babylonjs.com/features/featuresDeepDive/behaviors/cameraBehaviors
198
- - Babylon.js docs — Asset Containers & glTF loading: https://doc.babylonjs.com/features/featuresDeepDive/importers/assetContainers and https://doc.babylonjs.com/features/featuresDeepDive/importers/loadingFileTypes
199
- - Babylon.js docs — SceneOptimizer: https://doc.babylonjs.com/features/featuresDeepDive/scene/sceneOptimizer
200
- - Babylon.js docs — GUI: https://doc.babylonjs.com/features/featuresDeepDive/gui/gui ; Node Material: https://doc.babylonjs.com/features/featuresDeepDive/materials/node_material/nodeMaterial
201
- - Babylon.js docs — Inspector: https://doc.babylonjs.com/toolsAndResources/inspector
202
- - Babylon.js forum — optimization best practices thread: https://forum.babylonjs.com/t/best-practices-for-optimizing-babylon-js-scenes-not-just-on-lower-end-devices/58688
@@ -1,122 +0,0 @@
1
- # Collision & Physics for Browser Games (2D AABB/SAT/broadphase, swept collision, 3D Rapier/cannon, fixed timestep)
2
-
3
- Consolidated from MDN game collision docs, Gaffer On Games, Rapier/cannon-es docs, and the SAT/swept-AABB canon (see Sources). Focus: what an AI builder needs so collisions are **correct and stable** — the classic bugs are tunneling through walls at speed, jitter, sinking into the ground, and O(n²) slowdowns.
4
-
5
- ---
6
-
7
- ## 1. Do you even need a physics engine?
8
-
9
- - **Simple arcade games** (platformers, top-down, breakout, shooters) → hand-rolled **AABB** collision + resolution is often better: fully deterministic, no dependency, and you control feel. Most 2D games don't need Box2D/Matter.
10
- - **Rigid-body simulation** (stacking, ragdolls, joints, realistic bouncing, vehicles) → use an engine: **2D → Matter.js / Planck.js (Box2D) / Rapier2D**; **3D → Rapier (rapier.js, WASM, fast, favored) / cannon-es / Ammo.js**.
11
- - **Rule:** don't pull in a full rigid-body engine for a game that just needs "does the player box overlap the wall box." Physics engines add non-determinism and tuning overhead. Match the tool to the game.
12
-
13
- ---
14
-
15
- ## 2. 2D collision detection primitives
16
-
17
- - **AABB (axis-aligned bounding box)** — the workhorse. Two boxes overlap iff they overlap on **both** axes:
18
- ```js
19
- const hit = a.x < b.x+b.w && a.x+a.w > b.x && a.y < b.y+b.h && a.y+a.h > b.y;
20
- ```
21
- Cheap, ideal for tile maps, most 2D gameplay. Only valid for **non-rotated** boxes.
22
- - **Circle/distance** — for round objects: compare squared distance to summed radii (`dx*dx+dy*dy < (r1+r2)²` — avoid `sqrt`).
23
- - **SAT (Separating Axis Theorem)** — for **rotated boxes / convex polygons**: two convex shapes don't intersect iff there exists an axis (a face normal of either shape) on which their projections don't overlap. Test all face normals; if any gap exists → no collision. The **minimum overlap axis gives the collision normal + penetration depth** (the MTV, minimum translation vector) for resolution.
24
- - SAT only works on **convex** shapes — decompose concave shapes into convex pieces.
25
- - For circles vs polygon, also test the axis from circle center to nearest vertex.
26
-
27
- ---
28
-
29
- ## 3. Broadphase: don't test every pair (O(n²) killer)
30
-
31
- Checking all pairs is O(n²) — fine for dozens, catastrophic for hundreds/thousands. Split into **broadphase** (cheap culling of pairs that can't touch) → **narrowphase** (exact AABB/SAT on survivors).
32
-
33
- - **Uniform spatial hash grid** — bucket objects into cells by position; only test objects sharing a cell. Best default for many similar-sized, evenly-distributed objects (bullets, particles, .io games). Cell size ≈ average object size (2–3×).
34
- - **Quadtree** — recursively subdivide space; good for **non-uniform / clustered / varied-size** objects. Rebuild or update each frame.
35
- - **Sort and sweep (sweep-and-prune)** — sort AABB endpoints on an axis; good when objects move coherently.
36
- - **Rule:** the moment you have >~100 dynamic colliders, add a broadphase. Physics engines do this internally; hand-rolled collision needs it explicitly.
37
-
38
- ---
39
-
40
- ## 4. Tunneling & swept collision (the top correctness bug)
41
-
42
- **Tunneling:** a fast object moves so far in one frame that it passes *through* a thin wall without ever overlapping it on any frame. Discrete AABB checks miss it entirely.
43
-
44
- Fixes (in order of preference):
45
- - **Swept collision (continuous / CCD):** instead of testing the box at its new position, test the **motion path**. **Swept AABB** computes the fraction of the frame `t (0..1)` at which the moving box first touches the target, then moves the object to exactly that contact point and resolves — no overlap ever occurs. Essential for bullets, fast platformers, thin walls.
46
- - **Substepping / smaller fixed timestep:** break a big move into several small steps and test each. Simpler than swept, good enough for moderate speeds.
47
- - **Raycast** fast/small projectiles (bullets) instead of moving a body — cast a ray along the travel and hit the first collider.
48
- - **Minimum wall thickness** ≥ max per-step travel is a cheap band-aid but fragile.
49
- - In engines, **enable CCD** on fast bodies (Rapier `setCcdEnabled(true)`, cannon-es CCD options).
50
-
51
- ---
52
-
53
- ## 5. Collision *resolution* (not just detection)
54
-
55
- - **AABB resolution:** compute penetration on each axis; push the object out along the **axis of least penetration** (this makes walls/floors behave). Zero the velocity component on the axis you resolved (hitting the floor kills downward velocity).
56
- - **Resolve axes separately** for platformers ("move X, resolve X, then move Y, resolve Y") — prevents catching on tile seams and gives clean wall-slide behavior.
57
- - **Ground detection:** you're grounded if resolving downward this frame; set a small `coyoteTime` (see input skill) for feel.
58
- - **Avoid sinking/jitter:** apply a tiny "skin"/epsilon and don't over-correct; with engines, tune restitution/friction and let the solver settle. Resting jitter usually means variable timestep or fighting corrections.
59
- - With **SAT**, resolve along the MTV (normal × penetration depth); reflect/scale velocity along the normal for bounces.
60
-
61
- ---
62
-
63
- ## 6. Fixed timestep — the stability foundation (tie-in)
64
-
65
- **Physics MUST run on a fixed timestep with an accumulator** ("Fix Your Timestep!", Gaffer On Games). Variable `dt` makes collision/physics non-deterministic and unstable (tunneling worsens, springs explode, replays/netcode desync).
66
- ```js
67
- const STEP = 1/60; let acc = 0;
68
- function frame(dt){ acc += Math.min(dt, 0.25); // clamp to avoid spiral-of-death after tab-out
69
- while (acc >= STEP){ physicsStep(STEP); acc -= STEP; }
70
- const alpha = acc / STEP; render(alpha); // interpolate between last two states
71
- }
72
- ```
73
- - **Clamp accumulated dt** (e.g. ≤0.25s) so a backgrounded tab doesn't trigger a "spiral of death" of catch-up steps.
74
- - **Interpolate rendering** between the previous and current physics state using `alpha` for smooth visuals at any display rate.
75
- - All physics engines expect a fixed step — call `world.step()` at a fixed rate, not per rAF with variable dt. Rapier is deterministic given fixed steps + same inputs (good for netcode).
76
-
77
- ---
78
-
79
- ## 7. 3D character controllers
80
-
81
- Falling capsules from raw rigid-body dynamics feel bad for players — use a **kinematic character controller**:
82
- - **Rapier `KinematicCharacterController`** (favored): create via `world.createCharacterController(offset)`, use a kinematic body + capsule/collider, then each fixed step call `computeColliderMovement(collider, desiredTranslation)` and read `computedMovement()` to get the collision-corrected move. Built-in **autostep** (stairs), **snap-to-ground** (don't float off slopes/ramps), **max slope climb angle**, and slide-along-walls. Set gravity/jump yourself (kinematic = you control motion).
83
- - **cannon-es**: `PointerLockControlsCannon` example / a sphere or capsule body; more manual.
84
- - Rules: use a **capsule** (not a box) so the player slides over small steps and around corners; apply movement each **fixed step**; do ground checks via the controller's grounded flag or a short downward ray; keep the visual mesh synced to the body each frame (with interpolation).
85
-
86
- ---
87
-
88
- ## 8. Bug-prevention checklist
89
- - **Variable timestep for physics** → non-deterministic, jitter, worse tunneling, netcode desync; fixed step + accumulator.
90
- - **No dt clamp** → "spiral of death" after tab-out; clamp accumulated dt.
91
- - **Fast objects passing through walls** → tunneling; use swept AABB / CCD / raycast / substeps.
92
- - **SAT on concave shapes** → wrong results; decompose into convex pieces.
93
- - **AABB test on rotated boxes** → false/missed hits; use SAT for rotation.
94
- - **O(n²) pair testing** → frame drops at scale; add spatial hash/quadtree broadphase.
95
- - **Resolving both axes at once** → catching on tile seams / clipping corners; resolve X then Y.
96
- - **Not zeroing velocity on the resolved axis** → gravity accumulates, object shudders into ground.
97
- - **Player floats off ramps / trips on stairs** → missing snap-to-ground / autostep; use a character controller (Rapier) with those enabled.
98
- - **Box character controller** → snags on edges; use a capsule.
99
- - **`sqrt` in hot distance checks** → wasted perf; compare squared distances.
100
- - **Reading physics state without render interpolation** → visible stutter at high refresh rates; interpolate with `alpha`.
101
-
102
- ---
103
-
104
- ## Defaults to apply
105
- - **Right-size the solution:** hand-rolled **AABB + separate-axis resolution + swept collision** for arcade/2D/platformers; **Rapier** (2D or 3D) when we need real rigid bodies, joints, or a character controller. Don't default to a heavy engine.
106
- - **Always run physics on a fixed timestep with a clamped accumulator + render interpolation** — this one pattern prevents tunneling instability and jitter, and it ties directly into the fixed-timestep game loop (see `threejs-foundational.md`).
107
- - **Ship anti-tunneling by default** for fast objects (swept AABB or CCD/raycast for projectiles) and a **broadphase (spatial hash or quadtree)** once there are many colliders.
108
- - **For 3D player movement, generate a Rapier `KinematicCharacterController` with a capsule, autostep, snap-to-ground, and slope limits** — not a raw dynamic body — so movement feels right out of the box.
109
-
110
- ---
111
-
112
- ## Sources
113
- - MDN — 2D collision detection (AABB, circle, SAT): https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection
114
- - Gaffer On Games — "Fix Your Timestep!": https://gafferongames.com/post/fix_your_timestep/ ; "Collision Response and Coulomb Friction": https://gafferongames.com/post/collision_response_and_coulomb_friction/
115
- - Swept AABB collision — jitter physics / "Swept AABB Collision Detection and Response" (gamedev): https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/swept-aabb-collision-detection-and-response-r3084/
116
- - SAT reference — Metanet/N tutorial & dyn4j "SAT (Separating Axis Theorem)": https://dyn4j.org/2010/01/sat/ ; https://www.metanetsoftware.com/technique/tutorialA.html
117
- - Spatial hashing / broadphase — "Spatial Hashing" (gamedev) & quadtree collision (GameDev Academy): https://gameprogrammingpatterns.com/spatial-partition.html
118
- - Rapier — docs (rigid bodies, CCD, character controller): https://rapier.rs/docs/ ; character controller: https://rapier.rs/docs/user_guides/javascript/character_controller ; JS bindings: https://github.com/dimforge/rapier.js
119
- - cannon-es — repo/examples (incl. PointerLockControlsCannon): https://github.com/pmndrs/cannon-es ; https://pmndrs.github.io/cannon-es/
120
- - Matter.js: https://brm.io/matter-js/ ; Planck.js (Box2D): https://github.com/piqnt/planck.js
121
- - Box2D docs (continuous collision / solver background): https://box2d.org/documentation/
122
- - Game Programming Patterns — Spatial Partition & Game Loop: https://gameprogrammingpatterns.com/spatial-partition.html , https://gameprogrammingpatterns.com/game-loop.html
@@ -1,111 +0,0 @@
1
- # ECS & Game State Architecture for JS Games (bitECS, miniplex, ECS vs OOP, state structure)
2
-
3
- Consolidated from webgamedev.com, the bitECS and miniplex docs, and data-oriented-design canon (see Sources). Focus: how an AI builder should **structure game state so it stays fast and untangled** as a game grows — and when *not* to reach for ECS.
4
-
5
- ---
6
-
7
- ## 1. What ECS is (and why it exists)
8
-
9
- **Entity-Component-System** separates data from behavior:
10
- - **Entity** — an ID (or a plain object) with no logic; just a thing that exists.
11
- - **Component** — pure **data**, no methods (Position, Velocity, Health, Sprite, Collider).
12
- - **System** — pure **behavior** that iterates all entities having a given set of components and updates them (MovementSystem reads Position+Velocity).
13
-
14
- Benefits: **composition over inheritance** (add/remove capabilities by adding/removing components — no deep class hierarchies), cache-friendly iteration, easy serialization (state = plain data), and clean separation that scales to thousands of entities.
15
-
16
- The classic problem ECS solves: the "deadly diamond" of OOP inheritance (`FlyingEnemy` vs `SwimmingEnemy` vs `FlyingSwimmingShootingEnemy`...). With ECS you just attach `Flying`, `Swimming`, `Shooting` components in any combination.
17
-
18
- ---
19
-
20
- ## 2. When ECS vs OOP (don't cargo-cult ECS)
21
-
22
- **Use plain OOP / a simple object list when:**
23
- - Small games, jams, prototypes, or a handful of distinct entity types.
24
- - Entity count is low (dozens–low hundreds) and perf isn't a concern.
25
- - The team/model iterates faster with intuitive `player.jump()` classes.
26
- - The engine already gives you a good model (Phaser GameObjects/prefabs, Three.js `Object3D` scene graph) — you can go a long way with a component-ish mixin approach without a full ECS.
27
-
28
- **Reach for ECS when:**
29
- - **Many similar entities** (bullet-hell, RTS, particles, simulations, .io games) — thousands of entities needing fast batch updates.
30
- - Highly **combinatorial** entity capabilities (lots of mix-and-match behaviors/status effects).
31
- - You need **determinism/serialization** (netcode, replays, save states) — pure-data components serialize trivially.
32
-
33
- **Rule:** ECS is an optimization/organization tool, not a moral requirement. A giant `update()` switch or a tidy class hierarchy is fine for small games. Adopt ECS when entity count/combinatorial complexity actually bites — premature ECS adds boilerplate for no gain.
34
-
35
- ---
36
-
37
- ## 3. Library choice: bitECS vs miniplex
38
-
39
- **miniplex** — DX-first, entities are **plain JS objects**, components are just properties. Best default for most indie/web games and rapid prototyping; excellent TypeScript + React bindings.
40
- ```js
41
- import { World } from 'miniplex';
42
- const world = new World();
43
- const player = world.add({ position:{x:0,y:0}, velocity:{x:100,y:0}, health:{cur:100,max:100} });
44
- const moving = world.with('position','velocity'); // live archetype query
45
- function movementSystem(dt){ for (const e of moving){ e.position.x += e.velocity.x*dt; e.position.y += e.velocity.y*dt; } }
46
- world.remove(player);
47
- ```
48
- - Use `world.addComponent(e,'velocity',{...})` / `removeComponent` so queries re-index (mutating a bare property can skip re-indexing).
49
- - `for...of` over a query is fast and **safe for removal during iteration**. No built-in scheduler — you call systems from your loop.
50
- - Object property access is slightly slower at extreme entity counts than bitECS's typed arrays.
51
-
52
- **bitECS** — performance-first, data-oriented: entities are **integer IDs**, components are **Structure-of-Arrays (typed arrays)**, archetype/bitmask queries. Best for tens of thousands of entities, WebGPU, perf-critical sims. ~5kb, zero deps (used in Hubs/Third Room; eyed by Phaser 4).
53
- ```js
54
- import { createWorld, addEntity, addComponent, query } from 'bitecs';
55
- const world = createWorld({ Position:{x:new Float32Array(1e4),y:new Float32Array(1e4)}, Velocity:{x:[],y:[]} });
56
- const { Position, Velocity } = world.components;
57
- const eid = addEntity(world); addComponent(world,eid,Position); addComponent(world,eid,Velocity);
58
- const moving = query(world,[Position,Velocity]);
59
- for (const e of moving){ Position.x[e] += Velocity.x[e]*dt; Position.y[e] += Velocity.y[e]*dt; }
60
- ```
61
- - **Note the API moved on:** older tutorials use `defineComponent`/`defineQuery`/`Types`; current bitECS (0.4+) uses `createWorld({...schemas})` + `query(world,[...])`, plus relationships/observers/prefabs. Verify the version you install.
62
- - SoA layout = cache-friendly; entities-as-IDs = trivial to serialize/network.
63
-
64
- **Others:** Becsy (multithreaded), Koota, or the engine's own model. Some projects mix (bitECS core sim + object layer for UI).
65
-
66
- ---
67
-
68
- ## 4. Structuring game state (even without a formal ECS)
69
-
70
- - **Single source of truth:** keep a central, serializable game-state object (or ECS world). Avoid scattering authoritative data across DOM, closures, and random globals — it makes save/load, undo, and netcode nearly impossible.
71
- - **Separate data from rendering:** gameplay state (positions, health) should be independent of the visual objects (meshes/sprites). Systems update data; a render/sync step pushes data → Three.js/Phaser objects each frame. This keeps the sim testable/deterministic and lets you do fixed-timestep + interpolation.
72
- - **Systems run in a defined order each tick:** input → AI → movement → collision → damage → cleanup → render-sync. Order matters and should be explicit, not incidental.
73
- - **Object pooling instead of create/destroy churn:** for bullets/enemies/particles, recycle entities (mark inactive) rather than allocating/GCing every frame (pairs with ECS well; see `threejs-foundational.md`).
74
- - **Deferred structural changes:** don't add/remove entities in the middle of iterating a query in ways the lib doesn't support — queue spawns/despawns and apply between systems (miniplex `for...of` is removal-safe; still queue mass changes for clarity).
75
- - **Fixed timestep for the sim** (see game-loop/collision skills) so ECS systems are deterministic — required for netcode/replays.
76
- - **Events/messaging** between systems via a small event queue rather than direct cross-system calls, to keep systems decoupled.
77
-
78
- ---
79
-
80
- ## 5. Bug-prevention checklist
81
- - **Putting logic in components / data in systems** → defeats ECS; keep components pure data, systems pure behavior.
82
- - **Adopting ECS for a tiny game** → boilerplate with no benefit; use a simple object list/classes until entity count/complexity warrants it.
83
- - **Deep inheritance for entity variety** → combinatorial class explosion; compose with components instead.
84
- - **Mutating a miniplex property directly and expecting query updates** → use `addComponent`/`removeComponent` so archetypes re-index.
85
- - **Using stale bitECS `defineComponent` tutorials against a new version** → API mismatch; check installed version's docs.
86
- - **Mixing render objects into authoritative state** → non-serializable, non-deterministic; separate sim data from view.
87
- - **Undefined system order** → order-dependent bugs (moving before collision, etc.); define an explicit pipeline.
88
- - **create/destroy per frame** → GC stalls; pool entities.
89
- - **Structural changes mid-iteration** → skipped/duplicated updates; defer to a queue.
90
- - **Scattered global state** → save/load and netcode become impossible; centralize the world.
91
-
92
- ---
93
-
94
- ## Defaults to apply
95
- - **Default to miniplex** for generated games that need ECS (plain objects, great TS/React DX); **switch to bitECS** only when the game genuinely has thousands of entities or needs SoA perf. For small/simple games, a plain object list or engine prefabs is fine — don't force ECS.
96
- - **Always structure state as a single serializable world with sim/render separation** and an **explicit system pipeline** (input→AI→movement→collision→damage→cleanup→render-sync) run on a fixed timestep. This unlocks save/load, replays, and netcode for free.
97
- - **Bake in pooling + deferred spawn/despawn** for entity-heavy genres.
98
- - When generating ECS code, **verify the library version's current API** (bitECS especially changed) rather than emitting old `defineComponent` patterns from memory.
99
-
100
- ---
101
-
102
- ## Sources
103
- - Web Game Dev — Code architecture / ECS overview: https://www.webgamedev.com/code-architecture/ecs
104
- - bitECS — repo & docs: https://github.com/NateTheGreatt/bitECS , https://bitecs.dev/docs/introduction
105
- - miniplex — repo & docs: https://github.com/hmans/miniplex , miniplex-react: https://github.com/hmans/miniplex/tree/main/packages/miniplex-react
106
- - Becsy (multithreaded ECS): https://lastolivegames.github.io/becsy/
107
- - Sander Mertens — "Entity Component System FAQ": https://github.com/SanderMertens/ecs-faq
108
- - Adam Martin — "Entity Systems are the future of MMOG development": http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/
109
- - Mick West — "Evolve Your Hierarchy" (components over inheritance): https://cowboyprogramming.com/2007/01/05/evolve-your-hierarchy/
110
- - Richard Fabian — Data-Oriented Design (book): https://www.dataorienteddesign.com/dodbook/
111
- - Game Programming Patterns — Component pattern: https://gameprogrammingpatterns.com/component.html
@@ -1,110 +0,0 @@
1
- # Game Feel & Juice (screenshake, hitstop, tweening/easing, particles, squash & stretch, camera, SFX layering)
2
-
3
- The canon: Steve Swink's *Game Feel*, Vlambeer/"Juice it or lose it" (Martin Jonasson & Petri Purho), and Jan Willem Nijman's "The art of screenshake" (see Sources). "Juice" = generous, layered, non-gameplay-affecting feedback that makes every input feel physical and satisfying. Focus: what an AI builder should reflexively add so games feel **alive instead of static**, without hurting readability or perf.
4
-
5
- ---
6
-
7
- ## 1. The core principle
8
-
9
- **Every meaningful action should produce disproportionate, multi-sensory feedback.** A single "hit" should simultaneously trigger several of: sound, particles, screenshake, hitstop, flash, knockback, squash/stretch, and a number/pop. The gameplay math can stay simple — the *feel* comes from the feedback layer stacked on top. The classic demo takes the same identical Breakout and makes it feel amazing purely by adding these layers.
10
-
11
- **Rule:** Separate "simulation" from "presentation." Feedback (shake, tween, particles, flash) must **never change gameplay outcomes** — it's cosmetic. This keeps physics deterministic (important for netcode/replays) while letting you pile on juice freely.
12
-
13
- ---
14
-
15
- ## 2. Screenshake (the highest impact-per-effort effect)
16
-
17
- - Offset the **camera** (or a camera container), not the world objects. Apply a random offset each frame from a **trauma value** that **decays over time**.
18
- - **Use trauma², not linear** (Squirrel Eiserloh's "Juicing Your Cameras"): store `trauma` in [0,1], set `shake = trauma * trauma` (or `trauma³`). Add trauma on events (small hit +0.3, explosion +0.8), decay `trauma -= decay * dt` each frame. Squaring makes small hits subtle and big hits explosive.
19
- - Offset with **noise, not pure random**, for smoother shake: `offsetX = maxOffset * shake * (noise(t) )`; also shake **rotation** slightly (`maxAngle * shake * noise`) — rotational shake reads as more violent.
20
- - **Directional shake** for directional hits (kick the camera opposite the impact) reads better than omnidirectional for melee/recoil.
21
- - **Cap it & scale it down for accessibility.** Excessive shake causes motion sickness — expose a "screen shake" slider/toggle. Never shake so hard UI/targets become unreadable.
22
- - Scale offsets by `dt`-independent amount but decay by `dt` so it's frame-rate independent.
23
-
24
- Nijman's rules also include: **more bullets, bigger bullets, muzzle flash, impact effects, permanent decals, camera lerp/lookahead, camera kick, sleep/hitstop, gun delay, knockback, screen shake, and even a little randomness in everything.**
25
-
26
- ---
27
-
28
- ## 3. Hitstop / hitstun / "sleep" (freeze frames on impact)
29
-
30
- - On a big hit, **freeze the game (or just the two involved entities) for a few frames** (~30–120ms), then resume. This sells impact enormously — the brain reads the pause as force.
31
- - Implement as a global **time scale** or a short "freeze frames" counter: while frozen, skip the gameplay update (or set `timeScale=0`) but **keep rendering** and keep the flash/particles visible. Common: freeze ~2–6 frames for normal hits, longer for finishers.
32
- - Keep hitstop **short**; too long feels laggy/unresponsive. Often paired with a brief hit **flash** (tint the sprite white for 1–2 frames) and knockback that starts *after* the freeze.
33
- - Distinguish **hitstop** (brief freeze for feel) from **hitstun** (gameplay state where a hit character can't act) — the latter is real gameplay, the former is pure juice.
34
-
35
- ---
36
-
37
- ## 4. Tweening & easing (motion that isn't linear)
38
-
39
- - **Almost nothing should move linearly.** Real, satisfying motion accelerates/decelerates. Use **easing functions** for UI transitions, pickups flying to the HUD, menus, popups, camera moves, damage numbers.
40
- - Common curves (see easings.net for exact formulas/graphs):
41
- - **easeOutQuad/Cubic** — arrive gently (great for things settling into place).
42
- - **easeInQuad/Cubic** — start slow (things launching).
43
- - **easeOutBack** — slight overshoot then settle (pop-in for UI/pickups — very juicy).
44
- - **easeOutElastic / easeOutBounce** — springy/bouncy (buttons, coin pickups). Use sparingly.
45
- - **easeInOutQuad** — smooth both ends (camera, generic).
46
- - **Use a tween library** rather than hand-rolling: **GSAP** (best-in-class, huge easing set, timelines), **@tweenjs/tween.js** (lightweight, common in Three.js), or the engine's built-in (Phaser `this.tweens.add`). Tweens compose (chains, delays, yoyo, repeat) and auto-handle dt.
47
- - **Kill/clean up tweens** when the target is destroyed or the scene shuts down (leaked tweens mutating dead objects = crashes/bugs). Phaser: kill on `SHUTDOWN`; GSAP: `.kill()`.
48
- - A **spring/damped-lerp** (`x += (target - x) * (1 - exp(-k*dt))`) is a great procedural alternative for continuous following (cameras, cursors, UI) — always frame-rate correct if you use the `exp` form rather than `x += (target-x)*0.1` (the naive lerp is frame-rate dependent — see §6).
49
-
50
- ---
51
-
52
- ## 5. Particles & squash-and-stretch
53
-
54
- - **Particles everywhere:** dust on landing/footsteps, sparks on hit, debris on death, trails on projectiles, confetti on win, ambient motes. They cost little and add enormous life. Use the engine's particle system (Phaser `add.particles`, Three.js points/instanced sprites) and **pool** them (no per-emit allocation — see `threejs-foundational.md`).
55
- - **Squash & stretch** (Disney's foundational animation principle): deform on acceleration to convey weight/speed while preserving apparent volume.
56
- - Jump: stretch vertically (taller/thinner) on takeoff, squash (shorter/wider) on landing, then spring back via `easeOutBack`/elastic.
57
- - Preserve volume: if you scale `y` by `s`, scale `x` by ~`1/s`, so it doesn't look like it's growing.
58
- - Drive it from velocity (stretch along the movement direction) or trigger on discrete events (land, hit, shoot recoil).
59
- - **Anticipation + follow-through:** wind up before a big action (tiny reverse/squash) and overshoot after — even a couple frames sells it.
60
- - **Pop numbers & flashes:** floating damage numbers that rise + fade + scale-pop, combo counters, "+10" pickups. Cheap, huge readability + satisfaction win.
61
-
62
- ---
63
-
64
- ## 6. Camera feel (lerp, lookahead, deadzone, punch)
65
-
66
- - **Never hard-snap the camera to the player.** Smoothly follow (`lerp`/spring) toward the target so motion is fluid.
67
- - **Frame-rate-correct smoothing:** `pos += (target - pos) * (1 - Math.exp(-k * dt))`. The naive `pos += (target - pos) * 0.1` is **frame-rate dependent** (faster on 144Hz than 60Hz) — a common bug; use the exp form or a fixed-timestep camera update.
68
- - **Lookahead:** offset the camera slightly in the direction of movement / where the player is aiming, so the player sees more of what's ahead. Ease the offset in/out.
69
- - **Deadzone / soft zone:** don't move the camera until the player leaves a central box — prevents nauseating micro-jitter from small movements.
70
- - **Camera punch/kick** on impacts (a quick zoom-in or positional kick that eases back) complements screenshake.
71
- - Clamp the camera to level bounds; round the final camera position to whole pixels for pixel-art games to avoid shimmer.
72
-
73
- ---
74
-
75
- ## 7. SFX layering & audio feel
76
-
77
- - **Layer sounds** for richness: a single "shoot" = a low thump + a mid body + a high click/transient. Impacts = hit + debris + a tail.
78
- - **Pitch-randomize** repeated sounds (±5–15%) so rapid fire / footsteps don't sound robotic (`playbackRate` / Howler `rate`). Slightly randomize volume too.
79
- - Sound is feedback: **every** action should have audio, and it should be tight (low latency) and satisfy on first frame of the action (see the audio skill for Web Audio/Howler, mobile unlock, buses).
80
- - Duck music briefly under big events; add a subtle low-frequency "boom" on explosions.
81
-
82
- ---
83
-
84
- ## 8. Don't over-juice (readability & perf guardrails)
85
- - **Juice must not obscure gameplay.** If shake/flash/particles hide the player, enemies, or projectiles, dial back. Readability > spectacle.
86
- - **Accessibility:** provide toggles/sliders for screen shake, flashing, and reduced motion (respect `prefers-reduced-motion`). Heavy flashing risks photosensitivity — avoid rapid full-screen strobing.
87
- - **Perf:** pool particles/tweens, cap concurrent particles, don't allocate in the hit path. Juice is cheap but "thousands of unpooled particles per explosion" is not.
88
- - Keep hitstop short and prediction-safe in multiplayer (apply juice on the client only; never let it alter the authoritative sim).
89
-
90
- ---
91
-
92
- ## Defaults to apply
93
- - **Auto-juice defaults:** whenever the builder generates a hit/pickup/death/land/win event, reflexively attach the stack: **sound + particles + short hitstop + white flash + screenshake(trauma²) + easeOutBack pop / squash-stretch + floating number.** Same simple gameplay, dramatically better feel — this is the single biggest perceived-quality lever.
94
- - **Ship a tiny reusable "juice" toolkit** in generated games: a `trauma`-based shake (squared, noise-driven, decaying), a `hitstop(frames)` helper (timeScale/freeze-count), a `flash(sprite)` helper, easing/tween helpers (or GSAP/tween.js), and frame-rate-correct camera follow with lerp + lookahead + deadzone.
95
- - **Always use the `exp`-based lerp** for cameras/followers so smoothing is frame-rate independent — bake this in to avoid the classic 144Hz-vs-60Hz bug.
96
- - **Separate presentation from simulation** so juice never affects gameplay/netcode. Provide screenshake/flash/reduced-motion toggles by default for accessibility.
97
-
98
- ---
99
-
100
- ## Sources
101
- - Martin Jonasson & Petri Purho — "Juice it or lose it" (GDC talk): https://www.youtube.com/watch?v=Fy0aCDmgnxg ; companion "Game feel" write-up on grapefrukt.
102
- - Jan Willem Nijman (Vlambeer) — "The art of screenshake": https://www.youtube.com/watch?v=AJdEqssNZ-U
103
- - Steve Swink — *Game Feel: A Game Designer's Guide to Virtual Sensation* (book), gamefeelbook.com.
104
- - Squirrel Eiserloh — "Juicing Your Cameras With Math" (GDC, trauma² screenshake): https://www.youtube.com/watch?v=tu-Qe66AvtY
105
- - easings.net — easing function reference with formulas & graphs: https://easings.net/
106
- - Robert Penner's easing equations (origin of the standard easings): http://robertpenner.com/easing/
107
- - GSAP docs (tweening/easing/timelines): https://gsap.com/docs/v3/ ; tween.js: https://github.com/tweenjs/tween.js
108
- - Disney's 12 principles of animation (squash & stretch, anticipation, follow-through): https://en.wikipedia.org/wiki/Twelve_basic_principles_of_animation
109
- - MDN — `prefers-reduced-motion`: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion
110
- - "The Juice Factor" / GDC Vault talks on feedback & game feel.