rn-gamekit 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (601) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/README.md +97 -16
  3. package/lib/module/assets/defineAssets.js +28 -3
  4. package/lib/module/assets/defineAssets.js.map +1 -1
  5. package/lib/module/assets.js +11 -0
  6. package/lib/module/assets.js.map +1 -0
  7. package/lib/module/audio/createGameAudio.js +784 -0
  8. package/lib/module/audio/createGameAudio.js.map +1 -0
  9. package/lib/module/audio/errors.js +12 -0
  10. package/lib/module/audio/errors.js.map +1 -0
  11. package/lib/module/audio/index.js +5 -0
  12. package/lib/module/audio/index.js.map +1 -0
  13. package/lib/module/audio/resolver.js +37 -0
  14. package/lib/module/audio/resolver.js.map +1 -0
  15. package/lib/module/audio/types.js +4 -0
  16. package/lib/module/audio/types.js.map +1 -0
  17. package/lib/module/audio.js +9 -0
  18. package/lib/module/audio.js.map +1 -0
  19. package/lib/module/camera2d/bounds.js +59 -0
  20. package/lib/module/camera2d/bounds.js.map +1 -0
  21. package/lib/module/camera2d/extents.js +25 -0
  22. package/lib/module/camera2d/extents.js.map +1 -0
  23. package/lib/module/camera2d/follow.js +138 -0
  24. package/lib/module/camera2d/follow.js.map +1 -0
  25. package/lib/module/camera2d/index.js +20 -0
  26. package/lib/module/camera2d/index.js.map +1 -0
  27. package/lib/module/camera2d/interpolation.js +98 -0
  28. package/lib/module/camera2d/interpolation.js.map +1 -0
  29. package/lib/module/camera2d/shake.js +85 -0
  30. package/lib/module/camera2d/shake.js.map +1 -0
  31. package/lib/module/camera2d/transform.js +151 -0
  32. package/lib/module/camera2d/transform.js.map +1 -0
  33. package/lib/module/camera2d/types.js +4 -0
  34. package/lib/module/camera2d/types.js.map +1 -0
  35. package/lib/module/camera2d/validation.js +98 -0
  36. package/lib/module/camera2d/validation.js.map +1 -0
  37. package/lib/module/camera2d/visibility.js +138 -0
  38. package/lib/module/camera2d/visibility.js.map +1 -0
  39. package/lib/module/camera2d.js +9 -0
  40. package/lib/module/camera2d.js.map +1 -0
  41. package/lib/module/collision2d/colliders.js +266 -0
  42. package/lib/module/collision2d/colliders.js.map +1 -0
  43. package/lib/module/collision2d/debug.js +105 -0
  44. package/lib/module/collision2d/debug.js.map +1 -0
  45. package/lib/module/collision2d/filters.js +40 -0
  46. package/lib/module/collision2d/filters.js.map +1 -0
  47. package/lib/module/collision2d/index.js +12 -0
  48. package/lib/module/collision2d/index.js.map +1 -0
  49. package/lib/module/collision2d/intersections.js +67 -0
  50. package/lib/module/collision2d/intersections.js.map +1 -0
  51. package/lib/module/collision2d/manifolds.js +218 -0
  52. package/lib/module/collision2d/manifolds.js.map +1 -0
  53. package/lib/module/collision2d/segments.js +187 -0
  54. package/lib/module/collision2d/segments.js.map +1 -0
  55. package/lib/module/collision2d/spatialHash.js +167 -0
  56. package/lib/module/collision2d/spatialHash.js.map +1 -0
  57. package/lib/module/collision2d/sweeps.js +255 -0
  58. package/lib/module/collision2d/sweeps.js.map +1 -0
  59. package/lib/module/collision2d.js +9 -0
  60. package/lib/module/collision2d.js.map +1 -0
  61. package/lib/module/core/input/buttonPad.js +214 -0
  62. package/lib/module/core/input/buttonPad.js.map +1 -0
  63. package/lib/module/core/input/createInputBuffer.js +66 -14
  64. package/lib/module/core/input/createInputBuffer.js.map +1 -1
  65. package/lib/module/core/session/createGameSession.js +454 -50
  66. package/lib/module/core/session/createGameSession.js.map +1 -1
  67. package/lib/module/core/session/deepFreeze.js +92 -2
  68. package/lib/module/core/session/deepFreeze.js.map +1 -1
  69. package/lib/module/core/session/types.js +12 -0
  70. package/lib/module/core/session/types.js.map +1 -1
  71. package/lib/module/definition/defineGame.js +23 -0
  72. package/lib/module/definition/defineGame.js.map +1 -1
  73. package/lib/module/events/defineGameEvents.js +46 -0
  74. package/lib/module/events/defineGameEvents.js.map +1 -0
  75. package/lib/module/events/errors.js +16 -0
  76. package/lib/module/events/errors.js.map +1 -0
  77. package/lib/module/events/index.js +7 -0
  78. package/lib/module/events/index.js.map +1 -0
  79. package/lib/module/events/payload.js +219 -0
  80. package/lib/module/events/payload.js.map +1 -0
  81. package/lib/module/events/seed.js +33 -0
  82. package/lib/module/events/seed.js.map +1 -0
  83. package/lib/module/events/types.js +4 -0
  84. package/lib/module/events/types.js.map +1 -0
  85. package/lib/module/events.js +13 -0
  86. package/lib/module/events.js.map +1 -0
  87. package/lib/module/geometry/helpers.js +140 -0
  88. package/lib/module/geometry/helpers.js.map +1 -0
  89. package/lib/module/geometry/index.js +5 -0
  90. package/lib/module/geometry/index.js.map +1 -0
  91. package/lib/module/geometry/validation.js +104 -0
  92. package/lib/module/geometry/validation.js.map +1 -0
  93. package/lib/module/geometry.js +9 -0
  94. package/lib/module/geometry.js.map +1 -0
  95. package/lib/module/haptics/createGameHaptics.js +214 -0
  96. package/lib/module/haptics/createGameHaptics.js.map +1 -0
  97. package/lib/module/haptics/errors.js +12 -0
  98. package/lib/module/haptics/errors.js.map +1 -0
  99. package/lib/module/haptics/index.js +5 -0
  100. package/lib/module/haptics/index.js.map +1 -0
  101. package/lib/module/haptics/resolver.js +37 -0
  102. package/lib/module/haptics/resolver.js.map +1 -0
  103. package/lib/module/haptics/types.js +4 -0
  104. package/lib/module/haptics/types.js.map +1 -0
  105. package/lib/module/haptics.js +9 -0
  106. package/lib/module/haptics.js.map +1 -0
  107. package/lib/module/index.js +8 -1
  108. package/lib/module/index.js.map +1 -1
  109. package/lib/module/particles/createParticleSystem.js +481 -0
  110. package/lib/module/particles/createParticleSystem.js.map +1 -0
  111. package/lib/module/particles/defineParticleEffect.js +178 -0
  112. package/lib/module/particles/defineParticleEffect.js.map +1 -0
  113. package/lib/module/particles/errors.js +9 -0
  114. package/lib/module/particles/errors.js.map +1 -0
  115. package/lib/module/particles/index.js +8 -0
  116. package/lib/module/particles/index.js.map +1 -0
  117. package/lib/module/particles/sampling.js +121 -0
  118. package/lib/module/particles/sampling.js.map +1 -0
  119. package/lib/module/particles/types.js +4 -0
  120. package/lib/module/particles/types.js.map +1 -0
  121. package/lib/module/particles.js +4 -0
  122. package/lib/module/particles.js.map +1 -0
  123. package/lib/module/react/GameButtonPad.js +344 -0
  124. package/lib/module/react/GameButtonPad.js.map +1 -0
  125. package/lib/module/react/GamePointerInput.js +74 -16
  126. package/lib/module/react/GamePointerInput.js.map +1 -1
  127. package/lib/module/react/GameView.js +139 -60
  128. package/lib/module/react/GameView.js.map +1 -1
  129. package/lib/module/react/assets/createGameAssetStore.js +145 -95
  130. package/lib/module/react/assets/createGameAssetStore.js.map +1 -1
  131. package/lib/module/react/assets/useGameAssets.js +60 -35
  132. package/lib/module/react/assets/useGameAssets.js.map +1 -1
  133. package/lib/module/react/bindAppLifecycle.js +46 -17
  134. package/lib/module/react/bindAppLifecycle.js.map +1 -1
  135. package/lib/module/react/bindGameSession.js +13 -2
  136. package/lib/module/react/bindGameSession.js.map +1 -1
  137. package/lib/module/react/camera2d/GameLayer2D.js +50 -0
  138. package/lib/module/react/camera2d/GameLayer2D.js.map +1 -0
  139. package/lib/module/react/camera2d/defineGameCamera2D.js +30 -0
  140. package/lib/module/react/camera2d/defineGameCamera2D.js.map +1 -0
  141. package/lib/module/react/camera2d/usePresentedCameraBinding.js +177 -0
  142. package/lib/module/react/camera2d/usePresentedCameraBinding.js.map +1 -0
  143. package/lib/module/react/cleanupList.js +38 -0
  144. package/lib/module/react/cleanupList.js.map +1 -0
  145. package/lib/module/react/lifecycleSource.js +49 -0
  146. package/lib/module/react/lifecycleSource.js.map +1 -0
  147. package/lib/module/react/particles/ParticleView.js +308 -0
  148. package/lib/module/react/particles/ParticleView.js.map +1 -0
  149. package/lib/module/react/particles/culling.js +115 -0
  150. package/lib/module/react/particles/culling.js.map +1 -0
  151. package/lib/module/react/particles/index.js +7 -0
  152. package/lib/module/react/particles/index.js.map +1 -0
  153. package/lib/module/react/particles/spriteXForm.js +45 -0
  154. package/lib/module/react/particles/spriteXForm.js.map +1 -0
  155. package/lib/module/react/particles/useParticlePresentation.js +204 -0
  156. package/lib/module/react/particles/useParticlePresentation.js.map +1 -0
  157. package/lib/module/react/pointerBinding.js +55 -17
  158. package/lib/module/react/pointerBinding.js.map +1 -1
  159. package/lib/module/react/pointerCamera.js +28 -0
  160. package/lib/module/react/pointerCamera.js.map +1 -0
  161. package/lib/module/react/pointerCoalescer.js +16 -9
  162. package/lib/module/react/pointerCoalescer.js.map +1 -1
  163. package/lib/module/react/sprites/GameSprite.js +5 -17
  164. package/lib/module/react/sprites/GameSprite.js.map +1 -1
  165. package/lib/module/react/sprites/GameWorld2D.js +112 -9
  166. package/lib/module/react/sprites/GameWorld2D.js.map +1 -1
  167. package/lib/module/react/sprites/Sprite.js +48 -63
  168. package/lib/module/react/sprites/Sprite.js.map +1 -1
  169. package/lib/module/react/sprites/SpriteBatch.js +53 -28
  170. package/lib/module/react/sprites/SpriteBatch.js.map +1 -1
  171. package/lib/module/react/sprites/batchVisibility.js +58 -0
  172. package/lib/module/react/sprites/batchVisibility.js.map +1 -0
  173. package/lib/module/react/sprites/spriteSelection.js +103 -0
  174. package/lib/module/react/sprites/spriteSelection.js.map +1 -0
  175. package/lib/module/react/sprites/spriteTransform.js +46 -25
  176. package/lib/module/react/sprites/spriteTransform.js.map +1 -1
  177. package/lib/module/react/tilemap/TileMapLayer2D.js +217 -0
  178. package/lib/module/react/tilemap/TileMapLayer2D.js.map +1 -0
  179. package/lib/module/react/tilemap/tilePresentation.js +374 -0
  180. package/lib/module/react/tilemap/tilePresentation.js.map +1 -0
  181. package/lib/module/react/useGameSession.js +70 -0
  182. package/lib/module/react/useGameSession.js.map +1 -0
  183. package/lib/module/react/useGameSessionStatus.js +46 -0
  184. package/lib/module/react/useGameSessionStatus.js.map +1 -0
  185. package/lib/module/react/viewportBinding.js +5 -1
  186. package/lib/module/react/viewportBinding.js.map +1 -1
  187. package/lib/module/react.js +12 -1
  188. package/lib/module/react.js.map +1 -1
  189. package/lib/module/scene/defineScene.js +17 -0
  190. package/lib/module/scene/defineScene.js.map +1 -1
  191. package/lib/module/sprites/sampleSpriteClip.js +66 -6
  192. package/lib/module/sprites/sampleSpriteClip.js.map +1 -1
  193. package/lib/module/sprites/spriteAnimationState.js +10 -20
  194. package/lib/module/sprites/spriteAnimationState.js.map +1 -1
  195. package/lib/module/sprites.js +11 -0
  196. package/lib/module/sprites.js.map +1 -0
  197. package/lib/module/storage/adapters/asyncStorage.js +57 -0
  198. package/lib/module/storage/adapters/asyncStorage.js.map +1 -0
  199. package/lib/module/storage/adapters/memory.js +50 -0
  200. package/lib/module/storage/adapters/memory.js.map +1 -0
  201. package/lib/module/storage/errors.js +34 -0
  202. package/lib/module/storage/errors.js.map +1 -0
  203. package/lib/module/storage/index.js +11 -0
  204. package/lib/module/storage/index.js.map +1 -0
  205. package/lib/module/storage/schema.js +151 -0
  206. package/lib/module/storage/schema.js.map +1 -0
  207. package/lib/module/storage/serialization.js +249 -0
  208. package/lib/module/storage/serialization.js.map +1 -0
  209. package/lib/module/storage/store.js +387 -0
  210. package/lib/module/storage/store.js.map +1 -0
  211. package/lib/module/storage/types.js +16 -0
  212. package/lib/module/storage/types.js.map +1 -0
  213. package/lib/module/storage/validation.js +111 -0
  214. package/lib/module/storage/validation.js.map +1 -0
  215. package/lib/module/storage.js +4 -0
  216. package/lib/module/storage.js.map +1 -0
  217. package/lib/module/testing.js +4 -0
  218. package/lib/module/testing.js.map +1 -1
  219. package/lib/module/tilemap/chunkStats.js +27 -0
  220. package/lib/module/tilemap/chunkStats.js.map +1 -0
  221. package/lib/module/tilemap/definitions.js +308 -0
  222. package/lib/module/tilemap/definitions.js.map +1 -0
  223. package/lib/module/tilemap/errors.js +13 -0
  224. package/lib/module/tilemap/errors.js.map +1 -0
  225. package/lib/module/tilemap/index.js +10 -0
  226. package/lib/module/tilemap/index.js.map +1 -0
  227. package/lib/module/tilemap/movement.js +379 -0
  228. package/lib/module/tilemap/movement.js.map +1 -0
  229. package/lib/module/tilemap/queries.js +114 -0
  230. package/lib/module/tilemap/queries.js.map +1 -0
  231. package/lib/module/tilemap/tiledAdapter.js +141 -0
  232. package/lib/module/tilemap/tiledAdapter.js.map +1 -0
  233. package/lib/module/tilemap/types.js +4 -0
  234. package/lib/module/tilemap/types.js.map +1 -0
  235. package/lib/module/tilemap.js +4 -0
  236. package/lib/module/tilemap.js.map +1 -0
  237. package/lib/typescript/src/assets/defineAssets.d.ts +1 -1
  238. package/lib/typescript/src/assets/defineAssets.d.ts.map +1 -1
  239. package/lib/typescript/src/assets.d.ts +11 -0
  240. package/lib/typescript/src/assets.d.ts.map +1 -0
  241. package/lib/typescript/src/audio/createGameAudio.d.ts +5 -0
  242. package/lib/typescript/src/audio/createGameAudio.d.ts.map +1 -0
  243. package/lib/typescript/src/audio/errors.d.ts +6 -0
  244. package/lib/typescript/src/audio/errors.d.ts.map +1 -0
  245. package/lib/typescript/src/audio/index.d.ts +4 -0
  246. package/lib/typescript/src/audio/index.d.ts.map +1 -0
  247. package/lib/typescript/src/audio/resolver.d.ts +44 -0
  248. package/lib/typescript/src/audio/resolver.d.ts.map +1 -0
  249. package/lib/typescript/src/audio/types.d.ts +42 -0
  250. package/lib/typescript/src/audio/types.d.ts.map +1 -0
  251. package/lib/typescript/src/audio.d.ts +8 -0
  252. package/lib/typescript/src/audio.d.ts.map +1 -0
  253. package/lib/typescript/src/camera2d/bounds.d.ts +25 -0
  254. package/lib/typescript/src/camera2d/bounds.d.ts.map +1 -0
  255. package/lib/typescript/src/camera2d/extents.d.ts +17 -0
  256. package/lib/typescript/src/camera2d/extents.d.ts.map +1 -0
  257. package/lib/typescript/src/camera2d/follow.d.ts +24 -0
  258. package/lib/typescript/src/camera2d/follow.d.ts.map +1 -0
  259. package/lib/typescript/src/camera2d/index.d.ts +19 -0
  260. package/lib/typescript/src/camera2d/index.d.ts.map +1 -0
  261. package/lib/typescript/src/camera2d/interpolation.d.ts +17 -0
  262. package/lib/typescript/src/camera2d/interpolation.d.ts.map +1 -0
  263. package/lib/typescript/src/camera2d/shake.d.ts +20 -0
  264. package/lib/typescript/src/camera2d/shake.d.ts.map +1 -0
  265. package/lib/typescript/src/camera2d/transform.d.ts +44 -0
  266. package/lib/typescript/src/camera2d/transform.d.ts.map +1 -0
  267. package/lib/typescript/src/camera2d/types.d.ts +74 -0
  268. package/lib/typescript/src/camera2d/types.d.ts.map +1 -0
  269. package/lib/typescript/src/camera2d/validation.d.ts +30 -0
  270. package/lib/typescript/src/camera2d/validation.d.ts.map +1 -0
  271. package/lib/typescript/src/camera2d/visibility.d.ts +47 -0
  272. package/lib/typescript/src/camera2d/visibility.d.ts.map +1 -0
  273. package/lib/typescript/src/camera2d.d.ts +7 -0
  274. package/lib/typescript/src/camera2d.d.ts.map +1 -0
  275. package/lib/typescript/src/collision2d/colliders.d.ts +120 -0
  276. package/lib/typescript/src/collision2d/colliders.d.ts.map +1 -0
  277. package/lib/typescript/src/collision2d/debug.d.ts +67 -0
  278. package/lib/typescript/src/collision2d/debug.d.ts.map +1 -0
  279. package/lib/typescript/src/collision2d/filters.d.ts +28 -0
  280. package/lib/typescript/src/collision2d/filters.d.ts.map +1 -0
  281. package/lib/typescript/src/collision2d/index.d.ts +17 -0
  282. package/lib/typescript/src/collision2d/index.d.ts.map +1 -0
  283. package/lib/typescript/src/collision2d/intersections.d.ts +24 -0
  284. package/lib/typescript/src/collision2d/intersections.d.ts.map +1 -0
  285. package/lib/typescript/src/collision2d/manifolds.d.ts +39 -0
  286. package/lib/typescript/src/collision2d/manifolds.d.ts.map +1 -0
  287. package/lib/typescript/src/collision2d/segments.d.ts +24 -0
  288. package/lib/typescript/src/collision2d/segments.d.ts.map +1 -0
  289. package/lib/typescript/src/collision2d/spatialHash.d.ts +50 -0
  290. package/lib/typescript/src/collision2d/spatialHash.d.ts.map +1 -0
  291. package/lib/typescript/src/collision2d/sweeps.d.ts +60 -0
  292. package/lib/typescript/src/collision2d/sweeps.d.ts.map +1 -0
  293. package/lib/typescript/src/collision2d.d.ts +7 -0
  294. package/lib/typescript/src/collision2d.d.ts.map +1 -0
  295. package/lib/typescript/src/core/input/buttonPad.d.ts +59 -0
  296. package/lib/typescript/src/core/input/buttonPad.d.ts.map +1 -0
  297. package/lib/typescript/src/core/input/createInputBuffer.d.ts +1 -1
  298. package/lib/typescript/src/core/input/createInputBuffer.d.ts.map +1 -1
  299. package/lib/typescript/src/core/input/types.d.ts +7 -0
  300. package/lib/typescript/src/core/input/types.d.ts.map +1 -1
  301. package/lib/typescript/src/core/session/createGameSession.d.ts +4 -2
  302. package/lib/typescript/src/core/session/createGameSession.d.ts.map +1 -1
  303. package/lib/typescript/src/core/session/deepFreeze.d.ts +21 -1
  304. package/lib/typescript/src/core/session/deepFreeze.d.ts.map +1 -1
  305. package/lib/typescript/src/core/session/diagnostics.d.ts +2 -0
  306. package/lib/typescript/src/core/session/diagnostics.d.ts.map +1 -1
  307. package/lib/typescript/src/core/session/types.d.ts +69 -4
  308. package/lib/typescript/src/core/session/types.d.ts.map +1 -1
  309. package/lib/typescript/src/definition/defineGame.d.ts +12 -1
  310. package/lib/typescript/src/definition/defineGame.d.ts.map +1 -1
  311. package/lib/typescript/src/definition/types.d.ts +10 -1
  312. package/lib/typescript/src/definition/types.d.ts.map +1 -1
  313. package/lib/typescript/src/events/defineGameEvents.d.ts +26 -0
  314. package/lib/typescript/src/events/defineGameEvents.d.ts.map +1 -0
  315. package/lib/typescript/src/events/errors.d.ts +12 -0
  316. package/lib/typescript/src/events/errors.d.ts.map +1 -0
  317. package/lib/typescript/src/events/index.d.ts +6 -0
  318. package/lib/typescript/src/events/index.d.ts.map +1 -0
  319. package/lib/typescript/src/events/payload.d.ts +21 -0
  320. package/lib/typescript/src/events/payload.d.ts.map +1 -0
  321. package/lib/typescript/src/events/seed.d.ts +3 -0
  322. package/lib/typescript/src/events/seed.d.ts.map +1 -0
  323. package/lib/typescript/src/events/types.d.ts +42 -0
  324. package/lib/typescript/src/events/types.d.ts.map +1 -0
  325. package/lib/typescript/src/events.d.ts +12 -0
  326. package/lib/typescript/src/events.d.ts.map +1 -0
  327. package/lib/typescript/src/geometry/helpers.d.ts +35 -0
  328. package/lib/typescript/src/geometry/helpers.d.ts.map +1 -0
  329. package/lib/typescript/src/geometry/index.d.ts +4 -0
  330. package/lib/typescript/src/geometry/index.d.ts.map +1 -0
  331. package/lib/typescript/src/geometry/types.d.ts +49 -0
  332. package/lib/typescript/src/geometry/types.d.ts.map +1 -1
  333. package/lib/typescript/src/geometry/validation.d.ts +44 -0
  334. package/lib/typescript/src/geometry/validation.d.ts.map +1 -0
  335. package/lib/typescript/src/geometry.d.ts +7 -0
  336. package/lib/typescript/src/geometry.d.ts.map +1 -0
  337. package/lib/typescript/src/haptics/createGameHaptics.d.ts +3 -0
  338. package/lib/typescript/src/haptics/createGameHaptics.d.ts.map +1 -0
  339. package/lib/typescript/src/haptics/errors.d.ts +6 -0
  340. package/lib/typescript/src/haptics/errors.d.ts.map +1 -0
  341. package/lib/typescript/src/haptics/index.d.ts +4 -0
  342. package/lib/typescript/src/haptics/index.d.ts.map +1 -0
  343. package/lib/typescript/src/haptics/resolver.d.ts +22 -0
  344. package/lib/typescript/src/haptics/resolver.d.ts.map +1 -0
  345. package/lib/typescript/src/haptics/types.d.ts +37 -0
  346. package/lib/typescript/src/haptics/types.d.ts.map +1 -0
  347. package/lib/typescript/src/haptics.d.ts +8 -0
  348. package/lib/typescript/src/haptics.d.ts.map +1 -0
  349. package/lib/typescript/src/index.d.ts +10 -2
  350. package/lib/typescript/src/index.d.ts.map +1 -1
  351. package/lib/typescript/src/particles/createParticleSystem.d.ts +5 -0
  352. package/lib/typescript/src/particles/createParticleSystem.d.ts.map +1 -0
  353. package/lib/typescript/src/particles/defineParticleEffect.d.ts +3 -0
  354. package/lib/typescript/src/particles/defineParticleEffect.d.ts.map +1 -0
  355. package/lib/typescript/src/particles/errors.d.ts +5 -0
  356. package/lib/typescript/src/particles/errors.d.ts.map +1 -0
  357. package/lib/typescript/src/particles/index.d.ts +6 -0
  358. package/lib/typescript/src/particles/index.d.ts.map +1 -0
  359. package/lib/typescript/src/particles/sampling.d.ts +54 -0
  360. package/lib/typescript/src/particles/sampling.d.ts.map +1 -0
  361. package/lib/typescript/src/particles/types.d.ts +292 -0
  362. package/lib/typescript/src/particles/types.d.ts.map +1 -0
  363. package/lib/typescript/src/particles.d.ts +2 -0
  364. package/lib/typescript/src/particles.d.ts.map +1 -0
  365. package/lib/typescript/src/react/GameButtonPad.d.ts +84 -0
  366. package/lib/typescript/src/react/GameButtonPad.d.ts.map +1 -0
  367. package/lib/typescript/src/react/GamePointerInput.d.ts.map +1 -1
  368. package/lib/typescript/src/react/GameView.d.ts +27 -1
  369. package/lib/typescript/src/react/GameView.d.ts.map +1 -1
  370. package/lib/typescript/src/react/assets/createGameAssetStore.d.ts.map +1 -1
  371. package/lib/typescript/src/react/assets/useGameAssets.d.ts.map +1 -1
  372. package/lib/typescript/src/react/bindAppLifecycle.d.ts +7 -1
  373. package/lib/typescript/src/react/bindAppLifecycle.d.ts.map +1 -1
  374. package/lib/typescript/src/react/bindGameSession.d.ts.map +1 -1
  375. package/lib/typescript/src/react/camera2d/GameLayer2D.d.ts +24 -0
  376. package/lib/typescript/src/react/camera2d/GameLayer2D.d.ts.map +1 -0
  377. package/lib/typescript/src/react/camera2d/defineGameCamera2D.d.ts +44 -0
  378. package/lib/typescript/src/react/camera2d/defineGameCamera2D.d.ts.map +1 -0
  379. package/lib/typescript/src/react/camera2d/usePresentedCameraBinding.d.ts +22 -0
  380. package/lib/typescript/src/react/camera2d/usePresentedCameraBinding.d.ts.map +1 -0
  381. package/lib/typescript/src/react/cleanupList.d.ts +21 -0
  382. package/lib/typescript/src/react/cleanupList.d.ts.map +1 -0
  383. package/lib/typescript/src/react/instrumentation.d.ts +33 -3
  384. package/lib/typescript/src/react/instrumentation.d.ts.map +1 -1
  385. package/lib/typescript/src/react/lifecycleSource.d.ts +21 -0
  386. package/lib/typescript/src/react/lifecycleSource.d.ts.map +1 -0
  387. package/lib/typescript/src/react/particles/ParticleView.d.ts +65 -0
  388. package/lib/typescript/src/react/particles/ParticleView.d.ts.map +1 -0
  389. package/lib/typescript/src/react/particles/culling.d.ts +70 -0
  390. package/lib/typescript/src/react/particles/culling.d.ts.map +1 -0
  391. package/lib/typescript/src/react/particles/index.d.ts +7 -0
  392. package/lib/typescript/src/react/particles/index.d.ts.map +1 -0
  393. package/lib/typescript/src/react/particles/spriteXForm.d.ts +28 -0
  394. package/lib/typescript/src/react/particles/spriteXForm.d.ts.map +1 -0
  395. package/lib/typescript/src/react/particles/useParticlePresentation.d.ts +48 -0
  396. package/lib/typescript/src/react/particles/useParticlePresentation.d.ts.map +1 -0
  397. package/lib/typescript/src/react/pointerBinding.d.ts +38 -8
  398. package/lib/typescript/src/react/pointerBinding.d.ts.map +1 -1
  399. package/lib/typescript/src/react/pointerCamera.d.ts +20 -0
  400. package/lib/typescript/src/react/pointerCamera.d.ts.map +1 -0
  401. package/lib/typescript/src/react/pointerCoalescer.d.ts +17 -1
  402. package/lib/typescript/src/react/pointerCoalescer.d.ts.map +1 -1
  403. package/lib/typescript/src/react/sprites/GameSprite.d.ts +3 -10
  404. package/lib/typescript/src/react/sprites/GameSprite.d.ts.map +1 -1
  405. package/lib/typescript/src/react/sprites/GameWorld2D.d.ts +51 -6
  406. package/lib/typescript/src/react/sprites/GameWorld2D.d.ts.map +1 -1
  407. package/lib/typescript/src/react/sprites/Sprite.d.ts.map +1 -1
  408. package/lib/typescript/src/react/sprites/SpriteBatch.d.ts +22 -1
  409. package/lib/typescript/src/react/sprites/SpriteBatch.d.ts.map +1 -1
  410. package/lib/typescript/src/react/sprites/batchVisibility.d.ts +28 -0
  411. package/lib/typescript/src/react/sprites/batchVisibility.d.ts.map +1 -0
  412. package/lib/typescript/src/react/sprites/spriteSelection.d.ts +58 -0
  413. package/lib/typescript/src/react/sprites/spriteSelection.d.ts.map +1 -0
  414. package/lib/typescript/src/react/sprites/spriteTransform.d.ts +27 -12
  415. package/lib/typescript/src/react/sprites/spriteTransform.d.ts.map +1 -1
  416. package/lib/typescript/src/react/tilemap/TileMapLayer2D.d.ts +69 -0
  417. package/lib/typescript/src/react/tilemap/TileMapLayer2D.d.ts.map +1 -0
  418. package/lib/typescript/src/react/tilemap/tilePresentation.d.ts +217 -0
  419. package/lib/typescript/src/react/tilemap/tilePresentation.d.ts.map +1 -0
  420. package/lib/typescript/src/react/useGameSession.d.ts +48 -0
  421. package/lib/typescript/src/react/useGameSession.d.ts.map +1 -0
  422. package/lib/typescript/src/react/useGameSessionStatus.d.ts +23 -0
  423. package/lib/typescript/src/react/useGameSessionStatus.d.ts.map +1 -0
  424. package/lib/typescript/src/react/viewportBinding.d.ts +5 -1
  425. package/lib/typescript/src/react/viewportBinding.d.ts.map +1 -1
  426. package/lib/typescript/src/react.d.ts +18 -1
  427. package/lib/typescript/src/react.d.ts.map +1 -1
  428. package/lib/typescript/src/scene/defineScene.d.ts +22 -2
  429. package/lib/typescript/src/scene/defineScene.d.ts.map +1 -1
  430. package/lib/typescript/src/scene/types.d.ts +24 -4
  431. package/lib/typescript/src/scene/types.d.ts.map +1 -1
  432. package/lib/typescript/src/sprites/sampleSpriteClip.d.ts +26 -2
  433. package/lib/typescript/src/sprites/sampleSpriteClip.d.ts.map +1 -1
  434. package/lib/typescript/src/sprites/spriteAnimationState.d.ts +6 -7
  435. package/lib/typescript/src/sprites/spriteAnimationState.d.ts.map +1 -1
  436. package/lib/typescript/src/sprites.d.ts +10 -0
  437. package/lib/typescript/src/sprites.d.ts.map +1 -0
  438. package/lib/typescript/src/storage/adapters/asyncStorage.d.ts +18 -0
  439. package/lib/typescript/src/storage/adapters/asyncStorage.d.ts.map +1 -0
  440. package/lib/typescript/src/storage/adapters/memory.d.ts +16 -0
  441. package/lib/typescript/src/storage/adapters/memory.d.ts.map +1 -0
  442. package/lib/typescript/src/storage/errors.d.ts +37 -0
  443. package/lib/typescript/src/storage/errors.d.ts.map +1 -0
  444. package/lib/typescript/src/storage/index.d.ts +11 -0
  445. package/lib/typescript/src/storage/index.d.ts.map +1 -0
  446. package/lib/typescript/src/storage/schema.d.ts +22 -0
  447. package/lib/typescript/src/storage/schema.d.ts.map +1 -0
  448. package/lib/typescript/src/storage/serialization.d.ts +23 -0
  449. package/lib/typescript/src/storage/serialization.d.ts.map +1 -0
  450. package/lib/typescript/src/storage/store.d.ts +3 -0
  451. package/lib/typescript/src/storage/store.d.ts.map +1 -0
  452. package/lib/typescript/src/storage/types.d.ts +69 -0
  453. package/lib/typescript/src/storage/types.d.ts.map +1 -0
  454. package/lib/typescript/src/storage/validation.d.ts +24 -0
  455. package/lib/typescript/src/storage/validation.d.ts.map +1 -0
  456. package/lib/typescript/src/storage.d.ts +2 -0
  457. package/lib/typescript/src/storage.d.ts.map +1 -0
  458. package/lib/typescript/src/testing.d.ts +1 -0
  459. package/lib/typescript/src/testing.d.ts.map +1 -1
  460. package/lib/typescript/src/tilemap/chunkStats.d.ts +14 -0
  461. package/lib/typescript/src/tilemap/chunkStats.d.ts.map +1 -0
  462. package/lib/typescript/src/tilemap/definitions.d.ts +38 -0
  463. package/lib/typescript/src/tilemap/definitions.d.ts.map +1 -0
  464. package/lib/typescript/src/tilemap/errors.d.ts +7 -0
  465. package/lib/typescript/src/tilemap/errors.d.ts.map +1 -0
  466. package/lib/typescript/src/tilemap/index.d.ts +8 -0
  467. package/lib/typescript/src/tilemap/index.d.ts.map +1 -0
  468. package/lib/typescript/src/tilemap/movement.d.ts +52 -0
  469. package/lib/typescript/src/tilemap/movement.d.ts.map +1 -0
  470. package/lib/typescript/src/tilemap/queries.d.ts +21 -0
  471. package/lib/typescript/src/tilemap/queries.d.ts.map +1 -0
  472. package/lib/typescript/src/tilemap/tiledAdapter.d.ts +32 -0
  473. package/lib/typescript/src/tilemap/tiledAdapter.d.ts.map +1 -0
  474. package/lib/typescript/src/tilemap/types.d.ts +127 -0
  475. package/lib/typescript/src/tilemap/types.d.ts.map +1 -0
  476. package/lib/typescript/src/tilemap.d.ts +2 -0
  477. package/lib/typescript/src/tilemap.d.ts.map +1 -0
  478. package/package.json +100 -10
  479. package/src/assets/defineAssets.ts +31 -5
  480. package/src/assets.ts +27 -0
  481. package/src/audio/createGameAudio.ts +749 -0
  482. package/src/audio/errors.ts +12 -0
  483. package/src/audio/index.ts +9 -0
  484. package/src/audio/resolver.ts +74 -0
  485. package/src/audio/types.ts +47 -0
  486. package/src/audio.ts +13 -0
  487. package/src/camera2d/bounds.ts +69 -0
  488. package/src/camera2d/extents.ts +25 -0
  489. package/src/camera2d/follow.ts +165 -0
  490. package/src/camera2d/index.ts +29 -0
  491. package/src/camera2d/interpolation.ts +113 -0
  492. package/src/camera2d/shake.ts +90 -0
  493. package/src/camera2d/transform.ts +148 -0
  494. package/src/camera2d/types.ts +73 -0
  495. package/src/camera2d/validation.ts +126 -0
  496. package/src/camera2d/visibility.ts +181 -0
  497. package/src/camera2d.ts +6 -0
  498. package/src/collision2d/colliders.ts +292 -0
  499. package/src/collision2d/debug.ts +133 -0
  500. package/src/collision2d/filters.ts +48 -0
  501. package/src/collision2d/index.ts +74 -0
  502. package/src/collision2d/intersections.ts +82 -0
  503. package/src/collision2d/manifolds.ts +191 -0
  504. package/src/collision2d/segments.ts +176 -0
  505. package/src/collision2d/spatialHash.ts +211 -0
  506. package/src/collision2d/sweeps.ts +269 -0
  507. package/src/collision2d.ts +6 -0
  508. package/src/core/input/buttonPad.ts +235 -0
  509. package/src/core/input/createInputBuffer.ts +95 -14
  510. package/src/core/input/types.ts +7 -0
  511. package/src/core/session/createGameSession.ts +480 -53
  512. package/src/core/session/deepFreeze.ts +104 -3
  513. package/src/core/session/diagnostics.ts +2 -0
  514. package/src/core/session/types.ts +77 -4
  515. package/src/definition/defineGame.ts +61 -3
  516. package/src/definition/types.ts +10 -0
  517. package/src/events/defineGameEvents.ts +46 -0
  518. package/src/events/errors.ts +14 -0
  519. package/src/events/index.ts +14 -0
  520. package/src/events/payload.ts +234 -0
  521. package/src/events/seed.ts +33 -0
  522. package/src/events/types.ts +53 -0
  523. package/src/events.ts +20 -0
  524. package/src/geometry/helpers.ts +136 -0
  525. package/src/geometry/index.ts +14 -0
  526. package/src/geometry/types.ts +54 -0
  527. package/src/geometry/validation.ts +131 -0
  528. package/src/geometry.ts +6 -0
  529. package/src/haptics/createGameHaptics.ts +214 -0
  530. package/src/haptics/errors.ts +12 -0
  531. package/src/haptics/index.ts +3 -0
  532. package/src/haptics/resolver.ts +58 -0
  533. package/src/haptics/types.ts +48 -0
  534. package/src/haptics.ts +7 -0
  535. package/src/index.ts +37 -1
  536. package/src/particles/createParticleSystem.ts +505 -0
  537. package/src/particles/defineParticleEffect.ts +164 -0
  538. package/src/particles/errors.ts +6 -0
  539. package/src/particles/index.ts +5 -0
  540. package/src/particles/sampling.ts +141 -0
  541. package/src/particles/types.ts +327 -0
  542. package/src/particles.ts +1 -0
  543. package/src/react/GameButtonPad.tsx +436 -0
  544. package/src/react/GamePointerInput.tsx +73 -8
  545. package/src/react/GameView.tsx +160 -61
  546. package/src/react/assets/createGameAssetStore.ts +140 -107
  547. package/src/react/assets/useGameAssets.ts +63 -31
  548. package/src/react/bindAppLifecycle.ts +55 -19
  549. package/src/react/bindGameSession.ts +12 -2
  550. package/src/react/camera2d/GameLayer2D.tsx +43 -0
  551. package/src/react/camera2d/defineGameCamera2D.ts +59 -0
  552. package/src/react/camera2d/usePresentedCameraBinding.ts +185 -0
  553. package/src/react/cleanupList.ts +48 -0
  554. package/src/react/instrumentation.ts +31 -3
  555. package/src/react/lifecycleSource.ts +58 -0
  556. package/src/react/particles/ParticleView.tsx +358 -0
  557. package/src/react/particles/culling.ts +145 -0
  558. package/src/react/particles/index.ts +6 -0
  559. package/src/react/particles/spriteXForm.ts +72 -0
  560. package/src/react/particles/useParticlePresentation.ts +261 -0
  561. package/src/react/pointerBinding.ts +74 -16
  562. package/src/react/pointerCamera.ts +33 -0
  563. package/src/react/pointerCoalescer.ts +36 -10
  564. package/src/react/sprites/GameSprite.tsx +4 -33
  565. package/src/react/sprites/GameWorld2D.tsx +113 -7
  566. package/src/react/sprites/Sprite.tsx +51 -72
  567. package/src/react/sprites/SpriteBatch.tsx +74 -22
  568. package/src/react/sprites/batchVisibility.ts +76 -0
  569. package/src/react/sprites/spriteSelection.ts +133 -0
  570. package/src/react/sprites/spriteTransform.ts +46 -26
  571. package/src/react/tilemap/TileMapLayer2D.tsx +274 -0
  572. package/src/react/tilemap/tilePresentation.ts +491 -0
  573. package/src/react/useGameSession.ts +90 -0
  574. package/src/react/useGameSessionStatus.ts +53 -0
  575. package/src/react/viewportBinding.ts +5 -1
  576. package/src/react.ts +18 -1
  577. package/src/scene/defineScene.ts +47 -5
  578. package/src/scene/types.ts +37 -3
  579. package/src/sprites/sampleSpriteClip.ts +82 -14
  580. package/src/sprites/spriteAnimationState.ts +29 -25
  581. package/src/sprites.ts +22 -0
  582. package/src/storage/adapters/asyncStorage.ts +77 -0
  583. package/src/storage/adapters/memory.ts +58 -0
  584. package/src/storage/errors.ts +88 -0
  585. package/src/storage/index.ts +18 -0
  586. package/src/storage/schema.ts +147 -0
  587. package/src/storage/serialization.ts +248 -0
  588. package/src/storage/store.ts +380 -0
  589. package/src/storage/types.ts +76 -0
  590. package/src/storage/validation.ts +102 -0
  591. package/src/storage.ts +1 -0
  592. package/src/testing.ts +4 -0
  593. package/src/tilemap/chunkStats.ts +24 -0
  594. package/src/tilemap/definitions.ts +327 -0
  595. package/src/tilemap/errors.ts +11 -0
  596. package/src/tilemap/index.ts +10 -0
  597. package/src/tilemap/movement.ts +368 -0
  598. package/src/tilemap/queries.ts +136 -0
  599. package/src/tilemap/tiledAdapter.ts +165 -0
  600. package/src/tilemap/types.ts +119 -0
  601. package/src/tilemap.ts +1 -0
@@ -0,0 +1,12 @@
1
+ export class GameAudioError extends Error {
2
+ override name = 'GameAudioError';
3
+ constructor(message: string) {
4
+ super(message);
5
+ }
6
+ }
7
+
8
+ export function createAudioInstallationError(): GameAudioError {
9
+ return new GameAudioError(
10
+ 'react-native-audio-api is not installed. Run `npx expo install react-native-audio-api react-native-worklets` and rebuild with `npx expo prebuild` (or `expo run:ios` / `expo run:android`). See https://docs.swmansion.com/react-native-audio-api/docs/fundamentals/getting-started',
11
+ );
12
+ }
@@ -0,0 +1,9 @@
1
+ export { createGameAudio } from './createGameAudio';
2
+ export { GameAudioError } from './errors';
3
+ export type {
4
+ AudioCategory,
5
+ AudioSoundRecord,
6
+ CreateGameAudioOptions,
7
+ GameAudio,
8
+ GameAudioPlayOptions,
9
+ } from './types';
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Injectable resolver for the optional `react-native-audio-api` peer.
3
+ *
4
+ * Production code calls `loadAudioApi()` which does a dynamic `import()`.
5
+ * Tests inject a fake via `__setAudioApiLoader` to simulate a missing peer
6
+ * without relying on a production fallback object.
7
+ */
8
+ export type LoadedAudioApi = {
9
+ AudioContext: new (options?: { sampleRate?: number }) => {
10
+ readonly state: 'running' | 'suspended' | 'closed';
11
+ readonly currentTime: number;
12
+ readonly destination: unknown;
13
+ readonly sampleRate: number;
14
+ decodeAudioData(input: number | string | ArrayBuffer): Promise<{ length: number; duration: number } & Record<string, unknown>>;
15
+ createBufferSource(): {
16
+ buffer: unknown | null;
17
+ loop: boolean;
18
+ connect(destination: unknown): void;
19
+ start(when?: number, offset?: number, duration?: number): void;
20
+ stop(when?: number): void;
21
+ addEventListener?(type: string, cb: () => void): void;
22
+ };
23
+ createGain(): unknown;
24
+ suspend(): Promise<void>;
25
+ resume(): Promise<void>;
26
+ close(): Promise<void>;
27
+ };
28
+ AudioManager: {
29
+ getDevicePreferredSampleRate(): number;
30
+ addSystemEventListener(
31
+ name: 'interruption' | 'volumeChange' | 'duck' | 'routeChange',
32
+ cb: (event: unknown) => void,
33
+ ): { remove(): void; subscriptionId?: string };
34
+ observeAudioInterruptions(param: unknown): void;
35
+ } | undefined;
36
+ };
37
+
38
+ let loader: (() => Promise<LoadedAudioApi>) | null = null;
39
+
40
+ export function __setAudioApiLoader(fn: (() => Promise<LoadedAudioApi>) | null): void {
41
+ loader = fn;
42
+ }
43
+
44
+ export async function loadAudioApi(): Promise<LoadedAudioApi> {
45
+ if (loader) {
46
+ return loader();
47
+ }
48
+ // Dynamic import so `mock.module('react-native-audio-api', ...)` can intercept in tests
49
+ // and so importing `rn-gamekit/audio` does not eagerly load the native module.
50
+ const mod = (await import('react-native-audio-api')) as unknown as LoadedAudioApi & {
51
+ AudioContext?: LoadedAudioApi['AudioContext'];
52
+ default?: LoadedAudioApi;
53
+ };
54
+ // The package re-exports AudioContext via `src/api.ts` -> `export * from './core/AudioContext'`
55
+ // and also via `src/index.ts`. Handle both shapes.
56
+ const AudioContext =
57
+ (mod as unknown as { AudioContext?: LoadedAudioApi['AudioContext'] }).AudioContext ??
58
+ (mod as unknown as { default?: { AudioContext?: LoadedAudioApi['AudioContext'] } }).default?.AudioContext ??
59
+ (mod as unknown as LoadedAudioApi).AudioContext;
60
+ if (!AudioContext) {
61
+ throw new Error('AudioContext not found in react-native-audio-api — linking may have failed');
62
+ }
63
+ // GS-AUDIO-03: no synthesized no-op AudioManager. Interruption
64
+ // observation is an explicit optional capability: createGameAudio warns
65
+ // once and runs without it, so silence can never masquerade as support.
66
+ const AudioManager =
67
+ (mod as unknown as { default?: { AudioManager?: LoadedAudioApi['AudioManager'] } }).default?.AudioManager ??
68
+ (mod as unknown as { AudioManager?: LoadedAudioApi['AudioManager'] }).AudioManager ??
69
+ undefined;
70
+ return {
71
+ AudioContext: AudioContext as LoadedAudioApi['AudioContext'],
72
+ AudioManager: AudioManager as LoadedAudioApi['AudioManager'],
73
+ };
74
+ }
@@ -0,0 +1,47 @@
1
+ export type AudioCategory = 'master' | 'music' | 'sfx' | 'ui';
2
+
3
+ // Imported for documentation only; the runtime never requires the session.
4
+ import type { GameLifecycleSource } from '../core/session/types';
5
+
6
+ export type AudioSoundRecord = Record<string, number>;
7
+
8
+ export interface CreateGameAudioOptions<T extends AudioSoundRecord> {
9
+ readonly sounds: T;
10
+ }
11
+
12
+ export interface GameAudioPlayOptions {
13
+ readonly category?: AudioCategory;
14
+ readonly volume?: number;
15
+ readonly loop?: boolean;
16
+ readonly concurrency?: {
17
+ readonly key?: string;
18
+ readonly limit?: number;
19
+ readonly overflow?: 'drop-new' | 'stop-oldest';
20
+ };
21
+ }
22
+
23
+ export interface GameAudio<T extends AudioSoundRecord = AudioSoundRecord> {
24
+ play<K extends keyof T & string>(id: K, options?: GameAudioPlayOptions): void;
25
+ playMusic<K extends keyof T & string>(id: K): Promise<void>;
26
+ stopMusic(): void;
27
+ pause(): void;
28
+ resume(): void;
29
+ setVolume(category: AudioCategory, volume: number): void;
30
+ getVolume(category: AudioCategory): number;
31
+ setMuted(muted: boolean): void;
32
+ isMuted(): boolean;
33
+ /**
34
+ * Session-driven pause (GS-AUDIO-04): follows the bound session status,
35
+ * independent of the manual pause()/resume() hold, app backgrounding,
36
+ * interruption, and mute — any reason suspends.
37
+ */
38
+ setPaused(paused: boolean): void;
39
+ /**
40
+ * Bind one session lifecycle source (GS-AUDIO-04, mirrors haptics):
41
+ * applies the current status immediately, follows transitions, and
42
+ * detaches any previously bound source. Returns an idempotent detach.
43
+ * All subscriptions disappear on disposal.
44
+ */
45
+ bindLifecycle(source: GameLifecycleSource): () => void;
46
+ dispose(): void;
47
+ }
package/src/audio.ts ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Subpath entry for `rn-gamekit/audio`.
3
+ * Importing `rn-gamekit` or `rn-gamekit/react` must not load this module.
4
+ */
5
+ export { createGameAudio } from './audio/createGameAudio';
6
+ export { GameAudioError } from './audio/errors';
7
+ export type {
8
+ AudioCategory,
9
+ AudioSoundRecord,
10
+ CreateGameAudioOptions,
11
+ GameAudio,
12
+ GameAudioPlayOptions,
13
+ } from './audio/types';
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Camera2D world-bounds clamping (T12.2).
3
+ *
4
+ * Keeps the visible camera region inside an authored world bound at the
5
+ * current zoom, using conservative enclosing-AABB containment for rotated
6
+ * views (frozen in T12.0): stable near boundaries, never jittering, and
7
+ * centering axes where the world is smaller than the view.
8
+ */
9
+ import type { Aabb2D } from '../geometry/types';
10
+ import { assertFiniteNumber, assertNonnegativeSize, GeometryError } from '../geometry/validation';
11
+ import type { Camera2D } from './types';
12
+ import { assertValidCamera2D, assertValidLogicalView } from './validation';
13
+ import { rotatedHalfExtents2D } from './extents';
14
+
15
+ /** Half-extents of the rotated visible rect, in world units. */
16
+ export function cameraHalfExtents2D(camera: Camera2D, logicalView: Aabb2D): { x: number; y: number } {
17
+ return { ...rotatedHalfExtents2D(logicalView.width / 2 / camera.zoom, logicalView.height / 2 / camera.zoom, camera.rotationRadians) };
18
+ }
19
+
20
+ function clampCenter(center: number, halfExtent: number, axisMin: number, axisMax: number): number {
21
+ if (axisMax - axisMin < halfExtent * 2) {
22
+ return (axisMin + axisMax) / 2;
23
+ }
24
+ const min = axisMin + halfExtent;
25
+ const max = axisMax - halfExtent;
26
+ return center < min ? min : center > max ? max : center;
27
+ }
28
+
29
+ /**
30
+ * Clamp a camera so its visible region stays inside `worldBounds`.
31
+ *
32
+ * Conservative for rotated views: the enclosing AABB of the rotated
33
+ * visible rect is contained, so no part of the view leaves the world. An
34
+ * axis whose world is smaller than the view is centered rather than
35
+ * oscillating between impossible edges.
36
+ */
37
+ export function clampCameraBounds2D(
38
+ camera: Camera2D,
39
+ worldBounds: Aabb2D,
40
+ logicalView: Aabb2D,
41
+ ): Camera2D {
42
+ assertValidCamera2D(camera);
43
+ assertValidLogicalView(logicalView);
44
+ if (
45
+ typeof worldBounds !== 'object' ||
46
+ worldBounds === null ||
47
+ Array.isArray(worldBounds)
48
+ ) {
49
+ throw new GeometryError(
50
+ 'GEOMETRY_INVALID_NUMBER',
51
+ 'worldBounds',
52
+ `expected a rect record, got ${worldBounds === null ? 'null' : typeof worldBounds}`,
53
+ );
54
+ }
55
+ assertFiniteNumber(worldBounds.x, 'worldBounds.x');
56
+ assertFiniteNumber(worldBounds.y, 'worldBounds.y');
57
+ assertNonnegativeSize(worldBounds.width, 'worldBounds.width');
58
+ assertNonnegativeSize(worldBounds.height, 'worldBounds.height');
59
+
60
+ const extents = cameraHalfExtents2D(camera, logicalView);
61
+ return Object.freeze({
62
+ center: Object.freeze({
63
+ x: clampCenter(camera.center.x, extents.x, worldBounds.x, worldBounds.x + worldBounds.width),
64
+ y: clampCenter(camera.center.y, extents.y, worldBounds.y, worldBounds.y + worldBounds.height),
65
+ }),
66
+ zoom: camera.zoom,
67
+ rotationRadians: camera.rotationRadians,
68
+ });
69
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Shared rotated half-extent arithmetic (GS-CAMERA-03).
3
+ *
4
+ * The conservative enclosing half-extents of a rotated visible rect:
5
+ * `ex = |hx·cosθ| + |hy·sinθ|`, `ey = |hx·sinθ| + |hy·cosθ|`.
6
+ *
7
+ * Trusted scalars only: no validation, no errors, worklet-safe. Callers
8
+ * validate at their own boundary (headless paths with the camera
9
+ * validators) or consume already-validated values (UI paths that must
10
+ * never construct errors per frame). Padding, parallax, and centering
11
+ * stay per-system and explicit.
12
+ */
13
+ export function rotatedHalfExtents2D(
14
+ halfWidth: number,
15
+ halfHeight: number,
16
+ rotationRadians: number,
17
+ ): { readonly x: number; readonly y: number } {
18
+ 'worklet';
19
+ const cos = Math.abs(Math.cos(rotationRadians));
20
+ const sin = Math.abs(Math.sin(rotationRadians));
21
+ return {
22
+ x: halfWidth * cos + halfHeight * sin,
23
+ y: halfWidth * sin + halfHeight * cos,
24
+ };
25
+ }
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Camera2D follow behavior (T12.2).
3
+ *
4
+ * Deterministic, headless follow helpers for game update code. They never
5
+ * read a React ref, device clock, frame callback, or global singleton;
6
+ * games call them inside the scene update and store the returned camera in
7
+ * scene state.
8
+ */
9
+ import type { Aabb2D, Point2D } from '../geometry/types';
10
+ import { assertFiniteNumber, assertNonnegativeSize, GeometryError } from '../geometry/validation';
11
+ import type { Camera2D, FollowCamera2DOptions2D } from './types';
12
+ import { assertFinitePoint2D, assertValidCamera2D } from './validation';
13
+
14
+ function assertNonnegativeDeadZone(deadZone: unknown): asserts deadZone is Aabb2D {
15
+ if (typeof deadZone !== 'object' || deadZone === null || Array.isArray(deadZone)) {
16
+ throw new GeometryError(
17
+ 'GEOMETRY_INVALID_NUMBER',
18
+ 'deadZone',
19
+ `expected a rect record, got ${deadZone === null ? 'null' : typeof deadZone}`,
20
+ );
21
+ }
22
+ const typed = deadZone as Aabb2D;
23
+ assertFiniteNumber(typed.x, 'deadZone.x');
24
+ assertFiniteNumber(typed.y, 'deadZone.y');
25
+ assertNonnegativeSize(typed.width, 'deadZone.width');
26
+ assertNonnegativeSize(typed.height, 'deadZone.height');
27
+ }
28
+
29
+ function assertFollowOptionsShape(options: unknown): asserts options is FollowCamera2DOptions2D {
30
+ if (typeof options !== 'object' || options === null || Array.isArray(options)) {
31
+ throw new GeometryError(
32
+ 'GEOMETRY_INVALID_NUMBER',
33
+ 'options',
34
+ `expected a follow options record, got ${options === null ? 'null' : typeof options}`,
35
+ );
36
+ }
37
+ }
38
+
39
+ function followFactor(halfLifeSeconds: number, deltaSeconds: number): number {
40
+ if (!Number.isFinite(deltaSeconds) || !(deltaSeconds > 0)) {
41
+ throw new GeometryError(
42
+ 'GEOMETRY_INVALID_NUMBER',
43
+ 'deltaSeconds',
44
+ `expected a finite positive step, got ${String(deltaSeconds)}`,
45
+ );
46
+ }
47
+ return 1 - Math.pow(0.5, deltaSeconds / halfLifeSeconds);
48
+ }
49
+
50
+ /**
51
+ * Compute the next camera for a follow target.
52
+ *
53
+ * - Without options: direct follow — the camera center becomes the target.
54
+ * - With a dead zone: the camera moves only when the target crosses the
55
+ * zone edge, by exactly the amount needed to bring the target back to
56
+ * the edge.
57
+ * - `perAxis` disables following on either axis.
58
+ * - `dampingHalfLifeSeconds` blends toward the desired center with a
59
+ * half-life model; equivalent fixed-step schedules produce equivalent
60
+ * results.
61
+ */
62
+ export function followCamera2D(
63
+ camera: Camera2D,
64
+ target: Point2D,
65
+ options?: FollowCamera2DOptions2D,
66
+ deltaSeconds?: number,
67
+ ): Camera2D {
68
+ assertValidCamera2D(camera);
69
+ assertFinitePoint2D(target, 'target');
70
+
71
+ if (options !== undefined) {
72
+ assertFollowOptionsShape(options);
73
+ }
74
+ const perAxis = options?.perAxis;
75
+ if (perAxis !== undefined) {
76
+ // T12-SF3: the per-axis options must be a non-array record before any
77
+ // field is read.
78
+ if (typeof perAxis !== 'object' || perAxis === null || Array.isArray(perAxis)) {
79
+ throw new GeometryError(
80
+ 'GEOMETRY_INVALID_NUMBER',
81
+ 'perAxis',
82
+ `expected a per-axis record, got ${perAxis === null ? 'null' : typeof perAxis}`,
83
+ );
84
+ }
85
+ const x = (perAxis as { x?: unknown }).x;
86
+ const y = (perAxis as { y?: unknown }).y;
87
+ if (x !== undefined && typeof x !== 'boolean') {
88
+ throw new GeometryError('GEOMETRY_INVALID_NUMBER', 'perAxis.x', `expected a boolean, got ${String(x)}`);
89
+ }
90
+ if (y !== undefined && typeof y !== 'boolean') {
91
+ throw new GeometryError('GEOMETRY_INVALID_NUMBER', 'perAxis.y', `expected a boolean, got ${String(y)}`);
92
+ }
93
+ }
94
+ const perAxisX = options?.perAxis?.x ?? true;
95
+ const perAxisY = options?.perAxis?.y ?? true;
96
+ const deadZone = options?.deadZone;
97
+ if (deadZone !== undefined) {
98
+ assertNonnegativeDeadZone(deadZone);
99
+ }
100
+ const halfLife = options?.dampingHalfLifeSeconds;
101
+ if (halfLife !== undefined) {
102
+ assertFiniteNumber(halfLife, 'dampingHalfLifeSeconds');
103
+ if (!(halfLife > 0)) {
104
+ throw new GeometryError(
105
+ 'GEOMETRY_INVALID_NUMBER',
106
+ 'dampingHalfLifeSeconds',
107
+ `expected a finite positive half-life, got ${String(halfLife)}`,
108
+ );
109
+ }
110
+ if (deltaSeconds === undefined) {
111
+ throw new GeometryError(
112
+ 'GEOMETRY_INVALID_NUMBER',
113
+ 'deltaSeconds',
114
+ 'damping requires an explicit fixed-step deltaSeconds',
115
+ );
116
+ }
117
+ }
118
+
119
+ const center = camera.center;
120
+ const desired = { x: center.x, y: center.y };
121
+ if (deadZone === undefined) {
122
+ desired.x = target.x;
123
+ desired.y = target.y;
124
+ } else {
125
+ const minX = center.x + deadZone.x;
126
+ const maxX = minX + deadZone.width;
127
+ const minY = center.y + deadZone.y;
128
+ const maxY = minY + deadZone.height;
129
+ if (target.x > maxX) {
130
+ desired.x = target.x - deadZone.width - deadZone.x;
131
+ } else if (target.x < minX) {
132
+ desired.x = target.x - deadZone.x;
133
+ }
134
+ if (target.y > maxY) {
135
+ desired.y = target.y - deadZone.height - deadZone.y;
136
+ } else if (target.y < minY) {
137
+ desired.y = target.y - deadZone.y;
138
+ }
139
+ }
140
+ if (!perAxisX) {
141
+ desired.x = center.x;
142
+ }
143
+ if (!perAxisY) {
144
+ desired.y = center.y;
145
+ }
146
+
147
+ let nextCenter: Point2D;
148
+ if (halfLife !== undefined && deltaSeconds !== undefined) {
149
+ const factor = followFactor(halfLife, deltaSeconds);
150
+ nextCenter = {
151
+ x: center.x + (desired.x - center.x) * factor,
152
+ y: center.y + (desired.y - center.y) * factor,
153
+ };
154
+ } else {
155
+ nextCenter = desired;
156
+ }
157
+
158
+ // T12-F6: every public helper returns a frozen value; the caller's
159
+ // camera is never aliased or mutated.
160
+ return Object.freeze({
161
+ center: Object.freeze({ x: nextCenter.x, y: nextCenter.y }),
162
+ zoom: camera.zoom,
163
+ rotationRadians: camera.rotationRadians,
164
+ });
165
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Camera2D — the opt-in 2D camera system (Task 12).
3
+ *
4
+ * Pure, headless, native-free camera math shared by rendering and pointer
5
+ * input: immutable camera values, forward and inverse transforms, follow,
6
+ * bounds clamping, deterministic shake, presentation interpolation, and
7
+ * conservative visibility culling. The React integration
8
+ * (`defineGameCamera2D`, `GameView`, `GameWorld2D`, `GameLayer2D`) lives in
9
+ * `src/react/`.
10
+ */
11
+ export { createCamera2D, getCameraVisibleBounds2D, logicalToWorld2D, worldToLogical2D, worldToSurface2D, surfaceToWorld2D } from './transform';
12
+ export { interpolateCamera2D, interpolateCameraScalar2D, shortestRotationDelta2D } from './interpolation';
13
+ export { followCamera2D } from './follow';
14
+ export { clampCameraBounds2D, cameraHalfExtents2D } from './bounds';
15
+ export { rotatedHalfExtents2D } from './extents';
16
+ export { sampleCameraShake2D } from './shake';
17
+ export {
18
+ filterCameraVisible2D,
19
+ intersectsCameraView2D,
20
+ paddedCameraBounds2D,
21
+ type CameraViewShape2D,
22
+ } from './visibility';
23
+ export type {
24
+ Camera2D,
25
+ CameraCut2D,
26
+ CameraFollowAxisOptions2D,
27
+ CameraShakeOptions2D,
28
+ FollowCamera2DOptions2D,
29
+ } from './types';
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Camera2D presentation interpolation (T12.2, T12.3).
3
+ *
4
+ * The public `interpolateCamera2D` validates its inputs and returns a
5
+ * frozen camera. The internal `interpolateCameraScalar2D` is the trusted
6
+ * display-frequency projector: its COMPLETE call graph is workletized (no
7
+ * validation, no structured error construction, the shortest-arc math is
8
+ * inline), so the UI runtime can call it from the camera presentation
9
+ * worklet without crossing runtimes (T12-F2). Callers validate selector
10
+ * output at the JS commit boundary before publishing shared values.
11
+ */
12
+ import { assertFiniteNumber, GeometryError } from '../geometry/validation';
13
+ import type { Camera2D, CameraCut2D } from './types';
14
+ import { assertCameraShape } from './validation';
15
+
16
+ function assertCutShape(cut: unknown, field: string): asserts cut is CameraCut2D {
17
+ if (typeof cut !== 'object' || cut === null || Array.isArray(cut)) {
18
+ throw new GeometryError(
19
+ 'GEOMETRY_INVALID_NUMBER',
20
+ field,
21
+ `expected a camera cut record, got ${cut === null ? 'null' : typeof cut}`,
22
+ );
23
+ }
24
+ assertFiniteNumber((cut as CameraCut2D).cutId, `${field}.cutId`);
25
+ const camera = (cut as CameraCut2D).camera;
26
+ assertCameraShape(camera, `${field}.camera`);
27
+ const cameraField = `${field}.camera`;
28
+ assertFiniteNumber(camera.center.x, `${cameraField}.center.x`);
29
+ assertFiniteNumber(camera.center.y, `${cameraField}.center.y`);
30
+ assertFiniteNumber(camera.zoom, `${cameraField}.zoom`);
31
+ if (!(camera.zoom > 0)) {
32
+ throw new GeometryError(
33
+ 'GEOMETRY_INVALID_NUMBER',
34
+ `${cameraField}.zoom`,
35
+ `expected a finite zoom greater than zero, got ${String(camera.zoom)}`,
36
+ );
37
+ }
38
+ assertFiniteNumber(camera.rotationRadians, `${cameraField}.rotationRadians`);
39
+ }
40
+
41
+ /**
42
+ * Trusted scalar projector (worklet-safe): interpolates center and zoom
43
+ * linearly and rotation across the shortest angular arc. A changed `cutId`
44
+ * (or an absent previous cut) snaps to the current camera. No validation,
45
+ * no allocation of structured errors.
46
+ */
47
+ export function interpolateCameraScalar2D(
48
+ previous: CameraCut2D | undefined,
49
+ current: CameraCut2D,
50
+ alpha: number,
51
+ ): Camera2D {
52
+ 'worklet';
53
+ if (previous === undefined || previous.cutId !== current.cutId) {
54
+ return current.camera;
55
+ }
56
+ const from = previous.camera;
57
+ const to = current.camera;
58
+ let delta = (to.rotationRadians - from.rotationRadians) % (Math.PI * 2);
59
+ if (delta > Math.PI) {
60
+ delta -= Math.PI * 2;
61
+ } else if (delta < -Math.PI) {
62
+ delta += Math.PI * 2;
63
+ }
64
+ return {
65
+ center: {
66
+ x: from.center.x + (to.center.x - from.center.x) * alpha,
67
+ y: from.center.y + (to.center.y - from.center.y) * alpha,
68
+ },
69
+ zoom: from.zoom + (to.zoom - from.zoom) * alpha,
70
+ rotationRadians: from.rotationRadians + delta * alpha,
71
+ };
72
+ }
73
+
74
+ /** The shortest signed angular difference from `from` to `to`. */
75
+ export function shortestRotationDelta2D(from: number, to: number): number {
76
+ let delta = (to - from) % (Math.PI * 2);
77
+ if (delta > Math.PI) {
78
+ delta -= Math.PI * 2;
79
+ } else if (delta < -Math.PI) {
80
+ delta += Math.PI * 2;
81
+ }
82
+ return delta;
83
+ }
84
+
85
+ /**
86
+ * Public interpolated camera: validates every input, clamps the alpha
87
+ * policy (reject outside `[0, 1]`), and returns a frozen value. Delegates
88
+ * to the trusted scalar projector.
89
+ */
90
+ export function interpolateCamera2D(
91
+ previous: CameraCut2D | undefined,
92
+ current: CameraCut2D,
93
+ alpha: number,
94
+ ): Camera2D {
95
+ assertCutShape(current, 'current');
96
+ if (previous !== undefined) {
97
+ assertCutShape(previous, 'previous');
98
+ }
99
+ assertFiniteNumber(alpha, 'alpha');
100
+ if (alpha < 0 || alpha > 1) {
101
+ throw new GeometryError(
102
+ 'GEOMETRY_INVALID_NUMBER',
103
+ 'alpha',
104
+ `expected alpha in [0, 1], got ${String(alpha)}`,
105
+ );
106
+ }
107
+ const interpolated = interpolateCameraScalar2D(previous, current, alpha);
108
+ return Object.freeze({
109
+ center: Object.freeze({ x: interpolated.center.x, y: interpolated.center.y }),
110
+ zoom: interpolated.zoom,
111
+ rotationRadians: interpolated.rotationRadians,
112
+ });
113
+ }
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Camera2D deterministic shake (T12.2).
3
+ *
4
+ * Shake is reproducible from explicit state: a seed, elapsed simulation
5
+ * time, duration, and amplitude. No `Math.random()` anywhere. The sampler
6
+ * returns the unmodified base camera at and after the duration, and never
7
+ * mutates its input. Presentation applies the offset to the presented
8
+ * camera, so pointer inversion (which uses the same presented camera)
9
+ * keeps visible targets touchable.
10
+ */
11
+ import type { Camera2D, CameraShakeOptions2D } from './types';
12
+ import { assertValidCamera2D } from './validation';
13
+ import { assertFiniteNumber, assertNonnegativeSize, GeometryError } from '../geometry/validation';
14
+
15
+ function assertValidShakeOptions(options: CameraShakeOptions2D): void {
16
+ if (typeof options !== 'object' || options === null || Array.isArray(options)) {
17
+ throw new GeometryError(
18
+ 'GEOMETRY_INVALID_NUMBER',
19
+ 'options',
20
+ `expected a shake options record, got ${options === null ? 'null' : typeof options}`,
21
+ );
22
+ }
23
+ assertFiniteNumber(options.seed, 'seed');
24
+ assertFiniteNumber(options.elapsedSeconds, 'elapsedSeconds');
25
+ if (!(options.elapsedSeconds >= 0)) {
26
+ throw new GeometryError(
27
+ 'GEOMETRY_INVALID_NUMBER',
28
+ 'elapsedSeconds',
29
+ `expected a nonnegative elapsed time, got ${String(options.elapsedSeconds)}`,
30
+ );
31
+ }
32
+ assertFiniteNumber(options.durationSeconds, 'durationSeconds');
33
+ if (!(options.durationSeconds > 0)) {
34
+ throw new GeometryError(
35
+ 'GEOMETRY_INVALID_NUMBER',
36
+ 'durationSeconds',
37
+ `expected a positive duration, got ${String(options.durationSeconds)}`,
38
+ );
39
+ }
40
+ assertNonnegativeSize(options.amplitude, 'amplitude');
41
+ if (options.frequency !== undefined) {
42
+ assertFiniteNumber(options.frequency, 'frequency');
43
+ }
44
+ }
45
+
46
+ /** Deterministic per-axis phase from the seed (never a wall-clock read). */
47
+ function phaseOf(seed: number, axis: number): number {
48
+ const raw = Math.sin(seed * 12.9898 + axis * 78.233) * 43758.5453;
49
+ const fraction = raw - Math.floor(raw);
50
+ return fraction * Math.PI * 2;
51
+ }
52
+
53
+ /**
54
+ * Sample the presented camera offset for a shake.
55
+ *
56
+ * The offset decays linearly to zero over `durationSeconds`; at and after
57
+ * the duration the base camera is returned unchanged. Equal options
58
+ * produce equal results.
59
+ */
60
+ export function sampleCameraShake2D(
61
+ base: Camera2D,
62
+ options: CameraShakeOptions2D,
63
+ ): Camera2D {
64
+ assertValidCamera2D(base);
65
+ assertValidShakeOptions(options);
66
+
67
+ const { seed, elapsedSeconds, durationSeconds, amplitude, frequency = Math.PI * 2 } = options;
68
+ if (elapsedSeconds >= durationSeconds || amplitude === 0) {
69
+ // T12-F6: even the endpoint returns a frozen copy — never the caller's
70
+ // base object by identity.
71
+ return Object.freeze({
72
+ center: Object.freeze({ x: base.center.x, y: base.center.y }),
73
+ zoom: base.zoom,
74
+ rotationRadians: base.rotationRadians,
75
+ });
76
+ }
77
+ const envelope = 1 - elapsedSeconds / durationSeconds;
78
+ const offset = {
79
+ x: Math.sin(elapsedSeconds * frequency + phaseOf(seed, 1)) * amplitude * envelope,
80
+ y: Math.sin(elapsedSeconds * frequency + phaseOf(seed, 2)) * amplitude * envelope,
81
+ };
82
+ return Object.freeze({
83
+ center: Object.freeze({
84
+ x: base.center.x + offset.x,
85
+ y: base.center.y + offset.y,
86
+ }),
87
+ zoom: base.zoom,
88
+ rotationRadians: base.rotationRadians,
89
+ });
90
+ }