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,358 @@
1
+ import { useContext, useMemo } from 'react';
2
+ import { Atlas, Picture, Skia } from '@shopify/react-native-skia';
3
+ import { useColorBuffer, useRectBuffer, useRSXformBuffer } from '@shopify/react-native-skia';
4
+ import { useDerivedValue, type SharedValue } from 'react-native-reanimated';
5
+ import type { SkImage, SkColor } from '@shopify/react-native-skia';
6
+
7
+ import { GameWorldContext } from '../sprites/GameWorld2D';
8
+ import type {
9
+ ParticleEffectDefinition,
10
+ ParticleEmissionRecord,
11
+ ParticleSystem,
12
+ ParticleUiRegistry,
13
+ } from '../../particles/types';
14
+
15
+ import {
16
+ PARTICLE_CULL_PADDING,
17
+ cameraVisibleWorldBounds,
18
+ maxParticleExtent,
19
+ screenVisibleBounds,
20
+ viewportWorldBounds,
21
+ visibleInBounds,
22
+ } from './culling';
23
+ import { assertUniformParticleSpriteRatio, particleSpriteXform } from './spriteXForm';
24
+
25
+ export interface ParticleViewProps {
26
+ readonly system: ParticleSystem;
27
+ readonly effect: string;
28
+ /** Surface size: px for screen space, world units for world space. */
29
+ readonly width: number;
30
+ readonly height: number;
31
+ /**
32
+ * The presentation handle from `useParticlePresentation`: a scalar
33
+ * active-time clock plus the bounded emission registry. Views are pure
34
+ * readers and NEVER advance the system clock (T15-F1).
35
+ */
36
+ readonly presentation: {
37
+ readonly clock: SharedValue<number>;
38
+ readonly registry: SharedValue<ParticleUiRegistry>;
39
+ };
40
+ /**
41
+ * Sprite source for `kind: 'sprite'` effects — the decoded sheet resolved
42
+ * once at bind time by the caller. Required for sprite effects; a missing
43
+ * source is a structured render error (T15-F3).
44
+ */
45
+ readonly spriteSource?: {
46
+ readonly image: SkImage;
47
+ readonly frame: { x: number; y: number; width: number; height: number };
48
+ };
49
+ }
50
+
51
+ /**
52
+ * Presentation-only particle renderer.
53
+ *
54
+ * Topology is CONSTANT per effect regardless of capacity (T15-RF5): exactly
55
+ * one React node (`Picture` for shapes, `Atlas` for sprites) plus a single
56
+ * UI-runtime derived worklet that walks the effect's emission records and
57
+ * computes analytic transforms from the scalar active-time clock. No per-slot
58
+ * data crosses the runtime boundary per frame (T15-SF1).
59
+ *
60
+ * Coordinate ownership (GS-PARTICLE-02): `space: 'world'` effects sample in
61
+ * world units and must mount inside world space (no parent transform);
62
+ * `space: 'screen'` effects sample in surface pixels and must mount inside
63
+ * screen space. World culling uses the presented camera when one exists
64
+ * and the resolved viewport bounds otherwise; zoom applies through the
65
+ * camera, and there is no parallax factor on particles by design.
66
+ */
67
+ export function ParticleView({
68
+ system,
69
+ effect,
70
+ width,
71
+ height,
72
+ presentation,
73
+ spriteSource,
74
+ }: ParticleViewProps) {
75
+ const definition = useMemo<ParticleEffectDefinition>(
76
+ () => system.bindPresentation().definition(effect),
77
+ [system, effect],
78
+ );
79
+ // GS-PARTICLE-02: conservative cull extent from authored geometry and
80
+ // scale endpoints (bounding radius, rotation-proof); overscan stays in
81
+ // the bounds padding, never in this extent.
82
+ const cullExtent = useMemo(() => maxParticleExtent(definition), [definition]);
83
+ const world = useContext(GameWorldContext);
84
+ const camera = (world?.camera ?? null) as never;
85
+ const viewport = (world?.viewport ?? null) as never;
86
+
87
+ if (definition.particle.kind === 'sprite') {
88
+ if (spriteSource === undefined) {
89
+ throw new Error(
90
+ `[rn-gamekit/particles] effect "${effect}" declares kind "sprite" but no spriteSource was provided — resolve the sheet via the asset store before rendering`,
91
+ );
92
+ }
93
+ assertUniformParticleSpriteRatio(
94
+ definition.particle.size.width,
95
+ definition.particle.size.height,
96
+ spriteSource.frame.width,
97
+ spriteSource.frame.height,
98
+ );
99
+ return (
100
+ <SpriteSlots
101
+ clock={presentation.clock}
102
+ registry={presentation.registry}
103
+ effect={effect}
104
+ capacity={definition.capacity}
105
+ image={spriteSource.image}
106
+ frameRect={spriteSource.frame}
107
+ drawWidth={definition.particle.size.width}
108
+ drawHeight={definition.particle.size.height}
109
+ cullExtent={cullExtent}
110
+ fadeOut={definition.fadeOut}
111
+ gravityX={definition.gravity.x}
112
+ gravityY={definition.gravity.y}
113
+ width={width}
114
+ height={height}
115
+ space={definition.space}
116
+ camera={camera}
117
+ viewport={viewport}
118
+ />
119
+ );
120
+ }
121
+
122
+ return (
123
+ <ShapeBatch
124
+ clock={presentation.clock}
125
+ registry={presentation.registry}
126
+ effect={effect}
127
+ capacity={definition.capacity}
128
+ shape={definition.particle.shape === 'rectangle' ? 'rect' : 'circle'}
129
+ radius={definition.particle.radius ?? 3}
130
+ rectWidth={definition.particle.width ?? 6}
131
+ rectHeight={definition.particle.height ?? 6}
132
+ cullExtent={cullExtent}
133
+ color={definition.particle.color ?? '#ffffff'}
134
+ fadeOut={definition.fadeOut}
135
+ gravityX={definition.gravity.x}
136
+ gravityY={definition.gravity.y}
137
+ width={width}
138
+ height={height}
139
+ space={definition.space}
140
+ camera={camera}
141
+ viewport={viewport}
142
+ />
143
+ );
144
+ }
145
+
146
+ /**
147
+ * Analytic transform for one emission at the given ACTIVE time.
148
+ *
149
+ * T15-TF3: opacity honors the definition's fade policy — `fadeOut: true`
150
+ * ramps `1 -> t`, `fadeOut: false` stays fully opaque for the whole life.
151
+ */
152
+ export function sampleEmission(
153
+ e: ParticleEmissionRecord,
154
+ now: number,
155
+ gravityX: number,
156
+ gravityY: number,
157
+ fadeOut: boolean,
158
+ ): { x: number; y: number; rotation: number; scale: number; opacity: number; alive: boolean } {
159
+ 'worklet';
160
+ const age = now - e.bornAt;
161
+ if (age < 0 || age >= e.lifetime) {
162
+ return { x: 0, y: 0, rotation: 0, scale: 0, opacity: 0, alive: false };
163
+ }
164
+ const t = age / e.lifetime;
165
+ const x = e.originX + e.vx * age + 0.5 * gravityX * age * age;
166
+ const y = e.originY + e.vy * age + 0.5 * gravityY * age * age;
167
+ const rotation = e.rotation + e.rotationSpeed * age;
168
+ // T20A-R1: definitions guarantee non-negative scale. The clamp keeps any
169
+ // legacy negative `scaleOverLife` value DEFINED (collapse to a point)
170
+ // instead of handing Skia a signed radius or rectangle extent.
171
+ const scale = Math.max(0, e.scaleStart + (e.scaleEnd - e.scaleStart) * t);
172
+ const opacity = fadeOut ? 1 - t : 1;
173
+ return { x, y, rotation, scale, opacity, alive: true };
174
+ }
175
+
176
+ // ---------------------------------------------------------------------------
177
+ // Shapes: ONE immediate Picture built in ONE worklet per effect (T15-RF5).
178
+ // ---------------------------------------------------------------------------
179
+
180
+ function ShapeBatch(props: {
181
+ readonly clock: SharedValue<number>;
182
+ readonly registry: SharedValue<ParticleUiRegistry>;
183
+ readonly effect: string;
184
+ readonly capacity: number;
185
+ readonly shape: 'circle' | 'rect';
186
+ readonly radius: number;
187
+ readonly rectWidth: number;
188
+ readonly rectHeight: number;
189
+ readonly color: string;
190
+ readonly fadeOut: boolean;
191
+ readonly gravityX: number;
192
+ readonly gravityY: number;
193
+ readonly width: number;
194
+ readonly height: number;
195
+ readonly space: 'world' | 'screen';
196
+ readonly cullExtent: number;
197
+ readonly camera: unknown;
198
+ readonly viewport: unknown;
199
+ }) {
200
+ const { clock, registry, effect, capacity, shape, radius, rectWidth, rectHeight, color, fadeOut, gravityX, gravityY, width, height, space, cullExtent, camera, viewport } =
201
+ props;
202
+
203
+ const picture = useDerivedValue(() => {
204
+ 'worklet';
205
+ const reg = registry.value;
206
+ const entry = reg.effects[effect];
207
+ const now = clock.value;
208
+ // Culling bounds computed ONCE per revision. World space without a
209
+ // presented camera falls back to the resolved viewport bounds (never
210
+ // fail-closed hide); the particle extent keeps crossings visible.
211
+ const bounds =
212
+ space === 'world'
213
+ ? (camera as { value?: { camera?: unknown } } | null)?.value?.camera === undefined
214
+ ? viewportWorldBounds(viewport as never, PARTICLE_CULL_PADDING)
215
+ : cameraVisibleWorldBounds(camera as never, viewport as never, PARTICLE_CULL_PADDING)
216
+ : screenVisibleBounds(width, height, PARTICLE_CULL_PADDING);
217
+
218
+ const recorder = Skia.PictureRecorder();
219
+ const canvas = recorder.beginRecording();
220
+ if (entry === undefined) return recorder.finishRecordingAsPicture();
221
+
222
+ const paint = Skia.Paint();
223
+ paint.setColor(Skia.Color(color));
224
+
225
+ const particles = entry.particles;
226
+ for (let i = 0; i < particles.length && i < capacity; i++) {
227
+ const e = particles[i]!;
228
+ const s = sampleEmission(e, now, gravityX, gravityY, fadeOut);
229
+ if (!s.alive || s.opacity <= 0) continue;
230
+ if (!visibleInBounds(s.x, s.y, cullExtent, bounds)) continue;
231
+ paint.setAlphaf(Math.max(0, Math.min(1, s.opacity)));
232
+ if (shape === 'circle') {
233
+ canvas.drawCircle(s.x, s.y, radius * s.scale, paint);
234
+ } else {
235
+ const w = rectWidth * s.scale;
236
+ const h = rectHeight * s.scale;
237
+ const matrix = Skia.Matrix().translate(s.x, s.y).rotate(s.rotation);
238
+ canvas.save();
239
+ canvas.concat(matrix);
240
+ canvas.drawRect({ x: -w / 2, y: -h / 2, width: w, height: h }, paint);
241
+ canvas.restore();
242
+ }
243
+ }
244
+ return recorder.finishRecordingAsPicture();
245
+ });
246
+
247
+ return <Picture picture={picture} />;
248
+ }
249
+
250
+ // ---------------------------------------------------------------------------
251
+ // Sprites: fixed-capacity Atlas buffers filled by ONE worklet (T15-F3/R4/SF2).
252
+ // ---------------------------------------------------------------------------
253
+
254
+ function SpriteSlots(props: {
255
+ readonly clock: SharedValue<number>;
256
+ readonly registry: SharedValue<ParticleUiRegistry>;
257
+ readonly effect: string;
258
+ readonly capacity: number;
259
+ readonly image: SkImage;
260
+ readonly frameRect: { x: number; y: number; width: number; height: number };
261
+ readonly drawWidth: number;
262
+ readonly drawHeight: number;
263
+ readonly fadeOut: boolean;
264
+ readonly gravityX: number;
265
+ readonly gravityY: number;
266
+ readonly width: number;
267
+ readonly height: number;
268
+ readonly space: 'world' | 'screen';
269
+ readonly cullExtent: number;
270
+ readonly camera: unknown;
271
+ readonly viewport: unknown;
272
+ }) {
273
+ const { clock, registry, effect, capacity, image, frameRect, drawWidth, drawHeight, fadeOut, gravityX, gravityY, width, height, space, cullExtent, camera, viewport } =
274
+ props;
275
+
276
+ // UI-owned buffers created once per mount (T15-SF1). Colors use the
277
+ // supported Skia color buffer (T15-TF3): each entry is an SkColor
278
+ // Float32Array [r,g,b,a] mutated on the UI runtime.
279
+ const rects = useRectBuffer(capacity, (rect) => {
280
+ 'worklet';
281
+ rect.setXYWH(0, 0, 0, 0);
282
+ });
283
+ const xforms = useRSXformBuffer(capacity, (xform) => {
284
+ 'worklet';
285
+ xform.set(1, 0, 0, 0);
286
+ });
287
+ const colors = useColorBuffer(capacity, (color: SkColor) => {
288
+ 'worklet';
289
+ color[0] = 1;
290
+ color[1] = 1;
291
+ color[2] = 1;
292
+ color[3] = 0;
293
+ });
294
+
295
+ useDerivedValue(() => {
296
+ 'worklet';
297
+ const reg = registry.value;
298
+ const entry = reg.effects[effect];
299
+ const now = clock.value;
300
+ const bounds =
301
+ space === 'world'
302
+ ? (camera as { value?: { camera?: unknown } } | null)?.value?.camera === undefined
303
+ ? viewportWorldBounds(viewport as never, PARTICLE_CULL_PADDING)
304
+ : cameraVisibleWorldBounds(camera as never, viewport as never, PARTICLE_CULL_PADDING)
305
+ : screenVisibleBounds(width, height, PARTICLE_CULL_PADDING);
306
+
307
+ for (let i = 0; i < capacity; i++) {
308
+ const rectSlot = rects.value[i];
309
+ const xformSlot = xforms.value[i];
310
+ const colorSlot: SkColor | undefined = colors.value[i];
311
+ if (rectSlot === undefined || xformSlot === undefined || colorSlot === undefined) continue;
312
+
313
+ let placed = false;
314
+ if (entry !== undefined && i < entry.particles.length) {
315
+ const e = entry.particles[i]!;
316
+ const age = now - e.bornAt;
317
+ if (age >= 0 && age < e.lifetime) {
318
+ const t = age / e.lifetime;
319
+ const x = e.originX + e.vx * age + 0.5 * gravityX * age * age;
320
+ const y = e.originY + e.vy * age + 0.5 * gravityY * age * age;
321
+ if (visibleInBounds(x, y, cullExtent, bounds)) {
322
+ const op = fadeOut ? 1 - t : 1;
323
+ const xf = particleSpriteXform({
324
+ x,
325
+ y,
326
+ rotation: e.rotation + e.rotationSpeed * age,
327
+ // T20A-R1: non-negative clamp — see the shape sampler note.
328
+ scale: Math.max(0, e.scaleStart + (e.scaleEnd - e.scaleStart) * t),
329
+ drawWidth,
330
+ drawHeight,
331
+ frameWidth: frameRect.width,
332
+ frameHeight: frameRect.height,
333
+ });
334
+ rectSlot.setXYWH(frameRect.x, frameRect.y, frameRect.width, frameRect.height);
335
+ xformSlot.set(xf.scos, xf.ssin, xf.tx, xf.ty);
336
+ // White modulates the texture; alpha carries sampled fade.
337
+ colorSlot[0] = 1;
338
+ colorSlot[1] = 1;
339
+ colorSlot[2] = 1;
340
+ colorSlot[3] = Math.max(0, Math.min(1, op));
341
+ placed = true;
342
+ }
343
+ }
344
+ }
345
+ if (!placed) {
346
+ // Hide inactive/culled slots AND clear stale alpha (T15-SF2).
347
+ rectSlot.setXYWH(0, 0, 0, 0);
348
+ colorSlot[0] = 1;
349
+ colorSlot[1] = 1;
350
+ colorSlot[2] = 1;
351
+ colorSlot[3] = 0;
352
+ }
353
+ }
354
+ return colors;
355
+ });
356
+
357
+ return <Atlas image={image} sprites={rects} transforms={xforms} colors={colors} />;
358
+ }
@@ -0,0 +1,145 @@
1
+ /** Conservative world-space AABB used for presentation-only culling. */
2
+ import { rotatedHalfExtents2D } from '../../camera2d/extents';
3
+ import type { ParticleEffectDefinition } from '../../particles/types';
4
+ export interface WorldAabb {
5
+ readonly minX: number;
6
+ readonly minY: number;
7
+ readonly maxX: number;
8
+ readonly maxY: number;
9
+ }
10
+
11
+ export const PARTICLE_CULL_PADDING = 16;
12
+
13
+ /**
14
+ * The world region visible through the PRESENTED camera (T15-RF2).
15
+ *
16
+ * The logical viewport rectangle is rotated/zoomed by the camera, so its
17
+ * axis-aligned world bounds are the center plus the rotated half-extents:
18
+ *
19
+ * ex = |hx·cosθ| + |hy·sinθ|, ey = |hx·sinθ| + |hy·cosθ|
20
+ *
21
+ * which is the exact AABB of the rotated view rect. Padding is applied in
22
+ * world units. Worklet-safe; shared by the shape Picture and Atlas paths so
23
+ * their culling results cannot diverge.
24
+ */
25
+ export function cameraVisibleWorldBounds(
26
+ camera: SharedCamera | null,
27
+ viewport: SharedViewport | null,
28
+ pad: number,
29
+ ): WorldAabb | undefined {
30
+ 'worklet';
31
+ if (camera === null || viewport === null) return undefined;
32
+ const view = viewport.value?.visibleLogicalBounds;
33
+ const cam = camera.value?.camera;
34
+ if (view === undefined || cam === undefined) return undefined;
35
+ const hx = view.width / (2 * cam.zoom);
36
+ const hy = view.height / (2 * cam.zoom);
37
+ const extent = rotatedHalfExtents2D(hx, hy, cam.rotationRadians);
38
+ const ex = extent.x + pad;
39
+ const ey = extent.y + pad;
40
+ return {
41
+ minX: cam.center.x - ex,
42
+ minY: cam.center.y - ey,
43
+ maxX: cam.center.x + ex,
44
+ maxY: cam.center.y + ey,
45
+ };
46
+ }
47
+
48
+ export function screenVisibleBounds(
49
+ width: number,
50
+ height: number,
51
+ pad: number,
52
+ ): WorldAabb {
53
+ 'worklet';
54
+ return { minX: -pad, minY: -pad, maxX: width + pad, maxY: height + pad };
55
+ }
56
+
57
+ /**
58
+ * Viewport-only world bounds for presentation without a presented camera
59
+ * (GS-PARTICLE-02): the tile layer's viewport-only path — the resolved
60
+ * logical bounds expanded by world-unit padding. World particles inside an
61
+ * ordinary viewport-only GameWorld2D render instead of failing closed.
62
+ */
63
+ export function viewportWorldBounds(
64
+ viewport: SharedViewport | null,
65
+ pad: number,
66
+ ): WorldAabb | undefined {
67
+ 'worklet';
68
+ const view = viewport?.value?.visibleLogicalBounds;
69
+ if (view === undefined) return undefined;
70
+ return {
71
+ minX: view.x - pad,
72
+ minY: view.y - pad,
73
+ maxX: view.x + view.width + pad,
74
+ maxY: view.y + view.height + pad,
75
+ };
76
+ }
77
+
78
+ /**
79
+ * Circle-vs-bounds visibility (GS-PARTICLE-02): the particle's
80
+ * conservative extent (bounding radius from geometry and scale endpoints)
81
+ * expands the bounds, so partially crossing shapes stay visible while
82
+ * fully outside shapes cull. Extra overscan stays in the bounds padding —
83
+ * never folded into the shape extent. A missing bounds still hides.
84
+ */
85
+ export function visibleInBounds(
86
+ x: number,
87
+ y: number,
88
+ extent: number,
89
+ b: WorldAabb | undefined,
90
+ ): boolean {
91
+ 'worklet';
92
+ if (b === undefined) return false;
93
+ return x >= b.minX - extent && x <= b.maxX + extent && y >= b.minY - extent && y <= b.maxY + extent;
94
+ }
95
+
96
+ /**
97
+ * Conservative per-effect cull extent (GS-PARTICLE-02): the bounding
98
+ * radius of the authored geometry times the largest scale endpoint, so
99
+ * rotation can never push drawn pixels past the culled region. Circles
100
+ * use radius; rectangles and sprites use half the diagonal; absent
101
+ * dimensions fall back to the render defaults. The legacy scale range
102
+ * contributes its maximum; definitions without scale use 1.
103
+ */
104
+ export function maxParticleExtent(definition: ParticleEffectDefinition): number {
105
+ 'worklet';
106
+ let maxScale = 1;
107
+ const scale = (definition as { scale?: { start: { max: number }; end: { max: number } } }).scale;
108
+ if (scale !== undefined) {
109
+ if (scale.start.max > maxScale) maxScale = scale.start.max;
110
+ if (scale.end.max > maxScale) maxScale = scale.end.max;
111
+ }
112
+ const legacy = (
113
+ definition as { scaleOverLife?: { max: number } }
114
+ ).scaleOverLife;
115
+ if (legacy !== undefined && legacy.max > maxScale) maxScale = legacy.max;
116
+ const particle = definition.particle;
117
+ if (particle.kind === 'sprite') {
118
+ return (Math.hypot(particle.size.width, particle.size.height) / 2) * maxScale;
119
+ }
120
+ if (particle.shape === 'circle') {
121
+ return (particle.radius ?? 3) * maxScale;
122
+ }
123
+ return (Math.hypot(particle.width ?? 6, particle.height ?? 6) / 2) * maxScale;
124
+ }
125
+ // keeping this pure module free of Reanimated/RN imports while accepting
126
+ // real SharedValue<CameraCut2D|ResolvedViewport2D> instances.
127
+ // Minimal structural mirrors of the shared refs the view layer passes in,
128
+ // keeping this pure module free of Reanimated/RN imports while accepting
129
+ // real SharedValue<CameraCut2D|ResolvedViewport2D> instances.
130
+ interface SharedCamera {
131
+ readonly value?:
132
+ | {
133
+ readonly camera?: {
134
+ readonly center: { readonly x: number; readonly y: number };
135
+ readonly zoom: number;
136
+ readonly rotationRadians: number;
137
+ };
138
+ }
139
+ | undefined;
140
+ }
141
+ interface SharedViewport {
142
+ readonly value?:
143
+ | { readonly visibleLogicalBounds?: { readonly x: number; readonly y: number; readonly width: number; readonly height: number } }
144
+ | undefined;
145
+ }
@@ -0,0 +1,6 @@
1
+ export { ParticleView } from './ParticleView';
2
+ export type { ParticleViewProps } from './ParticleView';
3
+ export { useParticlePresentation } from './useParticlePresentation';
4
+ export type { ParticlePresentation, SessionStatus } from './useParticlePresentation';
5
+ export { particleSpriteXform, assertUniformParticleSpriteRatio } from './spriteXForm';
6
+ export { cameraVisibleWorldBounds, screenVisibleBounds, visibleInBounds, PARTICLE_CULL_PADDING } from './culling';
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Particle sprite transform (T15-RF4).
3
+ *
4
+ * Atlas RSXform carries rotation AND uniform scale in its 2×2 part:
5
+ * \`scos = s·cosθ\`, \`ssin = s·sinθ\`. The pivot compensation uses the
6
+ * AUTHORED draw size (the definition's \`size\`), and the source rect stays
7
+ * the sheet frame — so the authored-to-source ratio scales the drawn sprite.
8
+ *
9
+ * v1 requires the authored size ratio to match the source frame ratio; a
10
+ * mismatch is a structured error (RSXform cannot express nonuniform scale).
11
+ */
12
+ import { ParticleError } from '../../particles/errors';
13
+
14
+ export interface ParticleSpriteXformInput {
15
+ /** Sampled CENTER position (surface or world units). */
16
+ readonly x: number;
17
+ readonly y: number;
18
+ /** Sampled rotation in radians. */
19
+ readonly rotation: number;
20
+ /** Sampled uniform scale (scaleOverLife domain). */
21
+ readonly scale: number;
22
+ /** Authored draw size (definition particle.size). */
23
+ readonly drawWidth: number;
24
+ readonly drawHeight: number;
25
+ /** Source frame size in sheet pixels. */
26
+ readonly frameWidth: number;
27
+ readonly frameHeight: number;
28
+ }
29
+
30
+ export interface ParticleSpriteXform {
31
+ readonly scos: number;
32
+ readonly ssin: number;
33
+ readonly tx: number;
34
+ readonly ty: number;
35
+ }
36
+
37
+ export function particleSpriteXform(input: ParticleSpriteXformInput): ParticleSpriteXform {
38
+ 'worklet';
39
+ // T15-SF2: Atlas draws the SOURCE rect, so the authored-to-source ratio
40
+ // must ride in scos/ssin or the drawn size ignores particle.size entirely.
41
+ const effScale = input.scale * (input.drawWidth / input.frameWidth);
42
+ const cos = Math.cos(input.rotation);
43
+ const sin = Math.sin(input.rotation);
44
+ // Center anchor pivot against the DRAWN (scaled source) extent.
45
+ const px = (input.frameWidth / 2) * effScale;
46
+ const py = (input.frameHeight / 2) * effScale;
47
+ return {
48
+ scos: effScale * cos,
49
+ ssin: effScale * sin,
50
+ tx: input.x - px * cos + py * sin,
51
+ ty: input.y - px * sin - py * cos,
52
+ };
53
+ }
54
+
55
+ /**
56
+ * Validate that the authored size ratio matches the source frame ratio so
57
+ * uniform-scale Atlas drawing preserves the intended aspect.
58
+ */
59
+ export function assertUniformParticleSpriteRatio(
60
+ drawWidth: number,
61
+ drawHeight: number,
62
+ frameWidth: number,
63
+ frameHeight: number,
64
+ ): void {
65
+ const drawRatio = drawWidth / drawHeight;
66
+ const frameRatio = frameWidth / frameHeight;
67
+ if (!Number.isFinite(drawRatio) || !Number.isFinite(frameRatio) || Math.abs(drawRatio - frameRatio) > 1e-3) {
68
+ throw new ParticleError(
69
+ `[rn-gamekit/particles] sprite effect size ${drawWidth}x${drawHeight} does not match source frame ${frameWidth}x${frameHeight} aspect — nonuniform sprite scaling is not supported in v1`,
70
+ );
71
+ }
72
+ }