rn-gamekit 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (601) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/README.md +95 -14
  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 +94 -4
  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,133 @@
1
+ /**
2
+ * Shared sprite frame selection (GS-ANIMATION-01).
3
+ *
4
+ * The single headless selection contract behind `Sprite`'s rect modifier
5
+ * and `GameSprite`'s frame-name derivation: an explicit frame wins,
6
+ * otherwise clip + elapsed time resolve through the pure sampler. Absent
7
+ * selection (nothing chosen yet) presents nothing without throwing;
8
+ * invalid clips and frames fail clearly instead of masking bad data.
9
+ *
10
+ * Headless-safe: only type imports plus the pure sampler, so the same
11
+ * functions execute identically in tests and on the UI runtime. Every
12
+ * function carries the worklet directive for UI execution; the reachable
13
+ * call graph is plain arithmetic plus plain `Error` construction
14
+ * (GS-ANIMATION-02).
15
+ */
16
+ import type { LoadedImage, LoadedSpriteSheet } from '../../assets/types';
17
+ import type { SpriteFrameRect } from './spriteTransform';
18
+ import { spriteFrameNameForClip } from '../../sprites/sampleSpriteClip';
19
+ import type { SharedValue } from 'react-native-reanimated';
20
+
21
+ /** A static value or a UI-runtime shared value carrying it. Shared-value
22
+ * payloads list both the exact and the undefined-extended shapes because
23
+ * shared values are invariant in their payload. */
24
+ export type SpriteSelectable<T> = T | SharedValue<T>;
25
+
26
+ /** Selection props as the Sprite/GameSprite call sites declare them. */
27
+ export type SpriteFrameProp =
28
+ | string
29
+ | SharedValue<string>
30
+ | SharedValue<string | undefined>
31
+ | undefined;
32
+ export type SpriteClipProp = string | SharedValue<string> | undefined;
33
+
34
+ /** The discrete selection inputs for one sprite (all optional). */
35
+ export interface SpriteSelection {
36
+ /** The exact frame name; overrides clip + elapsedMs. */
37
+ readonly frame?: string;
38
+ /** The clip to select from the sprite sheet. */
39
+ readonly clip?: string;
40
+ /** Elapsed time within the clip in milliseconds. */
41
+ readonly elapsedMs?: number;
42
+ }
43
+
44
+ /**
45
+ * Resolve the source rectangle for a selection.
46
+ *
47
+ * Returns `undefined` for absent selection (present nothing); throws for
48
+ * unknown clips and frames.
49
+ */
50
+ export function selectSpriteFrameRect(
51
+ source: LoadedImage | LoadedSpriteSheet,
52
+ selection: SpriteSelection,
53
+ ): SpriteFrameRect | undefined {
54
+ 'worklet';
55
+ if (source.descriptor.kind === 'image') {
56
+ const image = source as LoadedImage;
57
+ return { x: 0, y: 0, width: image.width, height: image.height };
58
+ }
59
+ const sheet = source as LoadedSpriteSheet;
60
+ let name = selection.frame;
61
+ if (name === undefined) {
62
+ if (selection.clip === undefined) {
63
+ return undefined;
64
+ }
65
+ name = spriteFrameNameForClip(
66
+ sheet.descriptor.animations,
67
+ selection.clip,
68
+ selection.elapsedMs ?? 0,
69
+ );
70
+ }
71
+ const rect = sheet.frames[name];
72
+ if (rect === undefined) {
73
+ throw new Error(
74
+ `frame ${JSON.stringify(name)} does not belong to this sprite sheet (loaded frames: ${Object.keys(sheet.frames).join(', ')})`,
75
+ );
76
+ }
77
+ return rect;
78
+ }
79
+
80
+ /**
81
+ * Materialize mixed static/shared selection props into one plain selection
82
+ * (GS-SPRITE-03): every worklet that resolves frames — rect, transform, and
83
+ * Group correction — starts from this single helper, so clip-driven frame
84
+ * changes reach every consumer coherently.
85
+ */
86
+ export function materializeSpriteSelection(
87
+ frame: SpriteFrameProp,
88
+ clip: SpriteClipProp,
89
+ elapsedMs: SpriteSelectable<number> | undefined,
90
+ ): SpriteSelection {
91
+ 'worklet';
92
+ const selection: {
93
+ frame?: string;
94
+ clip?: string;
95
+ elapsedMs?: number;
96
+ } = {};
97
+ const frameValue = typeof frame === 'string' ? frame : frame?.value;
98
+ if (frameValue !== undefined) {
99
+ selection.frame = frameValue;
100
+ }
101
+ const clipValue = typeof clip === 'string' ? clip : clip?.value;
102
+ if (clipValue !== undefined) {
103
+ selection.clip = clipValue;
104
+ }
105
+ const elapsedValue = typeof elapsedMs === 'number' ? elapsedMs : elapsedMs?.value;
106
+ if (elapsedValue !== undefined) {
107
+ selection.elapsedMs = elapsedValue;
108
+ }
109
+ return selection;
110
+ }
111
+
112
+ /** A Skia rect-buffer entry (structural: only `setXYWH` is used). */
113
+ export interface SpriteRectBuffer {
114
+ setXYWH(x: number, y: number, width: number, height: number): void;
115
+ }
116
+
117
+ /**
118
+ * Apply a selection to a rect-buffer entry: the component callback logic
119
+ * behind `Sprite`'s modifier, executed here so tests observe it directly.
120
+ */
121
+ export function applySpriteFrameSelection(
122
+ rect: SpriteRectBuffer,
123
+ source: LoadedImage | LoadedSpriteSheet,
124
+ selection: SpriteSelection,
125
+ ): void {
126
+ 'worklet';
127
+ const resolved = selectSpriteFrameRect(source, selection);
128
+ if (resolved === undefined) {
129
+ rect.setXYWH(0, 0, 0, 0);
130
+ return;
131
+ }
132
+ rect.setXYWH(resolved.x, resolved.y, resolved.width, resolved.height);
133
+ }
@@ -52,12 +52,19 @@ export function resolveSpriteFrameRect(
52
52
  * `[0, 0, frameWidth, frameHeight]` in local space and the documented pivot
53
53
  * order is:
54
54
  *
55
- * M = T(x, y) · R(rotation) · T(anchor) · S(scaleX, scaleY) · T(-anchor)
55
+ * M = T(x, y) · R(rotation) · S(scaleX, scaleY) · T(-anchor)
56
56
  *
57
- * i.e. scale and explicit flips happen around the anchor, then the frame
58
- * rotates around the anchor at the world position. The RSXform carries the
59
- * rotation + position (its 2x2 cannot express flips or non-uniform scale);
60
- * the wrapping Group applies the scale/flip part around the anchor.
57
+ * i.e. uniform scale and explicit flips happen around the anchor in the
58
+ * local frame, then the frame rotates around the anchor at the world
59
+ * position. The invariant: the anchor maps to `(x, y)` under every scale,
60
+ * rotation, and flip (GS-SPRITE-01).
61
+ *
62
+ * Split across Skia's retained primitives (the Atlas RSXform is innermost,
63
+ * the wrapping Group is outermost): the RSXform carries `T·R·S` with the
64
+ * pivot pre-compensated, so no-flip sprites need no Group transform at
65
+ * all; reflection — which an RSXform cannot express — is isolated in the
66
+ * Group as a mirror that fixes the world anchor
67
+ * (`T(x,y)·R·F·R⁻¹·T(−x,−y)`).
61
68
  */
62
69
  import type { SharedValue } from 'react-native-reanimated';
63
70
 
@@ -89,12 +96,13 @@ export interface SpriteRsxform {
89
96
  readonly ty: number;
90
97
  }
91
98
 
92
- /** A Skia-compatible 3x3 transform element list. */
99
+ /** A Skia-compatible 3x3 transform element list (rotation in radians). */
93
100
  export type SkiaTransformElement =
94
101
  | { readonly translateX: number }
95
102
  | { readonly translateY: number }
96
103
  | { readonly scaleX: number }
97
- | { readonly scaleY: number };
104
+ | { readonly scaleY: number }
105
+ | { readonly rotate: number };
98
106
 
99
107
  function readNumber(value: number | SharedValue<number>): number {
100
108
  'worklet';
@@ -107,46 +115,58 @@ function readBoolean(value: boolean | SharedValue<boolean>): boolean {
107
115
  }
108
116
 
109
117
  /**
110
- * The RSXform for the atlas path: rotation + position with the pivot
111
- * compensated (`tx = x - pivotX·cos + pivotY·sin`). Scale and flips are
112
- * applied by the wrapping Group (`spriteGroupCorrection`).
118
+ * The RSXform for the atlas path: `T(x,y)·R·S` with the pivot
119
+ * pre-compensated (`t = p − s·R·pivot`), so the anchor lands exactly on
120
+ * `(x, y)` (GS-SPRITE-01/02). Uniform scale is encoded in the
121
+ * coefficients; the batch path shares this helper and needs no Group.
113
122
  */
114
123
  export function computeSpriteRsxform(input: SpriteTransformInput): SpriteRsxform {
115
124
  'worklet';
116
125
  const x = readNumber(input.x);
117
126
  const y = readNumber(input.y);
118
127
  const rotation = readNumber(input.rotation);
128
+ const scale = readNumber(input.scale);
119
129
  const pivotX = input.anchorX * input.frameWidth;
120
130
  const pivotY = input.anchorY * input.frameHeight;
121
131
  const cos = Math.cos(rotation);
122
132
  const sin = Math.sin(rotation);
123
133
  return {
124
- scos: cos,
125
- ssin: sin,
126
- tx: x - pivotX * cos + pivotY * sin,
127
- ty: y - pivotX * sin - pivotY * cos,
134
+ scos: scale * cos,
135
+ ssin: scale * sin,
136
+ tx: x - scale * (pivotX * cos - pivotY * sin),
137
+ ty: y - scale * (pivotX * sin + pivotY * cos),
128
138
  };
129
139
  }
130
140
 
131
141
  /**
132
- * The scale/flip part around the anchor as a Skia transform element list:
133
- * `T(anchor) · S(scaleX, scaleY) · T(-anchor)` (the first element is the
134
- * outermost).
142
+ * The reflection part as a Skia transform element list, outermost first.
143
+ *
144
+ * Without flips the RSXform alone carries the transform, so the correction
145
+ * is empty (identity). With flips it is the anchor-fixing mirror
146
+ * `T(x,y)·R·F·R⁻¹·T(−x,−y)`: mirroring about the rotated anchor axes while
147
+ * the world anchor stays fixed. Depends on position and rotation (not just
148
+ * the pivot), so callers must derive it on the UI runtime from live values
149
+ * — never memoize it from stale React-render reads (GS-SPRITE-01).
135
150
  */
136
151
  export function spriteGroupCorrection(input: SpriteTransformInput): readonly SkiaTransformElement[] {
137
152
  'worklet';
138
- const scale = readNumber(input.scale);
139
153
  const flipX = readBoolean(input.flipX);
140
154
  const flipY = readBoolean(input.flipY);
141
- const pivotX = input.anchorX * input.frameWidth;
142
- const pivotY = input.anchorY * input.frameHeight;
155
+ if (!flipX && !flipY) {
156
+ return [];
157
+ }
158
+ const x = readNumber(input.x);
159
+ const y = readNumber(input.y);
160
+ const rotation = readNumber(input.rotation);
143
161
  return [
144
- { translateX: pivotX },
145
- { translateY: pivotY },
146
- { scaleX: flipX ? -scale : scale },
147
- { scaleY: flipY ? -scale : scale },
148
- { translateX: -pivotX },
149
- { translateY: -pivotY },
162
+ { translateX: x },
163
+ { translateY: y },
164
+ { rotate: rotation },
165
+ { scaleX: flipX ? -1 : 1 },
166
+ { scaleY: flipY ? -1 : 1 },
167
+ { rotate: -rotation },
168
+ { translateX: -x },
169
+ { translateY: -y },
150
170
  ];
151
171
  }
152
172
 
@@ -0,0 +1,274 @@
1
+ import { useContext, useMemo, useCallback } from 'react';
2
+ import {
3
+ Atlas,
4
+ Group,
5
+ useRectBuffer,
6
+ useRSXformBuffer,
7
+ } from '@shopify/react-native-skia';
8
+ import { useDerivedValue, useSharedValue, type SharedValue } from 'react-native-reanimated';
9
+ import { scheduleOnRN } from 'react-native-worklets';
10
+ import type { SkImage } from '@shopify/react-native-skia';
11
+
12
+ import { GameWorldContext, layerParallaxTransform2D } from '../sprites/GameWorld2D';
13
+ import type { CameraCut2D } from '../../camera2d/types';
14
+ import type { ResolvedViewport2D } from '../../viewport2d/types';
15
+ import type { TileMap2D } from '../../tilemap/types';
16
+ import {
17
+ buildFrameTable,
18
+ buildTileWindowSnapshot,
19
+ bindingGeneration,
20
+ updateTileLayerUI,
21
+ EMPTY_TILE_WINDOW,
22
+ type TileFrameTable,
23
+ type TileWindowSnapshot,
24
+ } from './tilePresentation';
25
+
26
+ export interface TileMapLayer2DProps {
27
+ /** The normalized immutable map. */
28
+ readonly map: TileMap2D;
29
+ /** Which layer to draw. */
30
+ readonly layer: string;
31
+ /**
32
+ * Decoded sheet plus resolved frame rectangles — resolve ONCE at bind
33
+ * time via the asset store. Frame dimensions must equal the map cell
34
+ * dimensions in v1.
35
+ */
36
+ readonly source: {
37
+ readonly image: SkImage;
38
+ readonly frames: Readonly<Record<string, { x: number; y: number; width: number; height: number }>>;
39
+ };
40
+ /** Surface size: px for screen space, world units for world space. */
41
+ readonly width: number;
42
+ readonly height: number;
43
+ /** Extra visible cells around the camera bounds. Default 1. */
44
+ readonly overscan?: number;
45
+ /**
46
+ * Coherent parallax contract (T16-RF2): ONE factor drives BOTH the visual
47
+ * correction applied to this layer's Atlas AND the culling bounds —
48
+ * callers never wrap this component in an outer GameLayer2D to duplicate
49
+ * the factor.
50
+ */
51
+ readonly parallax?: { readonly x: number; y: number };
52
+ /**
53
+ * Bounded zoom-out contract (T16-RF2): the slot buffer is sized for a
54
+ * camera zoomed out to AT MOST `1 / minZoom`. Presented cameras zooming
55
+ * below this bound are rejected — every slot hides and a one-shot RN-side
56
+ * diagnostic fires — rather than silently returning a partially filled
57
+ * region. Default 1 (no zoom-out headroom).
58
+ */
59
+ readonly minZoom?: number;
60
+ }
61
+
62
+ /**
63
+ * Stable-topology Atlas tile layer (T16.4, reworked per T16-F3/F4/RF1/RF2).
64
+ *
65
+ * One React node per layer. The slot buffer is sized from the passed
66
+ * surface bounds + minZoom + overscan + cell size — NOT from map
67
+ * dimensions. The worklet never touches the map value, `layer.data`, or a
68
+ * JS `Map`:
69
+ *
70
+ * - Frame rectangles are pre-resolved into a flat numeric table at bind
71
+ * time (validated: missing frames and cell/frame size mismatches throw
72
+ * structured bind errors).
73
+ * - A bounded window snapshot (ids sized by slot capacity) is built on JS
74
+ * and transferred via a shared value ONLY when the visible cell span
75
+ * outgrows the current window; requests cross to React through
76
+ * `scheduleOnRN` (Reanimated 4 / react-native-worklets), and camera
77
+ * interpolation inside the window is allocation-free scalar math.
78
+ * - Culling bounds derive from the presented camera (center/zoom/rotation)
79
+ * with the SAME parallax factor applied to the visual transform and the
80
+ * bounds; without a presented camera the viewport-only world path applies.
81
+ * - Culling here can never affect simulation: collision queries read full
82
+ * layer data through the private chunk index regardless of visibility.
83
+ */
84
+ export function TileMapLayer2D({
85
+ map, layer, source, width, height, overscan = 1, parallax, minZoom = 1,
86
+ }: TileMapLayer2DProps) {
87
+ const world = useContext(GameWorldContext);
88
+ const camera = (world?.camera ?? null) as
89
+ | SharedValue<CameraCut2D | undefined>
90
+ | null;
91
+ const viewportSV = (world?.viewport ?? null) as
92
+ | SharedValue<ResolvedViewport2D | undefined>
93
+ | null;
94
+
95
+ const layerData = map.layerById[layer];
96
+ if (layerData === undefined) {
97
+ throw new Error(`[rn-gamekit/tilemap] layer "${layer}" does not exist on this map`);
98
+ }
99
+ if (!(minZoom > 0) || !Number.isFinite(minZoom)) {
100
+ throw new Error(`[rn-gamekit/tilemap] minZoom must be a finite number > 0; got ${String(minZoom)}`);
101
+ }
102
+ if (!Number.isFinite(width) || width <= 0) {
103
+ throw new Error(`[rn-gamekit/tilemap] width must be a finite number > 0; got ${String(width)}`);
104
+ }
105
+ if (!Number.isFinite(height) || height <= 0) {
106
+ throw new Error(`[rn-gamekit/tilemap] height must be a finite number > 0; got ${String(height)}`);
107
+ }
108
+ if (!Number.isFinite(overscan) || overscan < 0 || !Number.isInteger(overscan)) {
109
+ throw new Error(`[rn-gamekit/tilemap] overscan must be a finite integer >= 0; got ${String(overscan)}`);
110
+ }
111
+ const px = parallax?.x ?? 1;
112
+ const py = parallax?.y ?? 1;
113
+ if (!Number.isFinite(px)) {
114
+ throw new Error(`[rn-gamekit/tilemap] parallax.x must be a finite number; got ${String(px)}`);
115
+ }
116
+ if (!Number.isFinite(py)) {
117
+ throw new Error(`[rn-gamekit/tilemap] parallax.y must be a finite number; got ${String(py)}`);
118
+ }
119
+
120
+ const cw = map.cellSize.width;
121
+ const ch = map.cellSize.height;
122
+ const originX = map.origin.x;
123
+ const originY = map.origin.y;
124
+ // Pad world is scalar based on the larger cell dimension (T16-SF2
125
+ // overscan contract). Capacity and bounds must share this exact scalar
126
+ // so they cannot drift for non-square cells.
127
+ const padWorld = overscan * Math.max(cw, ch);
128
+ // px/py already validated above
129
+
130
+ // Resolve frames ONCE at bind time (structured errors for missing
131
+ // frames and frame/cell size mismatches — T16-F3).
132
+ const frameTable: TileFrameTable = useMemo(
133
+ () => buildFrameTable(map.tileset, source.frames, cw, ch),
134
+ [map, source, cw, ch],
135
+ );
136
+
137
+ // Slot capacity covers the worst rotated AABB at minZoom (T16-SF2):
138
+ // conservative extents approach the viewport diagonal at 45 degrees.
139
+ // Must use the same padWorld as writeLayerVisibleBounds so non-square
140
+ // cells (e.g. 8x64) do not under-size one axis.
141
+ const diagonal = Math.hypot(width, height);
142
+ const slotsX = Math.ceil((diagonal / minZoom + 2 * padWorld) / cw) + 1;
143
+ const slotsY = Math.ceil((diagonal / minZoom + 2 * padWorld) / ch) + 1;
144
+ const capacity = slotsX * slotsY;
145
+
146
+ const rects = useRectBuffer(capacity, (rect) => {
147
+ 'worklet';
148
+ rect.setXYWH(0, 0, 0, 0);
149
+ });
150
+ const xforms = useRSXformBuffer(capacity, (xform) => {
151
+ 'worklet';
152
+ xform.set(1, 0, 0, 0);
153
+ });
154
+
155
+ // Bounded transferred window + guards (T16-F4, T16-SF1). The scratch
156
+ // bounds object is written by the worklet every frame — one stable
157
+ // allocation, never per-frame objects (T16-RF2).
158
+ const windowSV = useSharedValue<TileWindowSnapshot>(EMPTY_TILE_WINDOW);
159
+ // GS-TILE-01: one pending request per BINDING (not per component): the
160
+ // stored generation lets a new binding request even when an old binding
161
+ // left its mark behind.
162
+ const pendingGenSV = useSharedValue(-1);
163
+ const warnedCapacitySV = useSharedValue(false);
164
+ const capacityWarnPendingSV = useSharedValue(false);
165
+
166
+ // GS-TILE-01: binding identity from everything that defines what a
167
+ // window shows — map, layer, frame source, cell size, and
168
+ // capacity-affecting configuration. A fresh identity mints a fresh
169
+ // generation; windows and requests stamped with older generations are
170
+ // ignored, never displayed.
171
+ // Binding-affecting inputs enumerated deliberately: equivalent values
172
+ // must not remint the identity (no reload churn), and any omitted input
173
+ // would reuse a stale window.
174
+ const bindingKey = useMemo(
175
+ () => ({}),
176
+ [map, layer, source.frames, cw, ch, overscan, capacity, px, py],
177
+ );
178
+ const generation = bindingGeneration(bindingKey);
179
+
180
+ // JS handler (React-owned): builds the next bounded snapshot for the
181
+ // requested range. Delivered via scheduleOnRN from the worklet (RF1).
182
+ // GS-TILE-01: the scheduled generation is checked before publishing, and
183
+ // the published window is stamped — the update refuses windows whose
184
+ // stamp differs from the live binding, so late deliveries converge by
185
+ // re-requesting instead of displaying stale tiles.
186
+ const requestWindow = useCallback(
187
+ (gen: number, x0: number, y0: number, x1: number, y1: number) => {
188
+ if (gen !== generation) {
189
+ return;
190
+ }
191
+ // Pad by the overscan so small camera motions don't re-request.
192
+ const snapshot = buildTileWindowSnapshot(
193
+ map,
194
+ layerData.id,
195
+ x0 - overscan,
196
+ y0 - overscan,
197
+ x1 + overscan,
198
+ y1 + overscan,
199
+ frameTable,
200
+ );
201
+ windowSV.value = Object.freeze({ ...snapshot, gen });
202
+ if (pendingGenSV.value === gen) {
203
+ pendingGenSV.value = -1;
204
+ }
205
+ },
206
+ [map, layerData.id, overscan, frameTable, generation, windowSV, pendingGenSV],
207
+ );
208
+
209
+ // One-shot RN-side diagnostic when a presented camera zooms beyond the
210
+ // declared capacity (T16-RF2): the layer hides instead of under-filling.
211
+ // Uses its own pending guard so the warning never blocks window requests
212
+ // (T16-SF1).
213
+ const onBeyondCapacity = useCallback(() => {
214
+ capacityWarnPendingSV.value = false;
215
+ if (!warnedCapacitySV.value) {
216
+ warnedCapacitySV.value = true;
217
+ console.warn(
218
+ '[rn-gamekit/tilemap] presented camera zoom is below minZoom; tile layer hides until the camera returns inside the declared capacity',
219
+ );
220
+ }
221
+ }, [warnedCapacitySV, capacityWarnPendingSV]);
222
+
223
+ // originX/Y and padWorld already defined above for capacity sizing
224
+
225
+ // GS-TILE-01: the update body lives in `updateTileLayerUI` with an
226
+ // explicit scalar-only parameter list — the worklet closure provably
227
+ // carries no map, layer, or frame-table objects (only layer dims and the
228
+ // binding generation). requestWindow's closure stays on the JS side.
229
+ useDerivedValue(() => {
230
+ 'worklet';
231
+ return updateTileLayerUI({
232
+ camera: camera as never,
233
+ viewport: viewportSV as never,
234
+ window: windowSV,
235
+ pendingGen: pendingGenSV,
236
+ warnedCapacity: warnedCapacitySV,
237
+ capacityWarnPending: capacityWarnPendingSV,
238
+ rects,
239
+ xforms,
240
+ requestWindow,
241
+ scheduleOnRN: (fn) => scheduleOnRN(fn),
242
+ onBeyondCapacity,
243
+ generation,
244
+ capacity,
245
+ originX,
246
+ originY,
247
+ cw,
248
+ ch,
249
+ layerWidth: layerData.width,
250
+ layerHeight: layerData.height,
251
+ padWorld,
252
+ px,
253
+ py,
254
+ minZoom,
255
+ });
256
+ });
257
+
258
+ // Coherent parallax: the visual correction uses the SAME factor as the
259
+ // culling bounds above, so callers never wrap this component in an outer
260
+ // GameLayer2D (T16-RF2). At factor 1 no transform applies.
261
+ const visualTransform = useDerivedValue(() => {
262
+ 'worklet';
263
+ if (px === 1 && py === 1) {
264
+ return [];
265
+ }
266
+ return layerParallaxTransform2D(camera?.value, viewportSV?.value, px, py);
267
+ });
268
+
269
+ const atlas = <Atlas image={source.image} sprites={rects} transforms={xforms} />;
270
+ if (px === 1 && py === 1) {
271
+ return atlas;
272
+ }
273
+ return <Group transform={visualTransform as never}>{atlas}</Group>;
274
+ }