kiwiengine 0.0.1-alpha → 0.5.2

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 (438) hide show
  1. package/README.ko.md +550 -0
  2. package/README.md +575 -4
  3. package/examples/collision-test/assets/cat.png +0 -0
  4. package/examples/collision-test/dist/game.js +2 -0
  5. package/examples/collision-test/dist/game.js.LICENSE.txt +35 -0
  6. package/examples/collision-test/index.ts +30 -0
  7. package/examples/dom-particle-test/assets/bird.png +0 -0
  8. package/examples/dom-particle-test/dist/game.js +2 -0
  9. package/examples/dom-particle-test/dist/game.js.LICENSE.txt +35 -0
  10. package/examples/dom-particle-test/index.html +24 -0
  11. package/examples/dom-particle-test/index.ts +27 -0
  12. package/examples/dom-sprite-test/assets/bird.png +0 -0
  13. package/examples/dom-sprite-test/assets/fire.png +0 -0
  14. package/examples/dom-sprite-test/assets/run.png +0 -0
  15. package/examples/dom-sprite-test/dist/game.js +2 -0
  16. package/examples/dom-sprite-test/dist/game.js.LICENSE.txt +35 -0
  17. package/examples/dom-sprite-test/index.html +24 -0
  18. package/examples/dom-sprite-test/index.ts +38 -0
  19. package/examples/dom-test/dist/game.js +2 -0
  20. package/examples/dom-test/dist/game.js.LICENSE.txt +35 -0
  21. package/examples/dom-test/index.html +24 -0
  22. package/examples/dom-test/index.ts +22 -0
  23. package/examples/flappy-cat/assets/bgm/bgm.ogg +0 -0
  24. package/examples/flappy-cat/assets/images/base.png +0 -0
  25. package/examples/flappy-cat/assets/images/bg.png +0 -0
  26. package/examples/flappy-cat/assets/images/cat.png +0 -0
  27. package/examples/flappy-cat/assets/images/pipe-green.png +0 -0
  28. package/examples/flappy-cat/assets/images/pipe-red.png +0 -0
  29. package/examples/flappy-cat/assets/sfx/die.wav +0 -0
  30. package/examples/flappy-cat/assets/sfx/hit.wav +0 -0
  31. package/examples/flappy-cat/assets/sfx/point.wav +0 -0
  32. package/examples/flappy-cat/assets/sfx/wing.wav +0 -0
  33. package/examples/flappy-cat/dist/game.js +0 -0
  34. package/examples/flappy-cat/index.html +24 -0
  35. package/examples/flappy-cat/index.ts +0 -0
  36. package/examples/particle-test/assets/bird.png +0 -0
  37. package/examples/particle-test/dist/game.js +2 -0
  38. package/examples/particle-test/dist/game.js.LICENSE.txt +35 -0
  39. package/examples/particle-test/index.html +24 -0
  40. package/examples/particle-test/index.ts +30 -0
  41. package/examples/renderer-test/dist/game.js +2 -0
  42. package/examples/renderer-test/dist/game.js.LICENSE.txt +35 -0
  43. package/examples/renderer-test/index.html +24 -0
  44. package/examples/renderer-test/index.ts +9 -0
  45. package/examples/simple-battle/assets/bgm/battle.mp3 +0 -0
  46. package/examples/simple-battle/assets/bitmap-fonts/white-peaberry.fnt +107 -0
  47. package/examples/simple-battle/assets/bitmap-fonts/white-peaberry.png +0 -0
  48. package/examples/simple-battle/assets/joystick/joystick.png +0 -0
  49. package/examples/simple-battle/assets/joystick/knob.png +0 -0
  50. package/examples/simple-battle/assets/sfx/hero/die/die.wav +0 -0
  51. package/examples/simple-battle/assets/sfx/hero/heal/heal.wav +0 -0
  52. package/examples/simple-battle/assets/sfx/hero/hit/hit1.wav +0 -0
  53. package/examples/simple-battle/assets/sfx/hero/hit/hit2.wav +0 -0
  54. package/examples/simple-battle/assets/sfx/hero/hit/hit3.wav +0 -0
  55. package/examples/simple-battle/assets/sfx/hero/miss/miss1.wav +0 -0
  56. package/examples/simple-battle/assets/sfx/hero/miss/miss2.wav +0 -0
  57. package/examples/simple-battle/assets/sfx/hero/miss/miss3.wav +0 -0
  58. package/examples/simple-battle/assets/sfx/orc/die/die.wav +0 -0
  59. package/examples/simple-battle/assets/sfx/orc/hit/hit1.wav +0 -0
  60. package/examples/simple-battle/assets/sfx/orc/hit/hit2.wav +0 -0
  61. package/examples/simple-battle/assets/sfx/orc/hit/hit3.wav +0 -0
  62. package/examples/simple-battle/assets/sfx/orc/miss/miss1.wav +0 -0
  63. package/examples/simple-battle/assets/sfx/orc/miss/miss2.wav +0 -0
  64. package/examples/simple-battle/assets/sfx/orc/miss/miss3.wav +0 -0
  65. package/examples/simple-battle/assets/spritesheets/hero-atlas.json +289 -0
  66. package/examples/simple-battle/assets/spritesheets/hero.png +0 -0
  67. package/examples/simple-battle/assets/spritesheets/orc-atlas.json +289 -0
  68. package/examples/simple-battle/assets/spritesheets/orc.png +0 -0
  69. package/examples/simple-battle/assets/spritesheets/potion-atlas.json +83 -0
  70. package/examples/simple-battle/assets/spritesheets/potion.png +0 -0
  71. package/examples/simple-battle/dist/game.js +2 -0
  72. package/examples/simple-battle/dist/game.js.LICENSE.txt +35 -0
  73. package/examples/simple-battle/hud/damage-text.ts +45 -0
  74. package/examples/simple-battle/hud/heal-text.ts +45 -0
  75. package/examples/simple-battle/hud/hp-bar.ts +38 -0
  76. package/examples/simple-battle/index.html +24 -0
  77. package/examples/simple-battle/index.ts +41 -0
  78. package/examples/simple-battle/objects/character.ts +95 -0
  79. package/examples/simple-battle/objects/hero.ts +113 -0
  80. package/examples/simple-battle/objects/orc.ts +109 -0
  81. package/examples/simple-battle/objects/potion.ts +29 -0
  82. package/examples/simple-battle/stage.ts +176 -0
  83. package/examples/spine-test/assets/spine/spineboy.atlas +95 -0
  84. package/examples/spine-test/assets/spine/spineboy.png +0 -0
  85. package/examples/spine-test/assets/spine/spineboy.skel +0 -0
  86. package/examples/spine-test/dist/game.js +2 -0
  87. package/examples/spine-test/dist/game.js.LICENSE.txt +35 -0
  88. package/examples/spine-test/index.html +24 -0
  89. package/examples/spine-test/index.ts +29 -0
  90. package/examples/sprite-test/assets/bird.png +0 -0
  91. package/examples/sprite-test/assets/fire.png +0 -0
  92. package/examples/sprite-test/dist/game.js +2 -0
  93. package/examples/sprite-test/dist/game.js.LICENSE.txt +35 -0
  94. package/examples/sprite-test/index.html +24 -0
  95. package/examples/sprite-test/index.ts +41 -0
  96. package/examples/tsconfig.json +2 -1
  97. package/examples/webpack.config.js +14 -3
  98. package/jest.config.ts +10 -0
  99. package/lib/asset/audio.js +47 -11
  100. package/lib/asset/audio.js.map +1 -1
  101. package/lib/asset/loaders/audio.js +3 -3
  102. package/lib/asset/loaders/audio.js.map +1 -1
  103. package/lib/asset/loaders/binary.js +3 -3
  104. package/lib/asset/loaders/binary.js.map +1 -1
  105. package/lib/asset/loaders/bitmap-font.js +71 -0
  106. package/lib/asset/loaders/bitmap-font.js.map +1 -0
  107. package/lib/asset/loaders/font.js +1 -1
  108. package/lib/asset/loaders/font.js.map +1 -1
  109. package/lib/asset/loaders/loader.js +17 -12
  110. package/lib/asset/loaders/loader.js.map +1 -1
  111. package/lib/asset/loaders/spritesheet.js +6 -7
  112. package/lib/asset/loaders/spritesheet.js.map +1 -1
  113. package/lib/asset/loaders/text.js +3 -3
  114. package/lib/asset/loaders/text.js.map +1 -1
  115. package/lib/asset/loaders/texture.js +5 -4
  116. package/lib/asset/loaders/texture.js.map +1 -1
  117. package/lib/asset/preload.js +60 -56
  118. package/lib/asset/preload.js.map +1 -1
  119. package/lib/collision/check-collision.js +804 -0
  120. package/lib/collision/check-collision.js.map +1 -0
  121. package/lib/collision/check-collision.test.js +300 -0
  122. package/lib/collision/check-collision.test.js.map +1 -0
  123. package/lib/collision/colliders.js +8 -0
  124. package/lib/collision/colliders.js.map +1 -0
  125. package/lib/debug.js.map +1 -0
  126. package/lib/dom/dom-animated-sprite.js +121 -0
  127. package/lib/dom/dom-animated-sprite.js.map +1 -0
  128. package/lib/dom/dom-game-object.js +106 -0
  129. package/lib/dom/dom-game-object.js.map +1 -0
  130. package/lib/dom/dom-particle.js +105 -0
  131. package/lib/dom/dom-particle.js.map +1 -0
  132. package/lib/dom/dom-preload.js +43 -0
  133. package/lib/dom/dom-preload.js.map +1 -0
  134. package/lib/dom/dom-sprite.js +40 -0
  135. package/lib/dom/dom-sprite.js.map +1 -0
  136. package/lib/dom/dom-texture-loader.js +36 -0
  137. package/lib/dom/dom-texture-loader.js.map +1 -0
  138. package/lib/dom/dom-utils.js +20 -0
  139. package/lib/dom/dom-utils.js.map +1 -0
  140. package/lib/index copy.js +16 -0
  141. package/lib/index copy.js.map +1 -0
  142. package/lib/index.js +35 -10
  143. package/lib/index.js.map +1 -1
  144. package/lib/input/joystick.js +262 -0
  145. package/lib/input/joystick.js.map +1 -0
  146. package/lib/node/core/dirty-number.js +38 -0
  147. package/lib/node/core/dirty-number.js.map +1 -0
  148. package/lib/node/core/game-node.js +63 -0
  149. package/lib/node/core/game-node.js.map +1 -0
  150. package/lib/node/core/game-object.js +8 -0
  151. package/lib/node/core/game-object.js.map +1 -0
  152. package/lib/node/core/renderable.js +52 -0
  153. package/lib/node/core/renderable.js.map +1 -0
  154. package/lib/node/core/transform.js +59 -0
  155. package/lib/node/core/transform.js.map +1 -0
  156. package/lib/node/core/transformable.js +85 -0
  157. package/lib/node/core/transformable.js.map +1 -0
  158. package/lib/node/ext/animated-sprite.js +96 -0
  159. package/lib/node/ext/animated-sprite.js.map +1 -0
  160. package/lib/node/ext/bitmap-text.js +89 -0
  161. package/lib/node/ext/bitmap-text.js.map +1 -0
  162. package/lib/node/ext/circle.js +28 -0
  163. package/lib/node/ext/circle.js.map +1 -0
  164. package/lib/node/ext/deplay.js +20 -0
  165. package/lib/node/ext/deplay.js.map +1 -0
  166. package/lib/node/ext/dom-container.js +51 -0
  167. package/lib/node/ext/dom-container.js.map +1 -0
  168. package/lib/node/ext/interval.js +20 -0
  169. package/lib/node/ext/interval.js.map +1 -0
  170. package/lib/node/ext/particle.js +98 -0
  171. package/lib/node/ext/particle.js.map +1 -0
  172. package/lib/node/ext/rectangle.js +32 -0
  173. package/lib/node/ext/rectangle.js.map +1 -0
  174. package/lib/node/ext/spine.js +272 -0
  175. package/lib/node/ext/spine.js.map +1 -0
  176. package/lib/node/ext/sprite.js +42 -0
  177. package/lib/node/ext/sprite.js.map +1 -0
  178. package/lib/node/physics/physics-object.js +112 -0
  179. package/lib/node/physics/physics-object.js.map +1 -0
  180. package/lib/node/physics/physics-world.js +27 -0
  181. package/lib/node/physics/physics-world.js.map +1 -0
  182. package/lib/renderer/camera.js +19 -0
  183. package/lib/renderer/camera.js.map +1 -0
  184. package/lib/renderer/container-manager.js +29 -0
  185. package/lib/renderer/container-manager.js.map +1 -0
  186. package/lib/renderer/fps-display.js +18 -0
  187. package/lib/renderer/fps-display.js.map +1 -0
  188. package/lib/renderer/layer.js +12 -0
  189. package/lib/renderer/layer.js.map +1 -0
  190. package/lib/renderer/renderer.js +145 -0
  191. package/lib/renderer/renderer.js.map +1 -0
  192. package/lib/renderer/ticker.js +56 -0
  193. package/lib/renderer/ticker.js.map +1 -0
  194. package/lib/renderer/ticker.test.js +241 -0
  195. package/lib/renderer/ticker.test.js.map +1 -0
  196. package/lib/types/asset/audio.d.ts +5 -4
  197. package/lib/types/asset/audio.d.ts.map +1 -1
  198. package/lib/types/asset/loaders/audio.d.ts +1 -1
  199. package/lib/types/asset/loaders/audio.d.ts.map +1 -1
  200. package/lib/types/asset/loaders/binary.d.ts +1 -1
  201. package/lib/types/asset/loaders/binary.d.ts.map +1 -1
  202. package/lib/types/asset/loaders/bitmap-font.d.ts +16 -0
  203. package/lib/types/asset/loaders/bitmap-font.d.ts.map +1 -0
  204. package/lib/types/asset/loaders/font.d.ts +1 -1
  205. package/lib/types/asset/loaders/font.d.ts.map +1 -1
  206. package/lib/types/asset/loaders/loader.d.ts +6 -6
  207. package/lib/types/asset/loaders/loader.d.ts.map +1 -1
  208. package/lib/types/asset/loaders/spritesheet.d.ts +5 -5
  209. package/lib/types/asset/loaders/spritesheet.d.ts.map +1 -1
  210. package/lib/types/asset/loaders/text.d.ts +1 -1
  211. package/lib/types/asset/loaders/text.d.ts.map +1 -1
  212. package/lib/types/asset/loaders/texture.d.ts +2 -2
  213. package/lib/types/asset/loaders/texture.d.ts.map +1 -1
  214. package/lib/types/asset/preload.d.ts +5 -3
  215. package/lib/types/asset/preload.d.ts.map +1 -1
  216. package/lib/types/bitmap-font.js +2 -0
  217. package/lib/types/bitmap-font.js.map +1 -0
  218. package/lib/types/collision/check-collision.d.ts +4 -0
  219. package/lib/types/collision/check-collision.d.ts.map +1 -0
  220. package/lib/types/collision/check-collision.test.d.ts +2 -0
  221. package/lib/types/collision/check-collision.test.d.ts.map +1 -0
  222. package/lib/types/collision/colliders.d.ts +34 -0
  223. package/lib/types/collision/colliders.d.ts.map +1 -0
  224. package/lib/types/debug.d.ts.map +1 -0
  225. package/lib/types/dom/dom-animated-sprite.d.ts +29 -0
  226. package/lib/types/dom/dom-animated-sprite.d.ts.map +1 -0
  227. package/lib/types/dom/dom-game-object.d.ts +44 -0
  228. package/lib/types/dom/dom-game-object.d.ts.map +1 -0
  229. package/lib/types/dom/dom-particle.d.ts +30 -0
  230. package/lib/types/dom/dom-particle.d.ts.map +1 -0
  231. package/lib/types/dom/dom-preload.d.ts +2 -0
  232. package/lib/types/dom/dom-preload.d.ts.map +1 -0
  233. package/lib/types/dom/dom-sprite.d.ts +13 -0
  234. package/lib/types/dom/dom-sprite.d.ts.map +1 -0
  235. package/lib/types/dom/dom-texture-loader.d.ts +8 -0
  236. package/lib/types/dom/dom-texture-loader.d.ts.map +1 -0
  237. package/lib/types/dom/dom-utils.d.ts +3 -0
  238. package/lib/types/dom/dom-utils.d.ts.map +1 -0
  239. package/lib/types/index copy.d.ts +16 -0
  240. package/lib/types/index copy.d.ts.map +1 -0
  241. package/lib/types/index.d.ts +25 -11
  242. package/lib/types/index.d.ts.map +1 -1
  243. package/lib/types/input/joystick.d.ts +28 -0
  244. package/lib/types/input/joystick.d.ts.map +1 -0
  245. package/lib/types/node/core/dirty-number.d.ts +17 -0
  246. package/lib/types/node/core/dirty-number.d.ts.map +1 -0
  247. package/lib/types/node/core/game-node.d.ts +16 -0
  248. package/lib/types/node/core/game-node.d.ts.map +1 -0
  249. package/lib/types/node/core/game-object.d.ts +8 -0
  250. package/lib/types/node/core/game-object.d.ts.map +1 -0
  251. package/lib/types/node/core/renderable.d.ts +22 -0
  252. package/lib/types/node/core/renderable.d.ts.map +1 -0
  253. package/lib/types/node/core/transform.d.ts +25 -0
  254. package/lib/types/node/core/transform.d.ts.map +1 -0
  255. package/lib/types/node/core/transformable.d.ts +44 -0
  256. package/lib/types/node/core/transformable.d.ts.map +1 -0
  257. package/lib/types/node/ext/animated-sprite.d.ts +28 -0
  258. package/lib/types/node/ext/animated-sprite.d.ts.map +1 -0
  259. package/lib/types/node/ext/bitmap-text.d.ts +14 -0
  260. package/lib/types/node/ext/bitmap-text.d.ts.map +1 -0
  261. package/lib/types/node/ext/circle.d.ts +19 -0
  262. package/lib/types/node/ext/circle.d.ts.map +1 -0
  263. package/lib/types/node/ext/deplay.d.ts +8 -0
  264. package/lib/types/node/ext/deplay.d.ts.map +1 -0
  265. package/lib/types/node/ext/dom-container.d.ts +12 -0
  266. package/lib/types/node/ext/dom-container.d.ts.map +1 -0
  267. package/lib/types/node/ext/interval.d.ts +9 -0
  268. package/lib/types/node/ext/interval.d.ts.map +1 -0
  269. package/lib/types/node/ext/particle.d.ts +30 -0
  270. package/lib/types/node/ext/particle.d.ts.map +1 -0
  271. package/lib/types/node/ext/rectangle.d.ts +22 -0
  272. package/lib/types/node/ext/rectangle.d.ts.map +1 -0
  273. package/lib/types/node/ext/spine.d.ts +36 -0
  274. package/lib/types/node/ext/spine.d.ts.map +1 -0
  275. package/lib/types/node/ext/sprite.d.ts +13 -0
  276. package/lib/types/node/ext/sprite.d.ts.map +1 -0
  277. package/lib/types/node/physics/physics-object.d.ts +38 -0
  278. package/lib/types/node/physics/physics-object.d.ts.map +1 -0
  279. package/lib/types/node/physics/physics-world.d.ts +18 -0
  280. package/lib/types/node/physics/physics-world.d.ts.map +1 -0
  281. package/lib/types/renderer/camera.d.ts +13 -0
  282. package/lib/types/renderer/camera.d.ts.map +1 -0
  283. package/lib/types/renderer/container-manager.d.ts +9 -0
  284. package/lib/types/renderer/container-manager.d.ts.map +1 -0
  285. package/lib/types/renderer/fps-display.d.ts +7 -0
  286. package/lib/types/renderer/fps-display.d.ts.map +1 -0
  287. package/lib/types/renderer/layer.d.ts +7 -0
  288. package/lib/types/renderer/layer.d.ts.map +1 -0
  289. package/lib/types/renderer/renderer.d.ts +40 -0
  290. package/lib/types/renderer/renderer.d.ts.map +1 -0
  291. package/lib/types/renderer/ticker.d.ts +6 -0
  292. package/lib/types/renderer/ticker.d.ts.map +1 -0
  293. package/lib/types/renderer/ticker.test.d.ts +40 -0
  294. package/lib/types/renderer/ticker.test.d.ts.map +1 -0
  295. package/lib/types/types/bitmap-font.d.ts +18 -0
  296. package/lib/types/types/bitmap-font.d.ts.map +1 -0
  297. package/lib/types/utils/device.d.ts +2 -0
  298. package/lib/types/utils/device.d.ts.map +1 -0
  299. package/lib/utils/device.js +2 -0
  300. package/lib/utils/device.js.map +1 -0
  301. package/package.json +8 -7
  302. package/src/asset/audio.ts +134 -90
  303. package/src/asset/loaders/audio.ts +19 -19
  304. package/src/asset/loaders/binary.ts +16 -16
  305. package/src/asset/loaders/bitmap-font.ts +85 -0
  306. package/src/asset/loaders/font.ts +14 -14
  307. package/src/asset/loaders/loader.ts +27 -23
  308. package/src/asset/loaders/spritesheet.ts +34 -36
  309. package/src/asset/loaders/text.ts +15 -15
  310. package/src/asset/loaders/texture.ts +29 -28
  311. package/src/asset/preload.ts +75 -64
  312. package/src/collision/check-collision.test.ts +349 -0
  313. package/src/collision/check-collision.ts +821 -0
  314. package/src/collision/colliders.ts +19 -0
  315. package/src/debug.ts +5 -0
  316. package/src/dom/dom-animated-sprite.ts +153 -0
  317. package/src/dom/dom-game-object.ts +131 -0
  318. package/src/dom/dom-particle.ts +151 -0
  319. package/src/dom/dom-preload.ts +54 -0
  320. package/src/dom/dom-sprite.ts +50 -0
  321. package/src/dom/dom-texture-loader.ts +44 -0
  322. package/src/dom/dom-utils.ts +19 -0
  323. package/src/index.ts +46 -13
  324. package/src/input/joystick.ts +316 -0
  325. package/src/node/core/dirty-number.ts +45 -0
  326. package/src/node/core/game-node.ts +74 -0
  327. package/src/node/core/game-object.ts +11 -0
  328. package/src/node/core/renderable.ts +65 -0
  329. package/src/node/core/transform.ts +70 -0
  330. package/src/node/core/transformable.ts +111 -0
  331. package/src/node/ext/animated-sprite.ts +123 -0
  332. package/src/node/ext/bitmap-text.ts +109 -0
  333. package/src/node/ext/circle.ts +40 -0
  334. package/src/node/ext/deplay.ts +24 -0
  335. package/src/node/ext/dom-container.ts +62 -0
  336. package/src/node/ext/interval.ts +24 -0
  337. package/src/node/ext/particle.ts +142 -0
  338. package/src/node/ext/rectangle.ts +51 -0
  339. package/src/node/ext/spine.ts +323 -0
  340. package/src/node/ext/sprite.ts +53 -0
  341. package/src/node/physics/physics-object.ts +156 -0
  342. package/src/node/physics/physics-world.ts +40 -0
  343. package/src/renderer/camera.ts +25 -0
  344. package/src/renderer/container-manager.ts +36 -0
  345. package/src/renderer/fps-display.ts +21 -0
  346. package/src/renderer/layer.ts +15 -0
  347. package/src/renderer/renderer.ts +180 -0
  348. package/src/renderer/ticker.test.ts +325 -0
  349. package/src/renderer/ticker.ts +54 -0
  350. package/src/types/bitmap-font.ts +19 -0
  351. package/src/utils/device.ts +1 -0
  352. package/examples/test-dom/index.ts +0 -21
  353. package/lib/game-object/game-object-physics.js +0 -188
  354. package/lib/game-object/game-object-physics.js.map +0 -1
  355. package/lib/game-object/game-object-rendering.js +0 -35
  356. package/lib/game-object/game-object-rendering.js.map +0 -1
  357. package/lib/game-object/game-object.js +0 -162
  358. package/lib/game-object/game-object.js.map +0 -1
  359. package/lib/game-object/transform.js +0 -118
  360. package/lib/game-object/transform.js.map +0 -1
  361. package/lib/game-object-ext/animated-sprite.js +0 -117
  362. package/lib/game-object-ext/animated-sprite.js.map +0 -1
  363. package/lib/game-object-ext/dom-container.js +0 -56
  364. package/lib/game-object-ext/dom-container.js.map +0 -1
  365. package/lib/game-object-ext/rect.js +0 -30
  366. package/lib/game-object-ext/rect.js.map +0 -1
  367. package/lib/game-object-ext/spine.js +0 -206
  368. package/lib/game-object-ext/spine.js.map +0 -1
  369. package/lib/game-object-ext/sprite.js +0 -46
  370. package/lib/game-object-ext/sprite.js.map +0 -1
  371. package/lib/game-object-ext/text.js +0 -68
  372. package/lib/game-object-ext/text.js.map +0 -1
  373. package/lib/game-object-ext/tiling-sprite.js +0 -64
  374. package/lib/game-object-ext/tiling-sprite.js.map +0 -1
  375. package/lib/types/game-object/game-object-physics.d.ts +0 -42
  376. package/lib/types/game-object/game-object-physics.d.ts.map +0 -1
  377. package/lib/types/game-object/game-object-rendering.d.ts +0 -15
  378. package/lib/types/game-object/game-object-rendering.d.ts.map +0 -1
  379. package/lib/types/game-object/game-object.d.ts +0 -81
  380. package/lib/types/game-object/game-object.d.ts.map +0 -1
  381. package/lib/types/game-object/transform.d.ts +0 -43
  382. package/lib/types/game-object/transform.d.ts.map +0 -1
  383. package/lib/types/game-object-ext/animated-sprite.d.ts +0 -29
  384. package/lib/types/game-object-ext/animated-sprite.d.ts.map +0 -1
  385. package/lib/types/game-object-ext/dom-container.d.ts +0 -16
  386. package/lib/types/game-object-ext/dom-container.d.ts.map +0 -1
  387. package/lib/types/game-object-ext/rect.d.ts +0 -17
  388. package/lib/types/game-object-ext/rect.d.ts.map +0 -1
  389. package/lib/types/game-object-ext/spine.d.ts +0 -35
  390. package/lib/types/game-object-ext/spine.d.ts.map +0 -1
  391. package/lib/types/game-object-ext/sprite.d.ts +0 -14
  392. package/lib/types/game-object-ext/sprite.d.ts.map +0 -1
  393. package/lib/types/game-object-ext/text.d.ts +0 -26
  394. package/lib/types/game-object-ext/text.d.ts.map +0 -1
  395. package/lib/types/game-object-ext/tiling-sprite.d.ts +0 -20
  396. package/lib/types/game-object-ext/tiling-sprite.d.ts.map +0 -1
  397. package/lib/types/utils/debug.d.ts.map +0 -1
  398. package/lib/types/utils/go.d.ts +0 -26
  399. package/lib/types/utils/go.d.ts.map +0 -1
  400. package/lib/types/world/world-debug.d.ts +0 -11
  401. package/lib/types/world/world-debug.d.ts.map +0 -1
  402. package/lib/types/world/world-physics.d.ts +0 -16
  403. package/lib/types/world/world-physics.d.ts.map +0 -1
  404. package/lib/types/world/world-rendering.d.ts +0 -28
  405. package/lib/types/world/world-rendering.d.ts.map +0 -1
  406. package/lib/types/world/world.d.ts +0 -38
  407. package/lib/types/world/world.d.ts.map +0 -1
  408. package/lib/utils/debug.js.map +0 -1
  409. package/lib/utils/go.js +0 -33
  410. package/lib/utils/go.js.map +0 -1
  411. package/lib/world/world-debug.js +0 -89
  412. package/lib/world/world-debug.js.map +0 -1
  413. package/lib/world/world-physics.js +0 -45
  414. package/lib/world/world-physics.js.map +0 -1
  415. package/lib/world/world-rendering.js +0 -123
  416. package/lib/world/world-rendering.js.map +0 -1
  417. package/lib/world/world.js +0 -147
  418. package/lib/world/world.js.map +0 -1
  419. package/src/game-object/game-object-physics.ts +0 -191
  420. package/src/game-object/game-object-rendering.ts +0 -27
  421. package/src/game-object/game-object.ts +0 -190
  422. package/src/game-object/transform.ts +0 -164
  423. package/src/game-object-ext/animated-sprite.ts +0 -140
  424. package/src/game-object-ext/dom-container.ts +0 -67
  425. package/src/game-object-ext/rect.ts +0 -40
  426. package/src/game-object-ext/spine.ts +0 -235
  427. package/src/game-object-ext/sprite.ts +0 -55
  428. package/src/game-object-ext/text.ts +0 -83
  429. package/src/game-object-ext/tiling-sprite.ts +0 -73
  430. package/src/utils/debug.ts +0 -5
  431. package/src/utils/go.ts +0 -53
  432. package/src/world/world-debug.ts +0 -114
  433. package/src/world/world-physics.ts +0 -52
  434. package/src/world/world-rendering.ts +0 -145
  435. package/src/world/world.ts +0 -171
  436. /package/examples/{test-dom → collision-test}/index.html +0 -0
  437. /package/lib/{utils/debug.js → debug.js} +0 -0
  438. /package/lib/types/{utils/debug.d.ts → debug.d.ts} +0 -0
@@ -0,0 +1,35 @@
1
+ /*!
2
+ * matter-js 0.20.0 by @liabru
3
+ * http://brm.io/matter-js/
4
+ * License MIT
5
+ *
6
+ * The MIT License (MIT)
7
+ *
8
+ * Copyright (c) Liam Brummitt and contributors.
9
+ *
10
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ * of this software and associated documentation files (the "Software"), to deal
12
+ * in the Software without restriction, including without limitation the rights
13
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ * copies of the Software, and to permit persons to whom the Software is
15
+ * furnished to do so, subject to the following conditions:
16
+ *
17
+ * The above copyright notice and this permission notice shall be included in
18
+ * all copies or substantial portions of the Software.
19
+ *
20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26
+ * THE SOFTWARE.
27
+ */
28
+
29
+ /**
30
+ * tiny-lru
31
+ *
32
+ * @copyright 2025 Jason Mulligan <jason.mulligan@avoidwork.com>
33
+ * @license BSD-3-Clause
34
+ * @version 11.4.5
35
+ */
@@ -0,0 +1,24 @@
1
+ <!doctype html>
2
+ <html>
3
+
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <meta name="viewport" content="width=device-width,initial-scale=1">
7
+ <style>
8
+ html,
9
+ body {
10
+ width: 100%;
11
+ height: 100%;
12
+ margin: 0;
13
+ padding: 0;
14
+ overflow: hidden;
15
+ background-color: #000;
16
+ }
17
+ </style>
18
+ </head>
19
+
20
+ <body>
21
+ <script src="dist/game.js"></script>
22
+ </body>
23
+
24
+ </html>
@@ -0,0 +1,41 @@
1
+ import { AnimatedSpriteNode, enableDebug, preload, Renderer, SpriteNode } from '../../src'
2
+
3
+ enableDebug()
4
+
5
+ const renderer = new Renderer(document.body, {
6
+ logicalWidth: 800,
7
+ logicalHeight: 600,
8
+ backgroundColor: '#304C79'
9
+ })
10
+
11
+ await preload(['assets/bird.png'])
12
+
13
+ for (let i = 0; i < 100; i++) {
14
+ const sprite = new SpriteNode({
15
+ src: 'assets/bird.png',
16
+ x: Math.random() * renderer.canvasWidth - renderer.canvasWidth / 2,
17
+ y: Math.random() * renderer.canvasHeight - renderer.canvasHeight / 2
18
+ })
19
+ renderer.add(sprite)
20
+ }
21
+
22
+ const animatedSprite = new AnimatedSpriteNode({
23
+ src: 'assets/fire.png',
24
+ atlas: {
25
+ frames: {
26
+ fire1: { frame: { x: 0, y: 0, w: 64, h: 64 } },
27
+ fire2: { frame: { x: 64, y: 0, w: 64, h: 64 } },
28
+ fire3: { frame: { x: 128, y: 0, w: 64, h: 64 } },
29
+ fire4: { frame: { x: 192, y: 0, w: 64, h: 64 } },
30
+ fire5: { frame: { x: 256, y: 0, w: 64, h: 64 } },
31
+ },
32
+ meta: { scale: 1 },
33
+ animations: {
34
+ fire: ['fire1', 'fire2', 'fire3', 'fire4', 'fire5'],
35
+ },
36
+ },
37
+ animation: 'fire',
38
+ fps: 12,
39
+ loop: true,
40
+ })
41
+ renderer.add(animatedSprite)
@@ -17,6 +17,7 @@
17
17
  "composite": false,
18
18
  "moduleResolution": "node",
19
19
  "skipLibCheck": true,
20
- "strict": true
20
+ "strict": true,
21
+ "resolveJsonModule": true
21
22
  }
22
23
  }
@@ -1,8 +1,19 @@
1
- const path = require('path');
1
+ const path = require('path')
2
2
 
3
3
  module.exports = {
4
4
  entry: {
5
- 'test-dom': './test-dom/index.ts',
5
+
6
+ 'renderer-test': './renderer-test/index.ts',
7
+ 'dom-test': './dom-test/index.ts',
8
+ 'sprite-test': './sprite-test/index.ts',
9
+ 'collision-test': './collision-test/index.ts',
10
+ 'spine-test': './spine-test/index.ts',
11
+ 'particle-test': './particle-test/index.ts',
12
+ 'dom-sprite-test': './dom-sprite-test/index.ts',
13
+ 'dom-particle-test': './dom-particle-test/index.ts',
14
+
15
+ 'flappy-cat': './flappy-cat/index.ts',
16
+ 'simple-battle': './simple-battle/index.ts',
6
17
  },
7
18
  output: {
8
19
  filename: '[name]/dist/game.js',
@@ -28,4 +39,4 @@ module.exports = {
28
39
  },
29
40
  open: true
30
41
  }
31
- };
42
+ }
package/jest.config.ts ADDED
@@ -0,0 +1,10 @@
1
+ /** @type {import('jest').Config} */
2
+ module.exports = {
3
+ testEnvironment: 'jsdom',
4
+ transform: {
5
+ '^.+\\.(ts|tsx)$': 'ts-jest',
6
+ },
7
+ moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
8
+ testPathIgnorePatterns: ['/node_modules/', '/lib/'],
9
+ testMatch: ['**/src/**/*.test.ts', '**/__tests__/**/*.spec.ts'],
10
+ };
@@ -1,5 +1,6 @@
1
+ import { isMobile } from '../utils/device';
1
2
  import { audioLoader } from './loaders/audio';
2
- const audioContext = new (window.AudioContext || window.webkitAudioContext)();
3
+ export const audioContext = new (window.AudioContext || window.webkitAudioContext)();
3
4
  window.addEventListener('mousedown', () => audioContext.resume());
4
5
  window.addEventListener('touchend', () => audioContext.resume());
5
6
  async function getAvailableContext() {
@@ -7,9 +8,39 @@ async function getAvailableContext() {
7
8
  await audioContext.resume();
8
9
  return audioContext;
9
10
  }
10
- const isMobile = /Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
11
11
  let isPageVisible = !document.hidden;
12
12
  window.addEventListener('visibilitychange', () => isPageVisible = !document.hidden);
13
+ function createSafeStorage() {
14
+ const memory = (() => {
15
+ const m = new Map();
16
+ const api = {
17
+ persistent: false,
18
+ getItem: (k) => (m.has(k) ? m.get(k) : null),
19
+ setItem: (k, v) => { m.set(k, String(v)); },
20
+ removeItem: (k) => { m.delete(k); },
21
+ };
22
+ return api;
23
+ })();
24
+ if (typeof window === 'undefined')
25
+ return memory;
26
+ try {
27
+ const ls = window.localStorage;
28
+ const probeKey = '__safe_ls_probe__' + Math.random().toString(36).slice(2);
29
+ ls.setItem(probeKey, '1');
30
+ ls.removeItem(probeKey);
31
+ const safe = {
32
+ persistent: true,
33
+ getItem: (k) => ls.getItem(k),
34
+ setItem: (k, v) => ls.setItem(k, v),
35
+ removeItem: (k) => ls.removeItem(k),
36
+ };
37
+ return safe;
38
+ }
39
+ catch {
40
+ return memory;
41
+ }
42
+ }
43
+ const safeStorage = createSafeStorage();
13
44
  class Audio {
14
45
  src;
15
46
  #volume;
@@ -39,10 +70,13 @@ class Audio {
39
70
  if (isMobile && !isPageVisible)
40
71
  return;
41
72
  if (!this.#audioBuffer) {
42
- if (!audioLoader.checkLoaded(this.src)) {
73
+ if (audioLoader.checkCached(this.src)) {
74
+ this.#audioBuffer = audioLoader.getCached(this.src);
75
+ }
76
+ else {
43
77
  console.info(`Audio not preloaded. Loading now: ${this.src}`);
78
+ this.#audioBuffer = await audioLoader.load(this.src);
44
79
  }
45
- this.#audioBuffer = await audioLoader.load(this.src);
46
80
  }
47
81
  if (!this.#audioBuffer)
48
82
  return;
@@ -99,7 +133,7 @@ class MusicPlayer {
99
133
  #volume = 0.7;
100
134
  #currentAudio;
101
135
  constructor() {
102
- const stored = parseFloat(localStorage.getItem('musicVolume') || '');
136
+ const stored = parseFloat(safeStorage.getItem('musicVolume') || '');
103
137
  this.#volume = Number.isNaN(stored) ? this.#volume : stored;
104
138
  if (isMobile) {
105
139
  document.addEventListener('visibilitychange', () => {
@@ -117,7 +151,7 @@ class MusicPlayer {
117
151
  }
118
152
  set volume(volume) {
119
153
  this.#volume = volume;
120
- localStorage.setItem('musicVolume', volume.toString());
154
+ safeStorage.setItem('musicVolume', volume.toString());
121
155
  if (this.#currentAudio)
122
156
  this.#currentAudio.volume = volume;
123
157
  }
@@ -138,7 +172,7 @@ class MusicPlayer {
138
172
  class SfxPlayer {
139
173
  #volume = 1;
140
174
  constructor() {
141
- const stored = parseFloat(localStorage.getItem('sfxVolume') || '');
175
+ const stored = parseFloat(safeStorage.getItem('sfxVolume') || '');
142
176
  this.#volume = Number.isNaN(stored) ? this.#volume : stored;
143
177
  }
144
178
  get volume() {
@@ -146,13 +180,15 @@ class SfxPlayer {
146
180
  }
147
181
  set volume(volume) {
148
182
  this.#volume = volume;
149
- localStorage.setItem('sfxVolume', volume.toString());
183
+ safeStorage.setItem('sfxVolume', volume.toString());
150
184
  }
151
185
  play(src) {
152
186
  new Audio(src, this.#volume, false);
153
187
  }
188
+ playRandom(...srcs) {
189
+ this.play(srcs[Math.floor(Math.random() * srcs.length)]);
190
+ }
154
191
  }
155
- const musicPlayer = new MusicPlayer();
156
- const sfxPlayer = new SfxPlayer();
157
- export { audioContext, musicPlayer, sfxPlayer };
192
+ export const musicPlayer = new MusicPlayer();
193
+ export const sfxPlayer = new SfxPlayer();
158
194
  //# sourceMappingURL=audio.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"audio.js","sourceRoot":"","sources":["../../src/asset/audio.ts"],"names":[],"mappings":"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","sourcesContent":["import { audioLoader } from './loaders/audio';\n\nconst audioContext = new (window.AudioContext || (window as any).webkitAudioContext)();\nwindow.addEventListener('mousedown', () => audioContext.resume());\nwindow.addEventListener('touchend', () => audioContext.resume());\n\nasync function getAvailableContext(): Promise<AudioContext> {\n if (audioContext.state === 'suspended') await audioContext.resume();\n return audioContext;\n}\n\nconst isMobile = /Android|iPhone|iPad|iPod/i.test(navigator.userAgent);\nlet isPageVisible = !document.hidden;\nwindow.addEventListener('visibilitychange', () => isPageVisible = !document.hidden);\n\nclass Audio {\n src: string;\n #volume: number;\n #loop: boolean;\n\n #audioBuffer?: AudioBuffer;\n #audioContext?: AudioContext;\n #gainNode?: GainNode;\n #source?: AudioBufferSourceNode;\n\n #isPlaying = false;\n #isPaused = false;\n #startTime = 0;\n #pauseTime = 0;\n #offset = 0;\n\n constructor(src: string, volume: number, loop: boolean) {\n this.src = src;\n this.#volume = volume;\n this.#loop = loop;\n this.play();\n }\n\n get volume() { return this.#volume; }\n set volume(volume: number) {\n this.#volume = volume;\n if (this.#gainNode) this.#gainNode.gain.value = Math.max(0, Math.min(1, volume));\n }\n\n async play() {\n if (isMobile && !isPageVisible) return;\n\n if (!this.#audioBuffer) {\n if (!audioLoader.checkLoaded(this.src)) {\n console.info(`Audio not preloaded. Loading now: ${this.src}`);\n }\n this.#audioBuffer = await audioLoader.load(this.src);\n }\n if (!this.#audioBuffer) return;\n\n if (this.#isPlaying) this.stop();\n if (!this.#isPaused) this.#offset = 0;\n this.#isPlaying = true;\n this.#isPaused = false;\n if (!this.#audioContext) this.#audioContext = await getAvailableContext();\n if (!this.#isPlaying) return;\n\n if (!this.#gainNode) {\n this.#gainNode = this.#audioContext.createGain();\n this.#gainNode.gain.value = this.#volume;\n this.#gainNode.connect(this.#audioContext.destination);\n }\n\n this.#source = this.#audioContext.createBufferSource();\n this.#source.buffer = this.#audioBuffer;\n this.#source.loop = this.#loop;\n this.#source.connect(this.#gainNode);\n this.#source.start(0, this.#offset);\n this.#startTime = this.#audioContext.currentTime;\n this.#source.onended = () => { if (!this.#isPaused && !this.#loop) this.stop(); };\n }\n\n #clear(): void {\n if (this.#source) {\n this.#source.stop();\n this.#source.disconnect();\n this.#source = undefined;\n }\n }\n\n pause() {\n if (this.#isPlaying && !this.#isPaused) {\n if (this.#audioContext) {\n this.#pauseTime = this.#audioContext.currentTime;\n this.#offset += this.#pauseTime - this.#startTime;\n }\n this.#isPaused = true;\n this.#isPlaying = false;\n this.#clear();\n }\n }\n\n stop() {\n this.#isPlaying = false;\n this.#isPaused = false;\n this.#offset = 0;\n this.#clear();\n }\n}\n\nclass MusicPlayer {\n #volume = 0.7;\n #currentAudio?: Audio;\n\n constructor() {\n const stored = parseFloat(localStorage.getItem('musicVolume') || '');\n this.#volume = Number.isNaN(stored) ? this.#volume : stored;\n\n if (isMobile) {\n document.addEventListener('visibilitychange', () => {\n if (document.hidden) this.pause();\n else {\n isPageVisible = true;\n this.#currentAudio?.play();\n }\n });\n }\n }\n\n get volume() {\n return this.#volume;\n }\n\n set volume(volume: number) {\n this.#volume = volume;\n localStorage.setItem('musicVolume', volume.toString());\n if (this.#currentAudio) this.#currentAudio.volume = volume;\n }\n\n play(src: string) {\n if (this.#currentAudio?.src === src) return;\n this.#currentAudio?.stop();\n this.#currentAudio = new Audio(src, this.#volume, true);\n }\n\n pause() {\n this.#currentAudio?.pause();\n }\n\n stop() {\n this.#currentAudio?.stop();\n this.#currentAudio = undefined;\n }\n}\n\nclass SfxPlayer {\n #volume = 1;\n\n constructor() {\n const stored = parseFloat(localStorage.getItem('sfxVolume') || '');\n this.#volume = Number.isNaN(stored) ? this.#volume : stored;\n }\n\n get volume() {\n return this.#volume;\n }\n\n set volume(volume: number) {\n this.#volume = volume;\n localStorage.setItem('sfxVolume', volume.toString());\n }\n\n play(src: string) {\n new Audio(src, this.#volume, false);\n }\n}\n\nconst musicPlayer = new MusicPlayer();\nconst sfxPlayer = new SfxPlayer();\n\nexport { audioContext, musicPlayer, sfxPlayer };\n"]}
1
+ {"version":3,"file":"audio.js","sourceRoot":"","sources":["../../src/asset/audio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAE7C,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,IAAK,MAAc,CAAC,kBAAkB,CAAC,EAAE,CAAA;AAC7F,MAAM,CAAC,gBAAgB,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAA;AACjE,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAA;AAEhE,KAAK,UAAU,mBAAmB;IAChC,IAAI,YAAY,CAAC,KAAK,KAAK,WAAW;QAAE,MAAM,YAAY,CAAC,MAAM,EAAE,CAAA;IACnE,OAAO,YAAY,CAAA;AACrB,CAAC;AAED,IAAI,aAAa,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAA;AACpC,MAAM,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,aAAa,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;AAQnF,SAAS,iBAAiB;IACxB,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE;QACnB,MAAM,CAAC,GAAG,IAAI,GAAG,EAAkB,CAAA;QACnC,MAAM,GAAG,GAAgB;YACvB,UAAU,EAAE,KAAK;YACjB,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YAC7C,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA,CAAC,CAAC;YAC1C,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA,CAAC,CAAC;SACnC,CAAA;QACD,OAAO,GAAG,CAAA;IACZ,CAAC,CAAC,EAAE,CAAA;IAEJ,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,MAAM,CAAA;IAEhD,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,MAAM,CAAC,YAAY,CAAA;QAC9B,MAAM,QAAQ,GAAG,mBAAmB,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAC1E,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAA;QACzB,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAA;QAEvB,MAAM,IAAI,GAAgB;YACxB,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;YAC7B,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;YACnC,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;SACpC,CAAA;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAA;IACf,CAAC;AACH,CAAC;AAED,MAAM,WAAW,GAAG,iBAAiB,EAAE,CAAA;AAEvC,MAAM,KAAK;IACT,GAAG,CAAQ;IACX,OAAO,CAAQ;IACf,KAAK,CAAS;IAEd,YAAY,CAAc;IAC1B,aAAa,CAAe;IAC5B,SAAS,CAAW;IACpB,OAAO,CAAwB;IAE/B,UAAU,GAAG,KAAK,CAAA;IAClB,SAAS,GAAG,KAAK,CAAA;IACjB,UAAU,GAAG,CAAC,CAAA;IACd,UAAU,GAAG,CAAC,CAAA;IACd,OAAO,GAAG,CAAC,CAAA;IAEX,YAAY,GAAW,EAAE,MAAc,EAAE,IAAa;QACpD,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QACd,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;QACrB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;QACjB,IAAI,CAAC,IAAI,EAAE,CAAA;IACb,CAAC;IAED,IAAI,MAAM,KAAK,OAAO,IAAI,CAAC,OAAO,CAAA,CAAC,CAAC;IACpC,IAAI,MAAM,CAAC,MAAc;QACvB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;QACrB,IAAI,IAAI,CAAC,SAAS;YAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAA;IAClF,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,QAAQ,IAAI,CAAC,aAAa;YAAE,OAAM;QAEtC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,IAAI,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBACtC,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACrD,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,IAAI,CAAC,qCAAqC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;gBAC7D,IAAI,CAAC,YAAY,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACtD,CAAC;QACH,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE,OAAM;QAE9B,IAAI,IAAI,CAAC,UAAU;YAAE,IAAI,CAAC,IAAI,EAAE,CAAA;QAChC,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,IAAI,CAAC,OAAO,GAAG,CAAC,CAAA;QACrC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAA;QACtB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAA;QACtB,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE,IAAI,CAAC,aAAa,GAAG,MAAM,mBAAmB,EAAE,CAAA;QACzE,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAM;QAE5B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,CAAA;YAChD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,OAAO,CAAA;YACxC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,CAAA;QACxD,CAAC;QAED,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,kBAAkB,EAAE,CAAA;QACtD,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,YAAY,CAAA;QACvC,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAA;QAC9B,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QACpC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;QACnC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,WAAW,CAAA;QAChD,IAAI,CAAC,OAAO,CAAC,OAAO,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,IAAI,EAAE,CAAA,CAAC,CAAC,CAAA;IAClF,CAAC;IAED,MAAM;QACJ,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;YACnB,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAA;YACzB,IAAI,CAAC,OAAO,GAAG,SAAS,CAAA;QAC1B,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACvC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;gBACvB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,WAAW,CAAA;gBAChD,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAA;YACnD,CAAC;YACD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;YACrB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAA;YACvB,IAAI,CAAC,MAAM,EAAE,CAAA;QACf,CAAC;IACH,CAAC;IAED,IAAI;QACF,IAAI,CAAC,UAAU,GAAG,KAAK,CAAA;QACvB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAA;QACtB,IAAI,CAAC,OAAO,GAAG,CAAC,CAAA;QAChB,IAAI,CAAC,MAAM,EAAE,CAAA;IACf,CAAC;CACF;AAED,MAAM,WAAW;IACf,OAAO,GAAG,GAAG,CAAA;IACb,aAAa,CAAQ;IAErB;QACE,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAA;QACnE,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAA;QAE3D,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,GAAG,EAAE;gBACjD,IAAI,QAAQ,CAAC,MAAM;oBAAE,IAAI,CAAC,KAAK,EAAE,CAAA;qBAC5B,CAAC;oBACJ,aAAa,GAAG,IAAI,CAAA;oBACpB,IAAI,CAAC,aAAa,EAAE,IAAI,EAAE,CAAA;gBAC5B,CAAC;YACH,CAAC,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED,IAAI,MAAM,CAAC,MAAc;QACvB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;QACrB,WAAW,CAAC,OAAO,CAAC,aAAa,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAA;QACrD,IAAI,IAAI,CAAC,aAAa;YAAE,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,MAAM,CAAA;IAC5D,CAAC;IAED,IAAI,CAAC,GAAW;QACd,IAAI,IAAI,CAAC,aAAa,EAAE,GAAG,KAAK,GAAG;YAAE,OAAM;QAC3C,IAAI,CAAC,aAAa,EAAE,IAAI,EAAE,CAAA;QAC1B,IAAI,CAAC,aAAa,GAAG,IAAI,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IACzD,CAAC;IAED,KAAK;QACH,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE,CAAA;IAC7B,CAAC;IAED,IAAI;QACF,IAAI,CAAC,aAAa,EAAE,IAAI,EAAE,CAAA;QAC1B,IAAI,CAAC,aAAa,GAAG,SAAS,CAAA;IAChC,CAAC;CACF;AAED,MAAM,SAAS;IACb,OAAO,GAAG,CAAC,CAAA;IAEX;QACE,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAA;QACjE,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAA;IAC7D,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED,IAAI,MAAM,CAAC,MAAc;QACvB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;QACrB,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAA;IACrD,CAAC;IAED,IAAI,CAAC,GAAW;QACd,IAAI,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;IACrC,CAAC;IAED,UAAU,CAAC,GAAG,IAAc;QAC1B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IAC1D,CAAC;CACF;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAA;AAC5C,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,SAAS,EAAE,CAAA","sourcesContent":["import { isMobile } from '../utils/device'\nimport { audioLoader } from './loaders/audio'\n\nexport const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)()\nwindow.addEventListener('mousedown', () => audioContext.resume())\nwindow.addEventListener('touchend', () => audioContext.resume())\n\nasync function getAvailableContext(): Promise<AudioContext> {\n if (audioContext.state === 'suspended') await audioContext.resume()\n return audioContext\n}\n\nlet isPageVisible = !document.hidden\nwindow.addEventListener('visibilitychange', () => isPageVisible = !document.hidden)\n\ntype BasicStorage = Pick<Storage, 'getItem' | 'setItem' | 'removeItem'>\n\ntype SafeStorage = BasicStorage & {\n persistent: boolean\n}\n\nfunction createSafeStorage(): SafeStorage {\n const memory = (() => {\n const m = new Map<string, string>()\n const api: SafeStorage = {\n persistent: false,\n getItem: (k) => (m.has(k) ? m.get(k)! : null),\n setItem: (k, v) => { m.set(k, String(v)) },\n removeItem: (k) => { m.delete(k) },\n }\n return api\n })()\n\n if (typeof window === 'undefined') return memory\n\n try {\n const ls = window.localStorage\n const probeKey = '__safe_ls_probe__' + Math.random().toString(36).slice(2)\n ls.setItem(probeKey, '1')\n ls.removeItem(probeKey)\n\n const safe: SafeStorage = {\n persistent: true,\n getItem: (k) => ls.getItem(k),\n setItem: (k, v) => ls.setItem(k, v),\n removeItem: (k) => ls.removeItem(k),\n }\n return safe\n } catch {\n return memory\n }\n}\n\nconst safeStorage = createSafeStorage()\n\nclass Audio {\n src: string\n #volume: number\n #loop: boolean\n\n #audioBuffer?: AudioBuffer\n #audioContext?: AudioContext\n #gainNode?: GainNode\n #source?: AudioBufferSourceNode\n\n #isPlaying = false\n #isPaused = false\n #startTime = 0\n #pauseTime = 0\n #offset = 0\n\n constructor(src: string, volume: number, loop: boolean) {\n this.src = src\n this.#volume = volume\n this.#loop = loop\n this.play()\n }\n\n get volume() { return this.#volume }\n set volume(volume: number) {\n this.#volume = volume\n if (this.#gainNode) this.#gainNode.gain.value = Math.max(0, Math.min(1, volume))\n }\n\n async play() {\n if (isMobile && !isPageVisible) return\n\n if (!this.#audioBuffer) {\n if (audioLoader.checkCached(this.src)) {\n this.#audioBuffer = audioLoader.getCached(this.src)\n } else {\n console.info(`Audio not preloaded. Loading now: ${this.src}`)\n this.#audioBuffer = await audioLoader.load(this.src)\n }\n }\n if (!this.#audioBuffer) return\n\n if (this.#isPlaying) this.stop()\n if (!this.#isPaused) this.#offset = 0\n this.#isPlaying = true\n this.#isPaused = false\n if (!this.#audioContext) this.#audioContext = await getAvailableContext()\n if (!this.#isPlaying) return\n\n if (!this.#gainNode) {\n this.#gainNode = this.#audioContext.createGain()\n this.#gainNode.gain.value = this.#volume\n this.#gainNode.connect(this.#audioContext.destination)\n }\n\n this.#source = this.#audioContext.createBufferSource()\n this.#source.buffer = this.#audioBuffer\n this.#source.loop = this.#loop\n this.#source.connect(this.#gainNode)\n this.#source.start(0, this.#offset)\n this.#startTime = this.#audioContext.currentTime\n this.#source.onended = () => { if (!this.#isPaused && !this.#loop) this.stop() }\n }\n\n #clear(): void {\n if (this.#source) {\n this.#source.stop()\n this.#source.disconnect()\n this.#source = undefined\n }\n }\n\n pause() {\n if (this.#isPlaying && !this.#isPaused) {\n if (this.#audioContext) {\n this.#pauseTime = this.#audioContext.currentTime\n this.#offset += this.#pauseTime - this.#startTime\n }\n this.#isPaused = true\n this.#isPlaying = false\n this.#clear()\n }\n }\n\n stop() {\n this.#isPlaying = false\n this.#isPaused = false\n this.#offset = 0\n this.#clear()\n }\n}\n\nclass MusicPlayer {\n #volume = 0.7\n #currentAudio?: Audio\n\n constructor() {\n const stored = parseFloat(safeStorage.getItem('musicVolume') || '')\n this.#volume = Number.isNaN(stored) ? this.#volume : stored\n\n if (isMobile) {\n document.addEventListener('visibilitychange', () => {\n if (document.hidden) this.pause()\n else {\n isPageVisible = true\n this.#currentAudio?.play()\n }\n })\n }\n }\n\n get volume() {\n return this.#volume\n }\n\n set volume(volume: number) {\n this.#volume = volume\n safeStorage.setItem('musicVolume', volume.toString())\n if (this.#currentAudio) this.#currentAudio.volume = volume\n }\n\n play(src: string) {\n if (this.#currentAudio?.src === src) return\n this.#currentAudio?.stop()\n this.#currentAudio = new Audio(src, this.#volume, true)\n }\n\n pause() {\n this.#currentAudio?.pause()\n }\n\n stop() {\n this.#currentAudio?.stop()\n this.#currentAudio = undefined\n }\n}\n\nclass SfxPlayer {\n #volume = 1\n\n constructor() {\n const stored = parseFloat(safeStorage.getItem('sfxVolume') || '')\n this.#volume = Number.isNaN(stored) ? this.#volume : stored\n }\n\n get volume() {\n return this.#volume\n }\n\n set volume(volume: number) {\n this.#volume = volume\n safeStorage.setItem('sfxVolume', volume.toString())\n }\n\n play(src: string) {\n new Audio(src, this.#volume, false)\n }\n\n playRandom(...srcs: string[]) {\n this.play(srcs[Math.floor(Math.random() * srcs.length)])\n }\n}\n\nexport const musicPlayer = new MusicPlayer()\nexport const sfxPlayer = new SfxPlayer()\n"]}
@@ -1,7 +1,7 @@
1
1
  import { audioContext } from '../audio';
2
2
  import { Loader } from './loader';
3
3
  class AudioLoader extends Loader {
4
- async _load(src) {
4
+ async doLoad(src) {
5
5
  const loadingPromise = (async () => {
6
6
  const response = await fetch(src);
7
7
  if (!response.ok) {
@@ -13,11 +13,11 @@ class AudioLoader extends Loader {
13
13
  const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
14
14
  this.loadingPromises.delete(src);
15
15
  if (this.hasActiveRef(src)) {
16
- if (this.loadedAssets.has(src)) {
16
+ if (this.cachedAssets.has(src)) {
17
17
  console.error(`Audio buffer already exists: ${src}`);
18
18
  }
19
19
  else {
20
- this.loadedAssets.set(src, audioBuffer);
20
+ this.cachedAssets.set(src, audioBuffer);
21
21
  return audioBuffer;
22
22
  }
23
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"audio.js","sourceRoot":"","sources":["../../../src/asset/loaders/audio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,MAAM,WAAY,SAAQ,MAAmB;IACxB,KAAK,CAAC,KAAK,CAAC,GAAW;QACxC,MAAM,cAAc,GAAG,CAAC,KAAK,IAAI,EAAE;YACjC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,OAAO,CAAC,KAAK,CAAC,8BAA8B,GAAG,EAAE,CAAC,CAAC;gBACnD,OAAO;YACT,CAAC;YAED,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;YAEjD,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,MAAM,YAAY,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;gBAEpE,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAEjC,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC3B,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;wBAC/B,OAAO,CAAC,KAAK,CAAC,gCAAgC,GAAG,EAAE,CAAC,CAAC;oBACvD,CAAC;yBAAM,CAAC;wBACN,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;wBACxC,OAAO,WAAW,CAAC;oBACrB,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,gCAAgC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;gBAC5D,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACnC,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;QAEL,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAC9C,OAAO,MAAM,cAAc,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC","sourcesContent":["import { audioContext } from '../audio';\nimport { Loader } from './loader';\n\nclass AudioLoader extends Loader<AudioBuffer> {\n protected override async _load(src: string) {\n const loadingPromise = (async () => {\n const response = await fetch(src);\n if (!response.ok) {\n console.error(`Failed to load audio data: ${src}`);\n return;\n }\n\n const arrayBuffer = await response.arrayBuffer();\n\n try {\n const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);\n\n this.loadingPromises.delete(src);\n\n if (this.hasActiveRef(src)) {\n if (this.loadedAssets.has(src)) {\n console.error(`Audio buffer already exists: ${src}`);\n } else {\n this.loadedAssets.set(src, audioBuffer);\n return audioBuffer;\n }\n }\n } catch (error) {\n console.error(`Failed to decode audio data: ${src}`, error);\n this.loadingPromises.delete(src);\n }\n })();\n\n this.loadingPromises.set(src, loadingPromise);\n return await loadingPromise;\n }\n}\n\nexport const audioLoader = new AudioLoader();\n"]}
1
+ {"version":3,"file":"audio.js","sourceRoot":"","sources":["../../../src/asset/loaders/audio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjC,MAAM,WAAY,SAAQ,MAAmB;IACxB,KAAK,CAAC,MAAM,CAAC,GAAW;QACzC,MAAM,cAAc,GAAG,CAAC,KAAK,IAAI,EAAE;YACjC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA;YACjC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,OAAO,CAAC,KAAK,CAAC,8BAA8B,GAAG,EAAE,CAAC,CAAA;gBAClD,OAAM;YACR,CAAC;YAED,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAA;YAEhD,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,MAAM,YAAY,CAAC,eAAe,CAAC,WAAW,CAAC,CAAA;gBAEnE,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;gBAEhC,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC3B,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;wBAC/B,OAAO,CAAC,KAAK,CAAC,gCAAgC,GAAG,EAAE,CAAC,CAAA;oBACtD,CAAC;yBAAM,CAAC;wBACN,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,WAAW,CAAC,CAAA;wBACvC,OAAO,WAAW,CAAA;oBACpB,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,gCAAgC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAA;gBAC3D,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAClC,CAAC;QACH,CAAC,CAAC,EAAE,CAAA;QAEJ,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,cAAc,CAAC,CAAA;QAC7C,OAAO,MAAM,cAAc,CAAA;IAC7B,CAAC;CACF;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAA","sourcesContent":["import { audioContext } from '../audio'\nimport { Loader } from './loader'\n\nclass AudioLoader extends Loader<AudioBuffer> {\n protected override async doLoad(src: string) {\n const loadingPromise = (async () => {\n const response = await fetch(src)\n if (!response.ok) {\n console.error(`Failed to load audio data: ${src}`)\n return\n }\n\n const arrayBuffer = await response.arrayBuffer()\n\n try {\n const audioBuffer = await audioContext.decodeAudioData(arrayBuffer)\n\n this.loadingPromises.delete(src)\n\n if (this.hasActiveRef(src)) {\n if (this.cachedAssets.has(src)) {\n console.error(`Audio buffer already exists: ${src}`)\n } else {\n this.cachedAssets.set(src, audioBuffer)\n return audioBuffer\n }\n }\n } catch (error) {\n console.error(`Failed to decode audio data: ${src}`, error)\n this.loadingPromises.delete(src)\n }\n })()\n\n this.loadingPromises.set(src, loadingPromise)\n return await loadingPromise\n }\n}\n\nexport const audioLoader = new AudioLoader()\n"]}
@@ -1,6 +1,6 @@
1
1
  import { Loader } from './loader';
2
2
  class BinaryLoader extends Loader {
3
- async _load(src) {
3
+ async doLoad(src) {
4
4
  const loadingPromise = (async () => {
5
5
  const response = await fetch(src);
6
6
  if (!response.ok) {
@@ -11,11 +11,11 @@ class BinaryLoader extends Loader {
11
11
  const data = new Uint8Array(arrayBuffer);
12
12
  this.loadingPromises.delete(src);
13
13
  if (this.hasActiveRef(src)) {
14
- if (this.loadedAssets.has(src)) {
14
+ if (this.cachedAssets.has(src)) {
15
15
  console.error(`Binary data already exists: ${src}`);
16
16
  }
17
17
  else {
18
- this.loadedAssets.set(src, data);
18
+ this.cachedAssets.set(src, data);
19
19
  return data;
20
20
  }
21
21
  }
@@ -1 +1 @@
1
- {"version":3,"file":"binary.js","sourceRoot":"","sources":["../../../src/asset/loaders/binary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,MAAM,YAAa,SAAQ,MAAkB;IACxB,KAAK,CAAC,KAAK,CAAC,GAAW;QACxC,MAAM,cAAc,GAAG,CAAC,KAAK,IAAI,EAAE;YACjC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,OAAO,CAAC,KAAK,CAAC,+BAA+B,GAAG,EAAE,CAAC,CAAC;gBACpD,OAAO;YACT,CAAC;YAED,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;YACjD,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;YAEzC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAEjC,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC3B,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC/B,OAAO,CAAC,KAAK,CAAC,+BAA+B,GAAG,EAAE,CAAC,CAAC;gBACtD,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;oBACjC,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;QAEL,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAC9C,OAAO,MAAM,cAAc,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAC","sourcesContent":["import { Loader } from './loader';\n\nclass BinaryLoader extends Loader<Uint8Array> {\n protected override async _load(src: string) {\n const loadingPromise = (async () => {\n const response = await fetch(src);\n if (!response.ok) {\n console.error(`Failed to load binary data: ${src}`);\n return;\n }\n\n const arrayBuffer = await response.arrayBuffer();\n const data = new Uint8Array(arrayBuffer);\n\n this.loadingPromises.delete(src);\n\n if (this.hasActiveRef(src)) {\n if (this.loadedAssets.has(src)) {\n console.error(`Binary data already exists: ${src}`);\n } else {\n this.loadedAssets.set(src, data);\n return data;\n }\n }\n })();\n\n this.loadingPromises.set(src, loadingPromise);\n return await loadingPromise;\n }\n}\n\nexport const binaryLoader = new BinaryLoader();\n"]}
1
+ {"version":3,"file":"binary.js","sourceRoot":"","sources":["../../../src/asset/loaders/binary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjC,MAAM,YAAa,SAAQ,MAAkB;IACxB,KAAK,CAAC,MAAM,CAAC,GAAW;QACzC,MAAM,cAAc,GAAG,CAAC,KAAK,IAAI,EAAE;YACjC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA;YACjC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,OAAO,CAAC,KAAK,CAAC,+BAA+B,GAAG,EAAE,CAAC,CAAA;gBACnD,OAAM;YACR,CAAC;YAED,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAA;YAChD,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAA;YAExC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAEhC,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC3B,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC/B,OAAO,CAAC,KAAK,CAAC,+BAA+B,GAAG,EAAE,CAAC,CAAA;gBACrD,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;oBAChC,OAAO,IAAI,CAAA;gBACb,CAAC;YACH,CAAC;QACH,CAAC,CAAC,EAAE,CAAA;QAEJ,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,cAAc,CAAC,CAAA;QAC7C,OAAO,MAAM,cAAc,CAAA;IAC7B,CAAC;CACF;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAA","sourcesContent":["import { Loader } from './loader'\n\nclass BinaryLoader extends Loader<Uint8Array> {\n protected override async doLoad(src: string) {\n const loadingPromise = (async () => {\n const response = await fetch(src)\n if (!response.ok) {\n console.error(`Failed to load binary data: ${src}`)\n return\n }\n\n const arrayBuffer = await response.arrayBuffer()\n const data = new Uint8Array(arrayBuffer)\n\n this.loadingPromises.delete(src)\n\n if (this.hasActiveRef(src)) {\n if (this.cachedAssets.has(src)) {\n console.error(`Binary data already exists: ${src}`)\n } else {\n this.cachedAssets.set(src, data)\n return data\n }\n }\n })()\n\n this.loadingPromises.set(src, loadingPromise)\n return await loadingPromise\n }\n}\n\nexport const binaryLoader = new BinaryLoader()\n"]}
@@ -0,0 +1,71 @@
1
+ import { Loader } from './loader';
2
+ import { textureLoader } from './texture';
3
+ class BitmapFontLoader extends Loader {
4
+ #fntToSrc = new Map();
5
+ async doLoad(fnt, src) {
6
+ this.#fntToSrc.set(fnt, src);
7
+ const loadingPromise = (async () => {
8
+ const texture = await textureLoader.load(src);
9
+ if (!texture) {
10
+ console.error(`Failed to load texture: ${src}`);
11
+ return;
12
+ }
13
+ const response = await fetch(fnt);
14
+ if (!response.ok) {
15
+ console.error(`Failed to load font xml: ${fnt}`);
16
+ return;
17
+ }
18
+ try {
19
+ const text = await response.text();
20
+ const parser = new DOMParser();
21
+ const xmlDoc = parser.parseFromString(text, 'application/xml');
22
+ const infoEl = xmlDoc.getElementsByTagName('info')[0];
23
+ const commonEl = xmlDoc.getElementsByTagName('common')[0];
24
+ const charEls = xmlDoc.getElementsByTagName('char');
25
+ const size = parseInt(infoEl.getAttribute('size') || '16', 10);
26
+ const lineHeight = parseInt(commonEl.getAttribute('lineHeight') || '32', 10);
27
+ const chars = {};
28
+ for (let i = 0; i < charEls.length; i++) {
29
+ const charEl = charEls[i];
30
+ const id = parseInt(charEl.getAttribute('id'), 10);
31
+ const x = parseInt(charEl.getAttribute('x'), 10);
32
+ const y = parseInt(charEl.getAttribute('y'), 10);
33
+ const width = parseInt(charEl.getAttribute('width'), 10);
34
+ const height = parseInt(charEl.getAttribute('height'), 10);
35
+ const xoffset = parseInt(charEl.getAttribute('xoffset'), 10);
36
+ const yoffset = parseInt(charEl.getAttribute('yoffset'), 10);
37
+ const xadvance = parseInt(charEl.getAttribute('xadvance'), 10);
38
+ chars[id] = { x, y, width, height, xoffset, yoffset, xadvance };
39
+ }
40
+ this.loadingPromises.delete(fnt);
41
+ const bitmapFont = { src, chars, texture, size, lineHeight };
42
+ if (this.hasActiveRef(fnt)) {
43
+ if (this.cachedAssets.has(fnt)) {
44
+ textureLoader.release(src);
45
+ console.error(`Bitmap font already exists: ${fnt}`);
46
+ }
47
+ else {
48
+ this.cachedAssets.set(fnt, bitmapFont);
49
+ return bitmapFont;
50
+ }
51
+ }
52
+ else {
53
+ textureLoader.release(src);
54
+ }
55
+ }
56
+ catch (error) {
57
+ console.error(`Failed to decode font xml: ${fnt}`, error);
58
+ this.loadingPromises.delete(fnt);
59
+ }
60
+ })();
61
+ this.loadingPromises.set(fnt, loadingPromise);
62
+ return await loadingPromise;
63
+ }
64
+ cleanup(fnt) {
65
+ const src = this.#fntToSrc.get(fnt);
66
+ if (src)
67
+ textureLoader.release(src);
68
+ }
69
+ }
70
+ export const bitmapFontLoader = new BitmapFontLoader();
71
+ //# sourceMappingURL=bitmap-font.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bitmap-font.js","sourceRoot":"","sources":["../../../src/asset/loaders/bitmap-font.ts"],"names":[],"mappings":"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","sourcesContent":["import { BitmapFont, Char } from '../../types/bitmap-font'\nimport { Loader } from './loader'\nimport { textureLoader } from './texture'\n\nclass BitmapFontLoader extends Loader<BitmapFont> {\n #fntToSrc = new Map<string, string>()\n\n protected override async doLoad(fnt: string, src: string) {\n this.#fntToSrc.set(fnt, src)\n\n const loadingPromise = (async () => {\n const texture = await textureLoader.load(src)\n if (!texture) {\n console.error(`Failed to load texture: ${src}`)\n return\n }\n\n const response = await fetch(fnt)\n if (!response.ok) {\n console.error(`Failed to load font xml: ${fnt}`)\n return\n }\n\n try {\n const text = await response.text()\n\n const parser = new DOMParser()\n const xmlDoc = parser.parseFromString(text, 'application/xml')\n\n const infoEl = xmlDoc.getElementsByTagName('info')[0]\n const commonEl = xmlDoc.getElementsByTagName('common')[0]\n const charEls = xmlDoc.getElementsByTagName('char')\n\n const size = parseInt(infoEl.getAttribute('size') || '16', 10)\n const lineHeight = parseInt(commonEl.getAttribute('lineHeight') || '32', 10)\n\n const chars: Record<number, Char> = {}\n\n for (let i = 0; i < charEls.length; i++) {\n const charEl = charEls[i]\n\n const id = parseInt(charEl.getAttribute('id')!, 10)\n const x = parseInt(charEl.getAttribute('x')!, 10)\n const y = parseInt(charEl.getAttribute('y')!, 10)\n const width = parseInt(charEl.getAttribute('width')!, 10)\n const height = parseInt(charEl.getAttribute('height')!, 10)\n const xoffset = parseInt(charEl.getAttribute('xoffset')!, 10)\n const yoffset = parseInt(charEl.getAttribute('yoffset')!, 10)\n const xadvance = parseInt(charEl.getAttribute('xadvance')!, 10)\n\n chars[id] = { x, y, width, height, xoffset, yoffset, xadvance }\n }\n\n this.loadingPromises.delete(fnt)\n\n const bitmapFont = { src, chars, texture, size, lineHeight }\n if (this.hasActiveRef(fnt)) {\n if (this.cachedAssets.has(fnt)) {\n textureLoader.release(src)\n console.error(`Bitmap font already exists: ${fnt}`)\n } else {\n this.cachedAssets.set(fnt, bitmapFont)\n return bitmapFont\n }\n } else {\n textureLoader.release(src)\n }\n\n } catch (error) {\n console.error(`Failed to decode font xml: ${fnt}`, error)\n this.loadingPromises.delete(fnt)\n }\n })()\n\n this.loadingPromises.set(fnt, loadingPromise)\n return await loadingPromise\n }\n\n protected override cleanup(fnt: string) {\n const src = this.#fntToSrc.get(fnt)\n if (src) textureLoader.release(src)\n }\n}\n\nexport const bitmapFontLoader = new BitmapFontLoader()\n"]}
@@ -1,6 +1,6 @@
1
1
  import { Loader } from './loader';
2
2
  class FontFamilyLoader extends Loader {
3
- async _load(fontName) {
3
+ async doLoad(fontName) {
4
4
  const loadingPromise = (async () => {
5
5
  if ('fonts' in document) {
6
6
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"font.js","sourceRoot":"","sources":["../../../src/asset/loaders/font.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,MAAM,gBAAiB,SAAQ,MAAe;IACzB,KAAK,CAAC,KAAK,CAAC,QAAgB;QAC7C,MAAM,cAAc,GAAG,CAAC,KAAK,IAAI,EAAE;YACjC,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAC;gBACxB,IAAI,CAAC;oBACH,MAAM,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,QAAQ,EAAE,CAAC,CAAC;oBAC7C,MAAM,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC;oBAC3B,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;oBACtC,OAAO,IAAI,CAAC;gBACd,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,OAAO,CAAC,KAAK,CAAC,wBAAwB,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAC;oBACzD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACxC,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;gBACnE,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACxC,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;QAEL,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QACnD,OAAO,MAAM,cAAc,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,gBAAgB,EAAE,CAAC","sourcesContent":["import { Loader } from './loader';\n\nclass FontFamilyLoader extends Loader<boolean> {\n protected override async _load(fontName: string) {\n const loadingPromise = (async () => {\n if ('fonts' in document) {\n try {\n await document.fonts.load(`1em ${fontName}`);\n await document.fonts.ready;\n this.loadingPromises.delete(fontName);\n return true;\n } catch (error) {\n console.error(`Failed to load font: ${fontName}`, error);\n this.loadingPromises.delete(fontName);\n }\n } else {\n console.warn(`This browser does not support the Font Loading API`);\n this.loadingPromises.delete(fontName);\n }\n })();\n\n this.loadingPromises.set(fontName, loadingPromise);\n return await loadingPromise;\n }\n}\n\nexport const fontFamilyLoader = new FontFamilyLoader();\n"]}
1
+ {"version":3,"file":"font.js","sourceRoot":"","sources":["../../../src/asset/loaders/font.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjC,MAAM,gBAAiB,SAAQ,MAAe;IACzB,KAAK,CAAC,MAAM,CAAC,QAAgB;QAC9C,MAAM,cAAc,GAAG,CAAC,KAAK,IAAI,EAAE;YACjC,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAC;gBACxB,IAAI,CAAC;oBACH,MAAM,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,QAAQ,EAAE,CAAC,CAAA;oBAC5C,MAAM,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAA;oBAC1B,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;oBACrC,OAAO,IAAI,CAAA;gBACb,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,OAAO,CAAC,KAAK,CAAC,wBAAwB,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAA;oBACxD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;gBACvC,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAA;gBAClE,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;YACvC,CAAC;QACH,CAAC,CAAC,EAAE,CAAA;QAEJ,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;QAClD,OAAO,MAAM,cAAc,CAAA;IAC7B,CAAC;CACF;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,gBAAgB,EAAE,CAAA","sourcesContent":["import { Loader } from './loader'\n\nclass FontFamilyLoader extends Loader<boolean> {\n protected override async doLoad(fontName: string) {\n const loadingPromise = (async () => {\n if ('fonts' in document) {\n try {\n await document.fonts.load(`1em ${fontName}`)\n await document.fonts.ready\n this.loadingPromises.delete(fontName)\n return true\n } catch (error) {\n console.error(`Failed to load font: ${fontName}`, error)\n this.loadingPromises.delete(fontName)\n }\n } else {\n console.warn(`This browser does not support the Font Loading API`)\n this.loadingPromises.delete(fontName)\n }\n })()\n\n this.loadingPromises.set(fontName, loadingPromise)\n return await loadingPromise\n }\n}\n\nexport const fontFamilyLoader = new FontFamilyLoader()\n"]}
@@ -1,20 +1,26 @@
1
- class Loader {
2
- loadedAssets = new Map();
1
+ export class Loader {
2
+ cachedAssets = new Map();
3
3
  loadingPromises = new Map();
4
4
  #refCount = new Map();
5
5
  #incRefCount(id) { this.#refCount.set(id, (this.#refCount.get(id) || 0) + 1); }
6
6
  hasActiveRef(id) { return this.#refCount.get(id) > 0; }
7
- _dispose(id, asset) { }
8
- checkLoaded(id) {
9
- return this.loadedAssets.has(id);
7
+ cleanup(id, asset) { }
8
+ checkCached(id) {
9
+ return this.cachedAssets.has(id);
10
+ }
11
+ getCached(id) {
12
+ if (!this.checkCached(id))
13
+ throw new Error(`Asset not found: ${id}`);
14
+ this.#incRefCount(id);
15
+ return this.cachedAssets.get(id);
10
16
  }
11
17
  async load(id, ...args) {
12
18
  this.#incRefCount(id);
13
- if (this.checkLoaded(id))
14
- return this.loadedAssets.get(id);
19
+ if (this.checkCached(id))
20
+ return this.cachedAssets.get(id);
15
21
  if (this.loadingPromises.has(id))
16
22
  return await this.loadingPromises.get(id);
17
- return await this._load(id, ...args);
23
+ return await this.doLoad(id, ...args);
18
24
  }
19
25
  release(id) {
20
26
  const refCount = this.#refCount.get(id);
@@ -22,10 +28,10 @@ class Loader {
22
28
  throw new Error(`Asset not found: ${id}`);
23
29
  if (refCount === 1) {
24
30
  this.#refCount.delete(id);
25
- const asset = this.loadedAssets.get(id);
31
+ const asset = this.cachedAssets.get(id);
26
32
  if (asset) {
27
- this._dispose(id, asset);
28
- this.loadedAssets.delete(id);
33
+ this.cleanup(id, asset);
34
+ this.cachedAssets.delete(id);
29
35
  }
30
36
  }
31
37
  else {
@@ -33,5 +39,4 @@ class Loader {
33
39
  }
34
40
  }
35
41
  }
36
- export { Loader };
37
42
  //# sourceMappingURL=loader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/asset/loaders/loader.ts"],"names":[],"mappings":"AAAA,MAAe,MAAM;IACT,YAAY,GAAmB,IAAI,GAAG,EAAE,CAAC;IACzC,eAAe,GAAwC,IAAI,GAAG,EAAE,CAAC;IAE3E,SAAS,GAAwB,IAAI,GAAG,EAAE,CAAC;IAC3C,YAAY,CAAC,EAAU,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAE7E,YAAY,CAAC,EAAU,IAAI,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IAEhE,QAAQ,CAAC,EAAU,EAAE,KAAQ,IAAqC,CAAC;IAE7E,WAAW,CAAC,EAAU;QACpB,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAU,EAAE,GAAG,IAAW;QACnC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACtB,IAAI,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YAAE,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3D,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,OAAO,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC5E,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,CAAC,EAAU;QAChB,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACxC,IAAI,QAAQ,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC;QACtE,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;YACnB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACxC,IAAI,KAAK,EAAE,CAAC;gBACV,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;gBACzB,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;CACF;AAED,OAAO,EAAE,MAAM,EAAE,CAAC","sourcesContent":["abstract class Loader<T> {\n protected loadedAssets: Map<string, T> = new Map();\n protected loadingPromises: Map<string, Promise<T | undefined>> = new Map();\n\n #refCount: Map<string, number> = new Map();\n #incRefCount(id: string) { this.#refCount.set(id, (this.#refCount.get(id) || 0) + 1); }\n\n protected hasActiveRef(id: string) { return this.#refCount.get(id)! > 0; }\n protected abstract _load(id: string, ...args: any[]): Promise<T | undefined>;\n protected _dispose(id: string, asset: T): void { /* override to clean up */ }\n\n checkLoaded(id: string) {\n return this.loadedAssets.has(id);\n }\n\n async load(id: string, ...args: any[]) {\n this.#incRefCount(id);\n if (this.checkLoaded(id)) return this.loadedAssets.get(id);\n if (this.loadingPromises.has(id)) return await this.loadingPromises.get(id);\n return await this._load(id, ...args);\n }\n\n release(id: string) {\n const refCount = this.#refCount.get(id);\n if (refCount === undefined) throw new Error(`Asset not found: ${id}`);\n if (refCount === 1) {\n this.#refCount.delete(id);\n const asset = this.loadedAssets.get(id);\n if (asset) {\n this._dispose(id, asset);\n this.loadedAssets.delete(id);\n }\n } else {\n this.#refCount.set(id, refCount - 1);\n }\n }\n}\n\nexport { Loader };\n"]}
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/asset/loaders/loader.ts"],"names":[],"mappings":"AAAA,MAAM,OAAgB,MAAM;IAChB,YAAY,GAAG,IAAI,GAAG,EAAa,CAAA;IACnC,eAAe,GAAG,IAAI,GAAG,EAAkC,CAAA;IAErE,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAA;IACrC,YAAY,CAAC,EAAU,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA,CAAC,CAAC;IAE5E,YAAY,CAAC,EAAU,IAAI,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAE,GAAG,CAAC,CAAA,CAAC,CAAC;IAE/D,OAAO,CAAC,EAAU,EAAE,KAAQ,IAAqC,CAAC;IAE5E,WAAW,CAAC,EAAU;QACpB,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAClC,CAAC;IAED,SAAS,CAAC,EAAU;QAClB,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAA;QACpE,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAA;QACrB,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAClC,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAU,EAAE,GAAG,IAAW;QACnC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAA;QACrB,IAAI,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YAAE,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAC1D,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,OAAO,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAC3E,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,CAAA;IACvC,CAAC;IAED,OAAO,CAAC,EAAU;QAChB,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACvC,IAAI,QAAQ,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAA;QACrE,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;YACnB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;YACzB,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YACvC,IAAI,KAAK,EAAE,CAAC;gBACV,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,CAAC,CAAA;gBACvB,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;YAC9B,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAA;QACtC,CAAC;IACH,CAAC;CACF","sourcesContent":["export abstract class Loader<T> {\n protected cachedAssets = new Map<string, T>()\n protected loadingPromises = new Map<string, Promise<T | undefined>>()\n\n #refCount = new Map<string, number>()\n #incRefCount(id: string) { this.#refCount.set(id, (this.#refCount.get(id) || 0) + 1) }\n\n protected hasActiveRef(id: string) { return this.#refCount.get(id)! > 0 }\n protected abstract doLoad(id: string, ...args: any[]): Promise<T | undefined>\n protected cleanup(id: string, asset: T): void { /* override to clean up */ }\n\n checkCached(id: string) {\n return this.cachedAssets.has(id)\n }\n\n getCached(id: string) {\n if (!this.checkCached(id)) throw new Error(`Asset not found: ${id}`)\n this.#incRefCount(id)\n return this.cachedAssets.get(id)\n }\n\n async load(id: string, ...args: any[]) {\n this.#incRefCount(id)\n if (this.checkCached(id)) return this.cachedAssets.get(id)\n if (this.loadingPromises.has(id)) return await this.loadingPromises.get(id)\n return await this.doLoad(id, ...args)\n }\n\n release(id: string) {\n const refCount = this.#refCount.get(id)\n if (refCount === undefined) throw new Error(`Asset not found: ${id}`)\n if (refCount === 1) {\n this.#refCount.delete(id)\n const asset = this.cachedAssets.get(id)\n if (asset) {\n this.cleanup(id, asset)\n this.cachedAssets.delete(id)\n }\n } else {\n this.#refCount.set(id, refCount - 1)\n }\n }\n}\n"]}
@@ -3,7 +3,7 @@ import { Loader } from './loader';
3
3
  import { textureLoader } from './texture';
4
4
  const atlasIdCache = new WeakMap();
5
5
  let idCounter = 0;
6
- function getCachedId(src, atlas) {
6
+ export function getCachedAtlasId(src, atlas) {
7
7
  let innerMap = atlasIdCache.get(atlas);
8
8
  if (!innerMap) {
9
9
  innerMap = new Map();
@@ -16,7 +16,7 @@ function getCachedId(src, atlas) {
16
16
  }
17
17
  class SpritesheetLoader extends Loader {
18
18
  #idToSrc = new Map();
19
- async _load(id, src, atlas) {
19
+ async doLoad(id, src, atlas) {
20
20
  this.#idToSrc.set(id, src);
21
21
  const loadingPromise = (async () => {
22
22
  const texture = await textureLoader.load(src);
@@ -28,12 +28,12 @@ class SpritesheetLoader extends Loader {
28
28
  await spritesheet.parse();
29
29
  this.loadingPromises.delete(id);
30
30
  if (this.hasActiveRef(id)) {
31
- if (this.loadedAssets.has(id)) {
31
+ if (this.cachedAssets.has(id)) {
32
32
  textureLoader.release(src);
33
33
  console.error(`Spritesheet already exists: ${src}`);
34
34
  }
35
35
  else {
36
- this.loadedAssets.set(id, spritesheet);
36
+ this.cachedAssets.set(id, spritesheet);
37
37
  return spritesheet;
38
38
  }
39
39
  }
@@ -44,13 +44,12 @@ class SpritesheetLoader extends Loader {
44
44
  this.loadingPromises.set(id, loadingPromise);
45
45
  return await loadingPromise;
46
46
  }
47
- _dispose(id, spritesheet) {
47
+ cleanup(id, spritesheet) {
48
48
  spritesheet.destroy();
49
49
  const src = this.#idToSrc.get(id);
50
50
  if (src)
51
51
  textureLoader.release(src);
52
52
  }
53
53
  }
54
- const spritesheetLoader = new SpritesheetLoader();
55
- export { getCachedId, spritesheetLoader };
54
+ export const spritesheetLoader = new SpritesheetLoader();
56
55
  //# sourceMappingURL=spritesheet.js.map