kiwiengine 0.0.1-alpha → 0.5.3

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 (599) hide show
  1. package/README.ko.md +550 -0
  2. package/README.md +575 -4
  3. package/examples/auto-battle/assets/bgm/battle.mp3 +0 -0
  4. package/examples/auto-battle/assets/bitmap-fonts/white-peaberry.fnt +107 -0
  5. package/examples/auto-battle/assets/bitmap-fonts/white-peaberry.png +0 -0
  6. package/examples/auto-battle/assets/joystick/joystick.png +0 -0
  7. package/examples/auto-battle/assets/joystick/knob.png +0 -0
  8. package/examples/auto-battle/assets/sfx/hero/die/die.wav +0 -0
  9. package/examples/auto-battle/assets/sfx/hero/heal/heal.wav +0 -0
  10. package/examples/auto-battle/assets/sfx/hero/hit/hit1.wav +0 -0
  11. package/examples/auto-battle/assets/sfx/hero/hit/hit2.wav +0 -0
  12. package/examples/auto-battle/assets/sfx/hero/hit/hit3.wav +0 -0
  13. package/examples/auto-battle/assets/sfx/hero/miss/miss1.wav +0 -0
  14. package/examples/auto-battle/assets/sfx/hero/miss/miss2.wav +0 -0
  15. package/examples/auto-battle/assets/sfx/hero/miss/miss3.wav +0 -0
  16. package/examples/auto-battle/assets/sfx/orc/die/die.wav +0 -0
  17. package/examples/auto-battle/assets/sfx/orc/hit/hit1.wav +0 -0
  18. package/examples/auto-battle/assets/sfx/orc/hit/hit2.wav +0 -0
  19. package/examples/auto-battle/assets/sfx/orc/hit/hit3.wav +0 -0
  20. package/examples/auto-battle/assets/sfx/orc/miss/miss1.wav +0 -0
  21. package/examples/auto-battle/assets/sfx/orc/miss/miss2.wav +0 -0
  22. package/examples/auto-battle/assets/sfx/orc/miss/miss3.wav +0 -0
  23. package/examples/auto-battle/assets/spritesheets/hero-atlas.json +246 -0
  24. package/examples/auto-battle/assets/spritesheets/hero.png +0 -0
  25. package/examples/auto-battle/assets/spritesheets/orc-atlas.json +246 -0
  26. package/examples/auto-battle/assets/spritesheets/orc.png +0 -0
  27. package/examples/auto-battle/assets/spritesheets/potion-atlas.json +68 -0
  28. package/examples/auto-battle/assets/spritesheets/potion.png +0 -0
  29. package/examples/auto-battle/dist/game.js +2 -0
  30. package/examples/auto-battle/dist/game.js.LICENSE.txt +35 -0
  31. package/examples/auto-battle/hud/damage-text.ts +46 -0
  32. package/examples/auto-battle/hud/heal-text.ts +46 -0
  33. package/examples/auto-battle/hud/hp-bar.ts +38 -0
  34. package/examples/auto-battle/index.ts +41 -0
  35. package/examples/auto-battle/objects/character.ts +95 -0
  36. package/examples/auto-battle/objects/hero.ts +119 -0
  37. package/examples/auto-battle/objects/orc.ts +107 -0
  38. package/examples/auto-battle/objects/potion.ts +27 -0
  39. package/examples/auto-battle/stage.ts +366 -0
  40. package/examples/battle-benchmark-matterjs/assets/bgm/battle.mp3 +0 -0
  41. package/examples/battle-benchmark-matterjs/assets/bitmap-fonts/white-peaberry.fnt +107 -0
  42. package/examples/battle-benchmark-matterjs/assets/bitmap-fonts/white-peaberry.png +0 -0
  43. package/examples/battle-benchmark-matterjs/assets/joystick/joystick.png +0 -0
  44. package/examples/battle-benchmark-matterjs/assets/joystick/knob.png +0 -0
  45. package/examples/battle-benchmark-matterjs/assets/sfx/hero/die/die.wav +0 -0
  46. package/examples/battle-benchmark-matterjs/assets/sfx/hero/heal/heal.wav +0 -0
  47. package/examples/battle-benchmark-matterjs/assets/sfx/hero/hit/hit1.wav +0 -0
  48. package/examples/battle-benchmark-matterjs/assets/sfx/hero/hit/hit2.wav +0 -0
  49. package/examples/battle-benchmark-matterjs/assets/sfx/hero/hit/hit3.wav +0 -0
  50. package/examples/battle-benchmark-matterjs/assets/sfx/hero/miss/miss1.wav +0 -0
  51. package/examples/battle-benchmark-matterjs/assets/sfx/hero/miss/miss2.wav +0 -0
  52. package/examples/battle-benchmark-matterjs/assets/sfx/hero/miss/miss3.wav +0 -0
  53. package/examples/battle-benchmark-matterjs/assets/sfx/orc/die/die.wav +0 -0
  54. package/examples/battle-benchmark-matterjs/assets/sfx/orc/hit/hit1.wav +0 -0
  55. package/examples/battle-benchmark-matterjs/assets/sfx/orc/hit/hit2.wav +0 -0
  56. package/examples/battle-benchmark-matterjs/assets/sfx/orc/hit/hit3.wav +0 -0
  57. package/examples/battle-benchmark-matterjs/assets/sfx/orc/miss/miss1.wav +0 -0
  58. package/examples/battle-benchmark-matterjs/assets/sfx/orc/miss/miss2.wav +0 -0
  59. package/examples/battle-benchmark-matterjs/assets/sfx/orc/miss/miss3.wav +0 -0
  60. package/examples/battle-benchmark-matterjs/assets/spritesheets/hero-atlas.json +246 -0
  61. package/examples/battle-benchmark-matterjs/assets/spritesheets/hero.png +0 -0
  62. package/examples/battle-benchmark-matterjs/assets/spritesheets/orc-atlas.json +246 -0
  63. package/examples/battle-benchmark-matterjs/assets/spritesheets/orc.png +0 -0
  64. package/examples/battle-benchmark-matterjs/assets/spritesheets/potion-atlas.json +68 -0
  65. package/examples/battle-benchmark-matterjs/assets/spritesheets/potion.png +0 -0
  66. package/examples/battle-benchmark-matterjs/dist/game.js +2 -0
  67. package/examples/battle-benchmark-matterjs/dist/game.js.LICENSE.txt +35 -0
  68. package/examples/battle-benchmark-matterjs/hud/damage-text.ts +46 -0
  69. package/examples/battle-benchmark-matterjs/hud/heal-text.ts +46 -0
  70. package/examples/battle-benchmark-matterjs/hud/hp-bar.ts +38 -0
  71. package/examples/battle-benchmark-matterjs/index.html +24 -0
  72. package/examples/battle-benchmark-matterjs/index.ts +41 -0
  73. package/examples/battle-benchmark-matterjs/objects/character.ts +95 -0
  74. package/examples/battle-benchmark-matterjs/objects/hero.ts +111 -0
  75. package/examples/battle-benchmark-matterjs/objects/orc.ts +107 -0
  76. package/examples/battle-benchmark-matterjs/objects/potion.ts +27 -0
  77. package/examples/battle-benchmark-matterjs/stage.ts +177 -0
  78. package/examples/battle-benchmark-separation/assets/bgm/battle.mp3 +0 -0
  79. package/examples/battle-benchmark-separation/assets/bitmap-fonts/white-peaberry.fnt +107 -0
  80. package/examples/battle-benchmark-separation/assets/bitmap-fonts/white-peaberry.png +0 -0
  81. package/examples/battle-benchmark-separation/assets/joystick/joystick.png +0 -0
  82. package/examples/battle-benchmark-separation/assets/joystick/knob.png +0 -0
  83. package/examples/battle-benchmark-separation/assets/sfx/hero/die/die.wav +0 -0
  84. package/examples/battle-benchmark-separation/assets/sfx/hero/heal/heal.wav +0 -0
  85. package/examples/battle-benchmark-separation/assets/sfx/hero/hit/hit1.wav +0 -0
  86. package/examples/battle-benchmark-separation/assets/sfx/hero/hit/hit2.wav +0 -0
  87. package/examples/battle-benchmark-separation/assets/sfx/hero/hit/hit3.wav +0 -0
  88. package/examples/battle-benchmark-separation/assets/sfx/hero/miss/miss1.wav +0 -0
  89. package/examples/battle-benchmark-separation/assets/sfx/hero/miss/miss2.wav +0 -0
  90. package/examples/battle-benchmark-separation/assets/sfx/hero/miss/miss3.wav +0 -0
  91. package/examples/battle-benchmark-separation/assets/sfx/orc/die/die.wav +0 -0
  92. package/examples/battle-benchmark-separation/assets/sfx/orc/hit/hit1.wav +0 -0
  93. package/examples/battle-benchmark-separation/assets/sfx/orc/hit/hit2.wav +0 -0
  94. package/examples/battle-benchmark-separation/assets/sfx/orc/hit/hit3.wav +0 -0
  95. package/examples/battle-benchmark-separation/assets/sfx/orc/miss/miss1.wav +0 -0
  96. package/examples/battle-benchmark-separation/assets/sfx/orc/miss/miss2.wav +0 -0
  97. package/examples/battle-benchmark-separation/assets/sfx/orc/miss/miss3.wav +0 -0
  98. package/examples/battle-benchmark-separation/assets/spritesheets/hero-atlas.json +246 -0
  99. package/examples/battle-benchmark-separation/assets/spritesheets/hero.png +0 -0
  100. package/examples/battle-benchmark-separation/assets/spritesheets/orc-atlas.json +246 -0
  101. package/examples/battle-benchmark-separation/assets/spritesheets/orc.png +0 -0
  102. package/examples/battle-benchmark-separation/assets/spritesheets/potion-atlas.json +68 -0
  103. package/examples/battle-benchmark-separation/assets/spritesheets/potion.png +0 -0
  104. package/examples/battle-benchmark-separation/dist/game.js +2 -0
  105. package/examples/battle-benchmark-separation/dist/game.js.LICENSE.txt +35 -0
  106. package/examples/battle-benchmark-separation/hud/damage-text.ts +46 -0
  107. package/examples/battle-benchmark-separation/hud/heal-text.ts +46 -0
  108. package/examples/battle-benchmark-separation/hud/hp-bar.ts +38 -0
  109. package/examples/battle-benchmark-separation/index.html +24 -0
  110. package/examples/battle-benchmark-separation/index.ts +41 -0
  111. package/examples/battle-benchmark-separation/objects/character.ts +225 -0
  112. package/examples/battle-benchmark-separation/objects/hero.ts +110 -0
  113. package/examples/battle-benchmark-separation/objects/orc.ts +213 -0
  114. package/examples/battle-benchmark-separation/objects/potion.ts +27 -0
  115. package/examples/battle-benchmark-separation/stage.ts +178 -0
  116. package/examples/battle-benchmark-separation2/assets/bgm/battle.mp3 +0 -0
  117. package/examples/battle-benchmark-separation2/assets/bitmap-fonts/white-peaberry.fnt +107 -0
  118. package/examples/battle-benchmark-separation2/assets/bitmap-fonts/white-peaberry.png +0 -0
  119. package/examples/battle-benchmark-separation2/assets/joystick/joystick.png +0 -0
  120. package/examples/battle-benchmark-separation2/assets/joystick/knob.png +0 -0
  121. package/examples/battle-benchmark-separation2/assets/sfx/hero/die/die.wav +0 -0
  122. package/examples/battle-benchmark-separation2/assets/sfx/hero/heal/heal.wav +0 -0
  123. package/examples/battle-benchmark-separation2/assets/sfx/hero/hit/hit1.wav +0 -0
  124. package/examples/battle-benchmark-separation2/assets/sfx/hero/hit/hit2.wav +0 -0
  125. package/examples/battle-benchmark-separation2/assets/sfx/hero/hit/hit3.wav +0 -0
  126. package/examples/battle-benchmark-separation2/assets/sfx/hero/miss/miss1.wav +0 -0
  127. package/examples/battle-benchmark-separation2/assets/sfx/hero/miss/miss2.wav +0 -0
  128. package/examples/battle-benchmark-separation2/assets/sfx/hero/miss/miss3.wav +0 -0
  129. package/examples/battle-benchmark-separation2/assets/sfx/orc/die/die.wav +0 -0
  130. package/examples/battle-benchmark-separation2/assets/sfx/orc/hit/hit1.wav +0 -0
  131. package/examples/battle-benchmark-separation2/assets/sfx/orc/hit/hit2.wav +0 -0
  132. package/examples/battle-benchmark-separation2/assets/sfx/orc/hit/hit3.wav +0 -0
  133. package/examples/battle-benchmark-separation2/assets/sfx/orc/miss/miss1.wav +0 -0
  134. package/examples/battle-benchmark-separation2/assets/sfx/orc/miss/miss2.wav +0 -0
  135. package/examples/battle-benchmark-separation2/assets/sfx/orc/miss/miss3.wav +0 -0
  136. package/examples/battle-benchmark-separation2/assets/spritesheets/hero-atlas.json +246 -0
  137. package/examples/battle-benchmark-separation2/assets/spritesheets/hero.png +0 -0
  138. package/examples/battle-benchmark-separation2/assets/spritesheets/orc-atlas.json +246 -0
  139. package/examples/battle-benchmark-separation2/assets/spritesheets/orc.png +0 -0
  140. package/examples/battle-benchmark-separation2/assets/spritesheets/potion-atlas.json +68 -0
  141. package/examples/battle-benchmark-separation2/assets/spritesheets/potion.png +0 -0
  142. package/examples/battle-benchmark-separation2/dist/game.js +2 -0
  143. package/examples/battle-benchmark-separation2/dist/game.js.LICENSE.txt +35 -0
  144. package/examples/battle-benchmark-separation2/hud/damage-text.ts +46 -0
  145. package/examples/battle-benchmark-separation2/hud/heal-text.ts +46 -0
  146. package/examples/battle-benchmark-separation2/hud/hp-bar.ts +38 -0
  147. package/examples/battle-benchmark-separation2/index.html +24 -0
  148. package/examples/battle-benchmark-separation2/index.ts +41 -0
  149. package/examples/battle-benchmark-separation2/objects/character.ts +195 -0
  150. package/examples/battle-benchmark-separation2/objects/hero.ts +110 -0
  151. package/examples/battle-benchmark-separation2/objects/orc.ts +213 -0
  152. package/examples/battle-benchmark-separation2/objects/potion.ts +27 -0
  153. package/examples/battle-benchmark-separation2/stage.ts +178 -0
  154. package/examples/collision-test/assets/cat.png +0 -0
  155. package/examples/collision-test/dist/game.js +2 -0
  156. package/examples/collision-test/dist/game.js.LICENSE.txt +35 -0
  157. package/examples/collision-test/index.html +24 -0
  158. package/examples/collision-test/index.ts +30 -0
  159. package/examples/dom-particle-test/assets/bird.png +0 -0
  160. package/examples/dom-particle-test/dist/game.js +2 -0
  161. package/examples/dom-particle-test/dist/game.js.LICENSE.txt +35 -0
  162. package/examples/dom-particle-test/index.html +24 -0
  163. package/examples/dom-particle-test/index.ts +27 -0
  164. package/examples/dom-sprite-test/assets/bird.png +0 -0
  165. package/examples/dom-sprite-test/assets/fire.png +0 -0
  166. package/examples/dom-sprite-test/assets/run.png +0 -0
  167. package/examples/dom-sprite-test/dist/game.js +2 -0
  168. package/examples/dom-sprite-test/dist/game.js.LICENSE.txt +35 -0
  169. package/examples/dom-sprite-test/index.html +24 -0
  170. package/examples/dom-sprite-test/index.ts +35 -0
  171. package/examples/dom-test/dist/game.js +2 -0
  172. package/examples/dom-test/dist/game.js.LICENSE.txt +35 -0
  173. package/examples/dom-test/index.html +24 -0
  174. package/examples/dom-test/index.ts +22 -0
  175. package/examples/particle-test/assets/bird.png +0 -0
  176. package/examples/particle-test/dist/game.js +2 -0
  177. package/examples/particle-test/dist/game.js.LICENSE.txt +35 -0
  178. package/examples/particle-test/index.html +24 -0
  179. package/examples/particle-test/index.ts +30 -0
  180. package/examples/renderer-test/dist/game.js +2 -0
  181. package/examples/renderer-test/dist/game.js.LICENSE.txt +35 -0
  182. package/examples/renderer-test/index.html +24 -0
  183. package/examples/renderer-test/index.ts +9 -0
  184. package/examples/simple-battle/assets/bgm/battle.mp3 +0 -0
  185. package/examples/simple-battle/assets/bitmap-fonts/white-peaberry.fnt +107 -0
  186. package/examples/simple-battle/assets/bitmap-fonts/white-peaberry.png +0 -0
  187. package/examples/simple-battle/assets/joystick/joystick.png +0 -0
  188. package/examples/simple-battle/assets/joystick/knob.png +0 -0
  189. package/examples/simple-battle/assets/sfx/hero/die/die.wav +0 -0
  190. package/examples/simple-battle/assets/sfx/hero/heal/heal.wav +0 -0
  191. package/examples/simple-battle/assets/sfx/hero/hit/hit1.wav +0 -0
  192. package/examples/simple-battle/assets/sfx/hero/hit/hit2.wav +0 -0
  193. package/examples/simple-battle/assets/sfx/hero/hit/hit3.wav +0 -0
  194. package/examples/simple-battle/assets/sfx/hero/miss/miss1.wav +0 -0
  195. package/examples/simple-battle/assets/sfx/hero/miss/miss2.wav +0 -0
  196. package/examples/simple-battle/assets/sfx/hero/miss/miss3.wav +0 -0
  197. package/examples/simple-battle/assets/sfx/orc/die/die.wav +0 -0
  198. package/examples/simple-battle/assets/sfx/orc/hit/hit1.wav +0 -0
  199. package/examples/simple-battle/assets/sfx/orc/hit/hit2.wav +0 -0
  200. package/examples/simple-battle/assets/sfx/orc/hit/hit3.wav +0 -0
  201. package/examples/simple-battle/assets/sfx/orc/miss/miss1.wav +0 -0
  202. package/examples/simple-battle/assets/sfx/orc/miss/miss2.wav +0 -0
  203. package/examples/simple-battle/assets/sfx/orc/miss/miss3.wav +0 -0
  204. package/examples/simple-battle/assets/spritesheets/hero-atlas.json +246 -0
  205. package/examples/simple-battle/assets/spritesheets/hero.png +0 -0
  206. package/examples/simple-battle/assets/spritesheets/orc-atlas.json +246 -0
  207. package/examples/simple-battle/assets/spritesheets/orc.png +0 -0
  208. package/examples/simple-battle/assets/spritesheets/potion-atlas.json +68 -0
  209. package/examples/simple-battle/assets/spritesheets/potion.png +0 -0
  210. package/examples/simple-battle/dist/game.js +2 -0
  211. package/examples/simple-battle/dist/game.js.LICENSE.txt +35 -0
  212. package/examples/simple-battle/hud/damage-text.ts +46 -0
  213. package/examples/simple-battle/hud/heal-text.ts +46 -0
  214. package/examples/simple-battle/hud/hp-bar.ts +38 -0
  215. package/examples/simple-battle/index.html +24 -0
  216. package/examples/simple-battle/index.ts +41 -0
  217. package/examples/simple-battle/objects/character.ts +95 -0
  218. package/examples/simple-battle/objects/hero.ts +111 -0
  219. package/examples/simple-battle/objects/orc.ts +107 -0
  220. package/examples/simple-battle/objects/potion.ts +27 -0
  221. package/examples/simple-battle/stage.ts +174 -0
  222. package/examples/spine-test/assets/spine/spineboy.atlas +95 -0
  223. package/examples/spine-test/assets/spine/spineboy.png +0 -0
  224. package/examples/spine-test/assets/spine/spineboy.skel +0 -0
  225. package/examples/spine-test/dist/game.js +2 -0
  226. package/examples/spine-test/dist/game.js.LICENSE.txt +35 -0
  227. package/examples/spine-test/index.html +24 -0
  228. package/examples/spine-test/index.ts +29 -0
  229. package/examples/sprite-test/assets/bird.png +0 -0
  230. package/examples/sprite-test/assets/fire.png +0 -0
  231. package/examples/sprite-test/dist/game.js +2 -0
  232. package/examples/sprite-test/dist/game.js.LICENSE.txt +35 -0
  233. package/examples/sprite-test/index.html +24 -0
  234. package/examples/sprite-test/index.ts +38 -0
  235. package/examples/tsconfig.json +2 -1
  236. package/examples/webpack.config.js +17 -3
  237. package/jest.config.ts +10 -0
  238. package/lib/asset/audio.js +47 -11
  239. package/lib/asset/audio.js.map +1 -1
  240. package/lib/asset/loaders/audio.js +7 -4
  241. package/lib/asset/loaders/audio.js.map +1 -1
  242. package/lib/asset/loaders/binary.js +7 -4
  243. package/lib/asset/loaders/binary.js.map +1 -1
  244. package/lib/asset/loaders/bitmap-font.js +74 -0
  245. package/lib/asset/loaders/bitmap-font.js.map +1 -0
  246. package/lib/asset/loaders/font.js +4 -1
  247. package/lib/asset/loaders/font.js.map +1 -1
  248. package/lib/asset/loaders/loader.js +17 -12
  249. package/lib/asset/loaders/loader.js.map +1 -1
  250. package/lib/asset/loaders/spritesheet.js +18 -8
  251. package/lib/asset/loaders/spritesheet.js.map +1 -1
  252. package/lib/asset/loaders/text.js +6 -3
  253. package/lib/asset/loaders/text.js.map +1 -1
  254. package/lib/asset/loaders/texture.js +22 -26
  255. package/lib/asset/loaders/texture.js.map +1 -1
  256. package/lib/asset/preload.js +60 -56
  257. package/lib/asset/preload.js.map +1 -1
  258. package/lib/collision/check-collision.js +804 -0
  259. package/lib/collision/check-collision.js.map +1 -0
  260. package/lib/collision/check-collision.test.js +300 -0
  261. package/lib/collision/check-collision.test.js.map +1 -0
  262. package/lib/collision/colliders.js +8 -0
  263. package/lib/collision/colliders.js.map +1 -0
  264. package/lib/debug.js.map +1 -0
  265. package/lib/dom/dom-animated-sprite.js +106 -0
  266. package/lib/dom/dom-animated-sprite.js.map +1 -0
  267. package/lib/dom/dom-game-object.js +108 -0
  268. package/lib/dom/dom-game-object.js.map +1 -0
  269. package/lib/dom/dom-particle.js +105 -0
  270. package/lib/dom/dom-particle.js.map +1 -0
  271. package/lib/dom/dom-preload.js +43 -0
  272. package/lib/dom/dom-preload.js.map +1 -0
  273. package/lib/dom/dom-sprite.js +40 -0
  274. package/lib/dom/dom-sprite.js.map +1 -0
  275. package/lib/dom/dom-texture-loader.js +36 -0
  276. package/lib/dom/dom-texture-loader.js.map +1 -0
  277. package/lib/dom/dom-utils.js +20 -0
  278. package/lib/dom/dom-utils.js.map +1 -0
  279. package/lib/index copy.js +16 -0
  280. package/lib/index copy.js.map +1 -0
  281. package/lib/index.js +36 -10
  282. package/lib/index.js.map +1 -1
  283. package/lib/input/joystick.js +262 -0
  284. package/lib/input/joystick.js.map +1 -0
  285. package/lib/node/core/dirty-number.js +19 -0
  286. package/lib/node/core/dirty-number.js.map +1 -0
  287. package/lib/node/core/game-node.js +63 -0
  288. package/lib/node/core/game-node.js.map +1 -0
  289. package/lib/node/core/game-object.js +8 -0
  290. package/lib/node/core/game-object.js.map +1 -0
  291. package/lib/node/core/renderable.js +59 -0
  292. package/lib/node/core/renderable.js.map +1 -0
  293. package/lib/node/core/transform.js +70 -0
  294. package/lib/node/core/transform.js.map +1 -0
  295. package/lib/node/core/transformable.js +85 -0
  296. package/lib/node/core/transformable.js.map +1 -0
  297. package/lib/node/ext/animated-sprite.js +77 -0
  298. package/lib/node/ext/animated-sprite.js.map +1 -0
  299. package/lib/node/ext/bitmap-text.js +93 -0
  300. package/lib/node/ext/bitmap-text.js.map +1 -0
  301. package/lib/node/ext/circle.js +43 -0
  302. package/lib/node/ext/circle.js.map +1 -0
  303. package/lib/node/ext/deplay.js +22 -0
  304. package/lib/node/ext/deplay.js.map +1 -0
  305. package/lib/node/ext/dom-container.js +51 -0
  306. package/lib/node/ext/dom-container.js.map +1 -0
  307. package/lib/node/ext/interval.js +22 -0
  308. package/lib/node/ext/interval.js.map +1 -0
  309. package/lib/node/ext/particle.js +98 -0
  310. package/lib/node/ext/particle.js.map +1 -0
  311. package/lib/node/ext/rectangle.js +52 -0
  312. package/lib/node/ext/rectangle.js.map +1 -0
  313. package/lib/node/ext/spine.js +272 -0
  314. package/lib/node/ext/spine.js.map +1 -0
  315. package/lib/node/ext/sprite.js +42 -0
  316. package/lib/node/ext/sprite.js.map +1 -0
  317. package/lib/node/physics/physics-object.js +92 -0
  318. package/lib/node/physics/physics-object.js.map +1 -0
  319. package/lib/node/physics/physics-world.js +29 -0
  320. package/lib/node/physics/physics-world.js.map +1 -0
  321. package/lib/node/physics/rigidbodies.js +7 -0
  322. package/lib/node/physics/rigidbodies.js.map +1 -0
  323. package/lib/renderer/camera.js +19 -0
  324. package/lib/renderer/camera.js.map +1 -0
  325. package/lib/renderer/container-manager.js +29 -0
  326. package/lib/renderer/container-manager.js.map +1 -0
  327. package/lib/renderer/fps-display.js +18 -0
  328. package/lib/renderer/fps-display.js.map +1 -0
  329. package/lib/renderer/layer.js +12 -0
  330. package/lib/renderer/layer.js.map +1 -0
  331. package/lib/renderer/renderer.js +146 -0
  332. package/lib/renderer/renderer.js.map +1 -0
  333. package/lib/renderer/ticker.js +56 -0
  334. package/lib/renderer/ticker.js.map +1 -0
  335. package/lib/renderer/ticker.test.js +241 -0
  336. package/lib/renderer/ticker.test.js.map +1 -0
  337. package/lib/types/animation-atlas.js +2 -0
  338. package/lib/types/animation-atlas.js.map +1 -0
  339. package/lib/types/asset/audio.d.ts +5 -4
  340. package/lib/types/asset/audio.d.ts.map +1 -1
  341. package/lib/types/asset/loaders/audio.d.ts +2 -1
  342. package/lib/types/asset/loaders/audio.d.ts.map +1 -1
  343. package/lib/types/asset/loaders/binary.d.ts +2 -1
  344. package/lib/types/asset/loaders/binary.d.ts.map +1 -1
  345. package/lib/types/asset/loaders/bitmap-font.d.ts +17 -0
  346. package/lib/types/asset/loaders/bitmap-font.d.ts.map +1 -0
  347. package/lib/types/asset/loaders/font.d.ts +2 -1
  348. package/lib/types/asset/loaders/font.d.ts.map +1 -1
  349. package/lib/types/asset/loaders/loader.d.ts +6 -6
  350. package/lib/types/asset/loaders/loader.d.ts.map +1 -1
  351. package/lib/types/asset/loaders/spritesheet.d.ts +14 -6
  352. package/lib/types/asset/loaders/spritesheet.d.ts.map +1 -1
  353. package/lib/types/asset/loaders/text.d.ts +2 -1
  354. package/lib/types/asset/loaders/text.d.ts.map +1 -1
  355. package/lib/types/asset/loaders/texture.d.ts +2 -2
  356. package/lib/types/asset/loaders/texture.d.ts.map +1 -1
  357. package/lib/types/asset/preload.d.ts +7 -5
  358. package/lib/types/asset/preload.d.ts.map +1 -1
  359. package/lib/types/atlas copy.js +2 -0
  360. package/lib/types/atlas copy.js.map +1 -0
  361. package/lib/types/atlas.js +2 -0
  362. package/lib/types/atlas.js.map +1 -0
  363. package/lib/types/bitmap-font.js +2 -0
  364. package/lib/types/bitmap-font.js.map +1 -0
  365. package/lib/types/collision/check-collision.d.ts +4 -0
  366. package/lib/types/collision/check-collision.d.ts.map +1 -0
  367. package/lib/types/collision/check-collision.test.d.ts +2 -0
  368. package/lib/types/collision/check-collision.test.d.ts.map +1 -0
  369. package/lib/types/collision/colliders.d.ts +34 -0
  370. package/lib/types/collision/colliders.d.ts.map +1 -0
  371. package/lib/types/debug.d.ts.map +1 -0
  372. package/lib/types/dom/dom-animated-sprite.d.ts +23 -0
  373. package/lib/types/dom/dom-animated-sprite.d.ts.map +1 -0
  374. package/lib/types/dom/dom-game-object.d.ts +44 -0
  375. package/lib/types/dom/dom-game-object.d.ts.map +1 -0
  376. package/lib/types/dom/dom-particle.d.ts +30 -0
  377. package/lib/types/dom/dom-particle.d.ts.map +1 -0
  378. package/lib/types/dom/dom-preload.d.ts +2 -0
  379. package/lib/types/dom/dom-preload.d.ts.map +1 -0
  380. package/lib/types/dom/dom-sprite.d.ts +13 -0
  381. package/lib/types/dom/dom-sprite.d.ts.map +1 -0
  382. package/lib/types/dom/dom-texture-loader.d.ts +8 -0
  383. package/lib/types/dom/dom-texture-loader.d.ts.map +1 -0
  384. package/lib/types/dom/dom-utils.d.ts +3 -0
  385. package/lib/types/dom/dom-utils.d.ts.map +1 -0
  386. package/lib/types/index copy.d.ts +16 -0
  387. package/lib/types/index copy.d.ts.map +1 -0
  388. package/lib/types/index.d.ts +26 -11
  389. package/lib/types/index.d.ts.map +1 -1
  390. package/lib/types/input/joystick.d.ts +28 -0
  391. package/lib/types/input/joystick.d.ts.map +1 -0
  392. package/lib/types/node/core/dirty-number.d.ts +9 -0
  393. package/lib/types/node/core/dirty-number.d.ts.map +1 -0
  394. package/lib/types/node/core/game-node.d.ts +16 -0
  395. package/lib/types/node/core/game-node.d.ts.map +1 -0
  396. package/lib/types/node/core/game-object.d.ts +8 -0
  397. package/lib/types/node/core/game-object.d.ts.map +1 -0
  398. package/lib/types/node/core/renderable.d.ts +23 -0
  399. package/lib/types/node/core/renderable.d.ts.map +1 -0
  400. package/lib/types/node/core/transform.d.ts +27 -0
  401. package/lib/types/node/core/transform.d.ts.map +1 -0
  402. package/lib/types/node/core/transformable.d.ts +44 -0
  403. package/lib/types/node/core/transformable.d.ts.map +1 -0
  404. package/lib/types/node/ext/animated-sprite.d.ts +22 -0
  405. package/lib/types/node/ext/animated-sprite.d.ts.map +1 -0
  406. package/lib/types/node/ext/bitmap-text.d.ts +14 -0
  407. package/lib/types/node/ext/bitmap-text.d.ts.map +1 -0
  408. package/lib/types/node/ext/circle.d.ts +19 -0
  409. package/lib/types/node/ext/circle.d.ts.map +1 -0
  410. package/lib/types/node/ext/deplay.d.ts +8 -0
  411. package/lib/types/node/ext/deplay.d.ts.map +1 -0
  412. package/lib/types/node/ext/dom-container.d.ts +12 -0
  413. package/lib/types/node/ext/dom-container.d.ts.map +1 -0
  414. package/lib/types/node/ext/interval.d.ts +9 -0
  415. package/lib/types/node/ext/interval.d.ts.map +1 -0
  416. package/lib/types/node/ext/particle.d.ts +30 -0
  417. package/lib/types/node/ext/particle.d.ts.map +1 -0
  418. package/lib/types/node/ext/rectangle.d.ts +22 -0
  419. package/lib/types/node/ext/rectangle.d.ts.map +1 -0
  420. package/lib/types/node/ext/spine.d.ts +36 -0
  421. package/lib/types/node/ext/spine.d.ts.map +1 -0
  422. package/lib/types/node/ext/sprite.d.ts +13 -0
  423. package/lib/types/node/ext/sprite.d.ts.map +1 -0
  424. package/lib/types/node/physics/physics-object.d.ts +38 -0
  425. package/lib/types/node/physics/physics-object.d.ts.map +1 -0
  426. package/lib/types/node/physics/physics-world.d.ts +18 -0
  427. package/lib/types/node/physics/physics-world.d.ts.map +1 -0
  428. package/lib/types/node/physics/rigidbodies.d.ts +23 -0
  429. package/lib/types/node/physics/rigidbodies.d.ts.map +1 -0
  430. package/lib/types/renderer/camera.d.ts +13 -0
  431. package/lib/types/renderer/camera.d.ts.map +1 -0
  432. package/lib/types/renderer/container-manager.d.ts +9 -0
  433. package/lib/types/renderer/container-manager.d.ts.map +1 -0
  434. package/lib/types/renderer/fps-display.d.ts +7 -0
  435. package/lib/types/renderer/fps-display.d.ts.map +1 -0
  436. package/lib/types/renderer/layer.d.ts +7 -0
  437. package/lib/types/renderer/layer.d.ts.map +1 -0
  438. package/lib/types/renderer/renderer.d.ts +40 -0
  439. package/lib/types/renderer/renderer.d.ts.map +1 -0
  440. package/lib/types/renderer/ticker.d.ts +6 -0
  441. package/lib/types/renderer/ticker.d.ts.map +1 -0
  442. package/lib/types/renderer/ticker.test.d.ts +40 -0
  443. package/lib/types/renderer/ticker.test.d.ts.map +1 -0
  444. package/lib/types/sprite-atlas.js +2 -0
  445. package/lib/types/sprite-atlas.js.map +1 -0
  446. package/lib/types/types/animation-atlas.d.ts +14 -0
  447. package/lib/types/types/animation-atlas.d.ts.map +1 -0
  448. package/lib/types/types/atlas copy.d.ts +12 -0
  449. package/lib/types/types/atlas copy.d.ts.map +1 -0
  450. package/lib/types/types/atlas.d.ts +16 -0
  451. package/lib/types/types/atlas.d.ts.map +1 -0
  452. package/lib/types/types/bitmap-font.d.ts +18 -0
  453. package/lib/types/types/bitmap-font.d.ts.map +1 -0
  454. package/lib/types/types/sprite-atlas.d.ts +13 -0
  455. package/lib/types/types/sprite-atlas.d.ts.map +1 -0
  456. package/lib/types/utils/device.d.ts +2 -0
  457. package/lib/types/utils/device.d.ts.map +1 -0
  458. package/lib/utils/device.js +2 -0
  459. package/lib/utils/device.js.map +1 -0
  460. package/package.json +8 -7
  461. package/src/asset/audio.ts +134 -90
  462. package/src/asset/loaders/audio.ts +23 -20
  463. package/src/asset/loaders/binary.ts +20 -16
  464. package/src/asset/loaders/bitmap-font.ts +91 -0
  465. package/src/asset/loaders/font.ts +18 -14
  466. package/src/asset/loaders/loader.ts +27 -23
  467. package/src/asset/loaders/spritesheet.ts +47 -36
  468. package/src/asset/loaders/text.ts +19 -15
  469. package/src/asset/loaders/texture.ts +30 -37
  470. package/src/asset/preload.ts +71 -64
  471. package/src/collision/check-collision.test.ts +349 -0
  472. package/src/collision/check-collision.ts +821 -0
  473. package/src/collision/colliders.ts +19 -0
  474. package/src/debug.ts +5 -0
  475. package/src/dom/dom-animated-sprite.ts +132 -0
  476. package/src/dom/dom-game-object.ts +134 -0
  477. package/src/dom/dom-particle.ts +151 -0
  478. package/src/dom/dom-preload.ts +54 -0
  479. package/src/dom/dom-sprite.ts +50 -0
  480. package/src/dom/dom-texture-loader.ts +44 -0
  481. package/src/dom/dom-utils.ts +19 -0
  482. package/src/index.ts +47 -13
  483. package/src/input/joystick.ts +316 -0
  484. package/src/node/core/dirty-number.ts +21 -0
  485. package/src/node/core/game-node.ts +74 -0
  486. package/src/node/core/game-object.ts +11 -0
  487. package/src/node/core/renderable.ts +72 -0
  488. package/src/node/core/transform.ts +82 -0
  489. package/src/node/core/transformable.ts +111 -0
  490. package/src/node/ext/animated-sprite.ts +103 -0
  491. package/src/node/ext/bitmap-text.ts +113 -0
  492. package/src/node/ext/circle.ts +55 -0
  493. package/src/node/ext/deplay.ts +25 -0
  494. package/src/node/ext/dom-container.ts +62 -0
  495. package/src/node/ext/interval.ts +25 -0
  496. package/src/node/ext/particle.ts +142 -0
  497. package/src/node/ext/rectangle.ts +71 -0
  498. package/src/node/ext/spine.ts +323 -0
  499. package/src/node/ext/sprite.ts +53 -0
  500. package/src/node/physics/physics-object.ts +127 -0
  501. package/src/node/physics/physics-world.ts +41 -0
  502. package/src/node/physics/rigidbodies.ts +14 -0
  503. package/src/renderer/camera.ts +25 -0
  504. package/src/renderer/container-manager.ts +36 -0
  505. package/src/renderer/fps-display.ts +21 -0
  506. package/src/renderer/layer.ts +15 -0
  507. package/src/renderer/renderer.ts +181 -0
  508. package/src/renderer/ticker.test.ts +325 -0
  509. package/src/renderer/ticker.ts +54 -0
  510. package/src/types/atlas.ts +17 -0
  511. package/src/types/bitmap-font.ts +19 -0
  512. package/src/utils/device.ts +1 -0
  513. package/examples/test-dom/index.ts +0 -21
  514. package/lib/game-object/game-object-physics.js +0 -188
  515. package/lib/game-object/game-object-physics.js.map +0 -1
  516. package/lib/game-object/game-object-rendering.js +0 -35
  517. package/lib/game-object/game-object-rendering.js.map +0 -1
  518. package/lib/game-object/game-object.js +0 -162
  519. package/lib/game-object/game-object.js.map +0 -1
  520. package/lib/game-object/transform.js +0 -118
  521. package/lib/game-object/transform.js.map +0 -1
  522. package/lib/game-object-ext/animated-sprite.js +0 -117
  523. package/lib/game-object-ext/animated-sprite.js.map +0 -1
  524. package/lib/game-object-ext/dom-container.js +0 -56
  525. package/lib/game-object-ext/dom-container.js.map +0 -1
  526. package/lib/game-object-ext/rect.js +0 -30
  527. package/lib/game-object-ext/rect.js.map +0 -1
  528. package/lib/game-object-ext/spine.js +0 -206
  529. package/lib/game-object-ext/spine.js.map +0 -1
  530. package/lib/game-object-ext/sprite.js +0 -46
  531. package/lib/game-object-ext/sprite.js.map +0 -1
  532. package/lib/game-object-ext/text.js +0 -68
  533. package/lib/game-object-ext/text.js.map +0 -1
  534. package/lib/game-object-ext/tiling-sprite.js +0 -64
  535. package/lib/game-object-ext/tiling-sprite.js.map +0 -1
  536. package/lib/types/game-object/game-object-physics.d.ts +0 -42
  537. package/lib/types/game-object/game-object-physics.d.ts.map +0 -1
  538. package/lib/types/game-object/game-object-rendering.d.ts +0 -15
  539. package/lib/types/game-object/game-object-rendering.d.ts.map +0 -1
  540. package/lib/types/game-object/game-object.d.ts +0 -81
  541. package/lib/types/game-object/game-object.d.ts.map +0 -1
  542. package/lib/types/game-object/transform.d.ts +0 -43
  543. package/lib/types/game-object/transform.d.ts.map +0 -1
  544. package/lib/types/game-object-ext/animated-sprite.d.ts +0 -29
  545. package/lib/types/game-object-ext/animated-sprite.d.ts.map +0 -1
  546. package/lib/types/game-object-ext/dom-container.d.ts +0 -16
  547. package/lib/types/game-object-ext/dom-container.d.ts.map +0 -1
  548. package/lib/types/game-object-ext/rect.d.ts +0 -17
  549. package/lib/types/game-object-ext/rect.d.ts.map +0 -1
  550. package/lib/types/game-object-ext/spine.d.ts +0 -35
  551. package/lib/types/game-object-ext/spine.d.ts.map +0 -1
  552. package/lib/types/game-object-ext/sprite.d.ts +0 -14
  553. package/lib/types/game-object-ext/sprite.d.ts.map +0 -1
  554. package/lib/types/game-object-ext/text.d.ts +0 -26
  555. package/lib/types/game-object-ext/text.d.ts.map +0 -1
  556. package/lib/types/game-object-ext/tiling-sprite.d.ts +0 -20
  557. package/lib/types/game-object-ext/tiling-sprite.d.ts.map +0 -1
  558. package/lib/types/utils/debug.d.ts.map +0 -1
  559. package/lib/types/utils/go.d.ts +0 -26
  560. package/lib/types/utils/go.d.ts.map +0 -1
  561. package/lib/types/world/world-debug.d.ts +0 -11
  562. package/lib/types/world/world-debug.d.ts.map +0 -1
  563. package/lib/types/world/world-physics.d.ts +0 -16
  564. package/lib/types/world/world-physics.d.ts.map +0 -1
  565. package/lib/types/world/world-rendering.d.ts +0 -28
  566. package/lib/types/world/world-rendering.d.ts.map +0 -1
  567. package/lib/types/world/world.d.ts +0 -38
  568. package/lib/types/world/world.d.ts.map +0 -1
  569. package/lib/utils/debug.js.map +0 -1
  570. package/lib/utils/go.js +0 -33
  571. package/lib/utils/go.js.map +0 -1
  572. package/lib/world/world-debug.js +0 -89
  573. package/lib/world/world-debug.js.map +0 -1
  574. package/lib/world/world-physics.js +0 -45
  575. package/lib/world/world-physics.js.map +0 -1
  576. package/lib/world/world-rendering.js +0 -123
  577. package/lib/world/world-rendering.js.map +0 -1
  578. package/lib/world/world.js +0 -147
  579. package/lib/world/world.js.map +0 -1
  580. package/src/game-object/game-object-physics.ts +0 -191
  581. package/src/game-object/game-object-rendering.ts +0 -27
  582. package/src/game-object/game-object.ts +0 -190
  583. package/src/game-object/transform.ts +0 -164
  584. package/src/game-object-ext/animated-sprite.ts +0 -140
  585. package/src/game-object-ext/dom-container.ts +0 -67
  586. package/src/game-object-ext/rect.ts +0 -40
  587. package/src/game-object-ext/spine.ts +0 -235
  588. package/src/game-object-ext/sprite.ts +0 -55
  589. package/src/game-object-ext/text.ts +0 -83
  590. package/src/game-object-ext/tiling-sprite.ts +0 -73
  591. package/src/utils/debug.ts +0 -5
  592. package/src/utils/go.ts +0 -53
  593. package/src/world/world-debug.ts +0 -114
  594. package/src/world/world-physics.ts +0 -52
  595. package/src/world/world-rendering.ts +0 -145
  596. package/src/world/world.ts +0 -171
  597. /package/examples/{test-dom → auto-battle}/index.html +0 -0
  598. /package/lib/{utils/debug.js → debug.js} +0 -0
  599. /package/lib/types/{utils/debug.d.ts → debug.d.ts} +0 -0
@@ -0,0 +1,316 @@
1
+ import { setStyle } from '../dom/dom-utils'
2
+ import { GameObject } from '../node/core/game-object'
3
+ import { Renderer } from '../renderer/renderer'
4
+
5
+ const ARROW_CODES = new Set(['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'])
6
+
7
+ function isArrow(code: string): boolean {
8
+ return ARROW_CODES.has(code)
9
+ }
10
+
11
+ function clampVector(dx: number, dy: number, maxR: number) {
12
+ const dist = Math.hypot(dx, dy)
13
+ if (dist <= maxR || dist === 0) return { x: dx, y: dy, dist }
14
+ const s = maxR / dist
15
+ return { x: dx * s, y: dy * s, dist: maxR }
16
+ }
17
+
18
+ function setPosition(el: HTMLElement | undefined, left: number, top: number) {
19
+ if (!el) return
20
+ el.style.left = `${left}px`
21
+ el.style.top = `${top}px`
22
+ }
23
+
24
+ export type JoystickOptions = {
25
+ // 공통 필수 콜백
26
+ onMove: (radian: number, strength: number) => void // 키보드일 때 strength=1
27
+ onRelease: () => void
28
+
29
+ // 선택 콜백
30
+ onKeyDown?: (code: string) => void
31
+
32
+ // (선택) 터치 전용 리소스/옵션
33
+ joystickImage?: HTMLElement // 조이스틱 배경
34
+ knobImage?: HTMLElement // 노브(스틱)
35
+ maxKnobDistance?: number // px (기본 80)
36
+ moveThreshold?: number // px (기본 0)
37
+ idlePosition?: { left: number; top: number } // 이미지 기본 위치 (기본값은 숨김 위치 -999999, -999999)
38
+ }
39
+
40
+ export class Joystick extends GameObject {
41
+ // 키보드 상태
42
+ #codesPressed = new Set<string>()
43
+ #arrowCodesPressed = new Set<string>()
44
+
45
+ // 터치 상태
46
+ #activeTouchId?: number
47
+ #touchStartX = 0
48
+ #touchStartY = 0
49
+ #moving = false
50
+
51
+ // DOM (터치용)
52
+ #joystickImage?: HTMLElement
53
+ #knobImage?: HTMLElement
54
+ #maxKnobDistance: number
55
+ #moveThreshold: number
56
+ #idlePosition: { left: number; top: number }
57
+
58
+ // 콜백
59
+ #onMove: (radian: number, strength: number) => void
60
+ #onRelease: () => void
61
+ #onKeydown?: (code: string) => void
62
+
63
+ constructor(options: JoystickOptions) {
64
+ super()
65
+
66
+ this.#onMove = options.onMove
67
+ this.#onRelease = options.onRelease
68
+ this.#onKeydown = options.onKeyDown
69
+ this.#joystickImage = options.joystickImage
70
+ this.#knobImage = options.knobImage
71
+ this.#maxKnobDistance = options.maxKnobDistance ?? 80
72
+ this.#moveThreshold = options.moveThreshold ?? 0
73
+ this.#idlePosition = options.idlePosition ?? { left: -999999, top: -999999 }
74
+
75
+ window.addEventListener('keydown', this.#onKeyDown)
76
+ window.addEventListener('keyup', this.#onKeyUp)
77
+ window.addEventListener('blur', this.#onBlur)
78
+ }
79
+
80
+ protected override set renderer(renderer: Renderer | undefined) {
81
+ const prev = super.renderer
82
+ if (prev) {
83
+ const pc = prev.container
84
+ pc.removeEventListener('touchstart', this.#onTouchStart)
85
+ pc.removeEventListener('touchmove', this.#onTouchMove)
86
+ pc.removeEventListener('touchend', this.#onTouchEnd)
87
+ pc.removeEventListener('touchcancel', this.#onTouchEnd)
88
+ }
89
+
90
+ super.renderer = renderer
91
+ if (renderer) {
92
+ const c = renderer.container
93
+ c.addEventListener('touchstart', this.#onTouchStart, { passive: false })
94
+ c.addEventListener('touchmove', this.#onTouchMove, { passive: false })
95
+ c.addEventListener('touchend', this.#onTouchEnd)
96
+ c.addEventListener('touchcancel', this.#onTouchEnd)
97
+
98
+ if (this.#joystickImage) {
99
+ setStyle(this.#joystickImage, {
100
+ position: 'absolute',
101
+ left: `${this.#idlePosition.left}px`,
102
+ top: `${this.#idlePosition.top}px`,
103
+ zIndex: '999998',
104
+ transform: 'translate(-50%, -50%)',
105
+ pointerEvents: 'none',
106
+ })
107
+ c.appendChild(this.#joystickImage)
108
+ }
109
+
110
+ if (this.#knobImage) {
111
+ setStyle(this.#knobImage, {
112
+ position: 'absolute',
113
+ left: `${this.#idlePosition.left}px`,
114
+ top: `${this.#idlePosition.top}px`,
115
+ zIndex: '999999',
116
+ transform: 'translate(-50%, -50%)',
117
+ pointerEvents: 'none',
118
+ })
119
+ c.appendChild(this.#knobImage)
120
+ }
121
+ }
122
+ }
123
+
124
+ protected override get renderer() {
125
+ return super.renderer
126
+ }
127
+
128
+ #onTouchStart = (event: TouchEvent) => {
129
+ if (this.paused) return
130
+ event.preventDefault()
131
+
132
+ if (this.#activeTouchId !== undefined) return
133
+
134
+ const touch = event.changedTouches[0]
135
+ this.#activeTouchId = touch.identifier
136
+ this.#touchStartX = touch.clientX
137
+ this.#touchStartY = touch.clientY
138
+ this.#moving = false
139
+
140
+ if (!this.renderer) return
141
+
142
+ const r = this.renderer.container.getBoundingClientRect()
143
+ const left = this.#touchStartX - r.left
144
+ const top = this.#touchStartY - r.top
145
+
146
+ setPosition(this.#joystickImage, left, top)
147
+ setPosition(this.#knobImage, left, top)
148
+ }
149
+
150
+ #onTouchMove = (event: TouchEvent) => {
151
+ if (this.paused) return
152
+ event.preventDefault()
153
+
154
+ if (this.#activeTouchId === undefined) return
155
+
156
+ for (let i = 0; i < event.changedTouches.length; i++) {
157
+ const t = event.changedTouches[i]
158
+ if (t.identifier !== this.#activeTouchId) continue
159
+
160
+ const dx = t.clientX - this.#touchStartX
161
+ const dy = t.clientY - this.#touchStartY
162
+
163
+ const { x: cx, y: cy, dist } = clampVector(dx, dy, this.#maxKnobDistance)
164
+
165
+ if (this.renderer) {
166
+ const r = this.renderer.container.getBoundingClientRect()
167
+ const left = this.#touchStartX - r.left + cx
168
+ const top = this.#touchStartY - r.top + cy
169
+ setPosition(this.#knobImage, left, top)
170
+ }
171
+
172
+ if (this.#moving || dist >= this.#moveThreshold) {
173
+ this.#moving = true
174
+ if (cx !== 0 || cy !== 0) {
175
+ const radian = Math.atan2(cy, cx)
176
+ const normalized = this.#maxKnobDistance === 0 ? 0 : dist / this.#maxKnobDistance
177
+ this.#onMove(radian, normalized)
178
+ }
179
+ }
180
+ break
181
+ }
182
+ }
183
+
184
+ #onTouchEnd = (event: TouchEvent) => {
185
+ if (this.paused || this.#activeTouchId === undefined) return
186
+
187
+ let ended = false
188
+ for (let i = 0; i < event.changedTouches.length; i++) {
189
+ if (event.changedTouches[i].identifier === this.#activeTouchId) {
190
+ ended = true
191
+ break
192
+ }
193
+ }
194
+ if (!ended) return
195
+
196
+ this.#activeTouchId = undefined
197
+
198
+ // 기본 위치로 복귀
199
+ const { left, top } = this.#idlePosition
200
+ setPosition(this.#joystickImage, left, top)
201
+ setPosition(this.#knobImage, left, top)
202
+
203
+ if (this.#moving) {
204
+ this.#moving = false
205
+ this.#onRelease()
206
+ }
207
+ }
208
+
209
+ #emitFromArrowKeys() {
210
+ let dx = 0
211
+ let dy = 0
212
+
213
+ if (this.#arrowCodesPressed.has('ArrowUp')) dy -= 1
214
+ if (this.#arrowCodesPressed.has('ArrowDown')) dy += 1
215
+ if (this.#arrowCodesPressed.has('ArrowLeft')) dx -= 1
216
+ if (this.#arrowCodesPressed.has('ArrowRight')) dx += 1
217
+
218
+ if (dx !== 0 || dy !== 0) {
219
+ const radian = Math.atan2(dy, dx)
220
+ // 키보드: strength=1 로 일관 전달
221
+ this.#onMove(radian, 1)
222
+ }
223
+ }
224
+
225
+ #onKeyDown = (event: KeyboardEvent) => {
226
+ if (this.paused) return
227
+
228
+ const code = event.code
229
+ if (this.#codesPressed.has(code)) return
230
+
231
+ this.#codesPressed.add(code)
232
+ this.#onKeydown?.(code)
233
+
234
+ if (isArrow(code)) {
235
+ const target = event.target as HTMLElement | null
236
+ const isEditing =
237
+ !!target?.closest('input, textarea, [contenteditable]:not([contenteditable="false"])')
238
+ if (!isEditing) event.preventDefault()
239
+
240
+ this.#arrowCodesPressed.add(code)
241
+ this.#emitFromArrowKeys()
242
+ }
243
+ }
244
+
245
+ #onKeyUp = (event: KeyboardEvent) => {
246
+ if (this.paused) return
247
+
248
+ const code = event.code
249
+ this.#codesPressed.delete(code)
250
+
251
+ if (isArrow(code)) {
252
+ this.#arrowCodesPressed.delete(code)
253
+
254
+ if (this.#arrowCodesPressed.size === 0) {
255
+ this.#onRelease()
256
+ } else {
257
+ this.#emitFromArrowKeys()
258
+ }
259
+ }
260
+ }
261
+
262
+ #onBlur = () => {
263
+ if (this.paused) return
264
+
265
+ // 키보드/터치 공통 릴리즈
266
+ this.#codesPressed.clear()
267
+ this.#arrowCodesPressed.clear()
268
+ this.#activeTouchId = undefined
269
+ this.#moving = false
270
+
271
+ // 기본 위치로 복귀
272
+ const { left, top } = this.#idlePosition
273
+ setPosition(this.#joystickImage, left, top)
274
+ setPosition(this.#knobImage, left, top)
275
+
276
+ this.#onRelease()
277
+ }
278
+
279
+ override pause() {
280
+ this.#onBlur()
281
+ super.pause()
282
+ }
283
+
284
+ // 조이스틱 이미지의 기본 위치(숨김 좌표) 설정
285
+ setIdlePosition(p: { left: number; top: number }): void {
286
+ this.#idlePosition = p
287
+
288
+ // 드래그 중이면 즉시 반영하지 않음
289
+ if (this.#activeTouchId !== undefined) return
290
+
291
+ setPosition(this.#joystickImage, p.left, p.top)
292
+ setPosition(this.#knobImage, p.left, p.top)
293
+ }
294
+
295
+ override remove() {
296
+ const renderer = this.renderer
297
+ if (renderer) {
298
+ const c = renderer.container
299
+ c.removeEventListener('touchstart', this.#onTouchStart)
300
+ c.removeEventListener('touchmove', this.#onTouchMove)
301
+ c.removeEventListener('touchend', this.#onTouchEnd)
302
+ c.removeEventListener('touchcancel', this.#onTouchEnd)
303
+ }
304
+
305
+ // 윈도우 리스너 정리
306
+ window.removeEventListener('keydown', this.#onKeyDown)
307
+ window.removeEventListener('keyup', this.#onKeyUp)
308
+ window.removeEventListener('blur', this.#onBlur)
309
+
310
+ // DOM 노드 제거
311
+ this.#joystickImage?.remove()
312
+ this.#knobImage?.remove()
313
+
314
+ super.remove()
315
+ }
316
+ }
@@ -0,0 +1,21 @@
1
+ export class DirtyNumber {
2
+ #value: number
3
+ #isDirty: boolean
4
+
5
+ constructor(initialValue: number) {
6
+ this.#value = initialValue
7
+ this.#isDirty = false
8
+ }
9
+
10
+ get dirty() { return this.#isDirty }
11
+ get v() { return this.#value }
12
+
13
+ set v(newValue: number) {
14
+ if (this.#value !== newValue) this.#isDirty = true
15
+ this.#value = newValue
16
+ }
17
+
18
+ resetDirty() {
19
+ this.#isDirty = false
20
+ }
21
+ }
@@ -0,0 +1,74 @@
1
+ import { EventEmitter, EventMap } from '@webtaku/event-emitter'
2
+
3
+ export abstract class GameNode<E extends EventMap> extends EventEmitter<E & {
4
+ update: (dt: number) => void
5
+ }> {
6
+ #parent?: GameNode<EventMap>
7
+ protected children: GameNode<EventMap>[] = [];
8
+ paused = false
9
+
10
+ protected set parent(parent: GameNode<EventMap> | undefined) {
11
+ this.#parent = parent
12
+ }
13
+
14
+ protected get parent() {
15
+ return this.#parent
16
+ }
17
+
18
+ add(...children: GameNode<EventMap>[]) {
19
+ for (const child of children) {
20
+
21
+ // 기존 부모로부터 제거
22
+ if (child.#parent) {
23
+ const idx = child.#parent.children.indexOf(child)
24
+ if (idx !== -1) child.#parent.children.splice(idx, 1)
25
+ }
26
+
27
+ // 새로운 부모 설정
28
+ child.parent = this
29
+ this.children.push(child)
30
+ }
31
+ }
32
+
33
+ remove() {
34
+ super.remove()
35
+
36
+ // 부모로부터 제거
37
+ if (this.#parent) {
38
+ const idx = this.#parent.children.indexOf(this)
39
+ if (idx !== -1) this.#parent.children.splice(idx, 1)
40
+ this.#parent = undefined
41
+ }
42
+
43
+ // 자식 노드 제거
44
+ for (const child of this.children) {
45
+ child.parent = undefined
46
+ child.remove()
47
+ }
48
+ this.children.length = 0
49
+ }
50
+
51
+ pause() {
52
+ this.paused = true
53
+ for (const child of this.children) {
54
+ child.pause()
55
+ }
56
+ }
57
+
58
+ resume() {
59
+ this.paused = false
60
+ for (const child of this.children) {
61
+ child.resume()
62
+ }
63
+ }
64
+
65
+ protected update(dt: number) {
66
+ if (this.paused) return
67
+
68
+ for (const child of this.children) {
69
+ if (!child.paused) child.update(dt)
70
+ }
71
+
72
+ (this as any).emit('update', dt)
73
+ }
74
+ }
@@ -0,0 +1,11 @@
1
+ import { EventMap } from '@webtaku/event-emitter'
2
+ import { Container as PixiContainer } from 'pixi.js'
3
+ import { TransformableNode, TransformableNodeOptions } from './transformable'
4
+
5
+ export type GameObjectOptions = {} & TransformableNodeOptions
6
+
7
+ export class GameObject<E extends EventMap = EventMap> extends TransformableNode<PixiContainer, E> {
8
+ constructor(options?: GameObjectOptions) {
9
+ super(new PixiContainer({ sortableChildren: true }), options ?? {})
10
+ }
11
+ }
@@ -0,0 +1,72 @@
1
+ import { EventMap } from '@webtaku/event-emitter'
2
+ import { Container as PixiContainer } from 'pixi.js'
3
+ import { Renderer } from '../../renderer/renderer'
4
+ import { DirtyNumber } from './dirty-number'
5
+ import { GameNode } from './game-node'
6
+ import { WorldTransform } from './transform'
7
+
8
+ export function isRenderableNode(v: unknown): v is RenderableNode<PixiContainer, EventMap> {
9
+ return (v as RenderableNode<PixiContainer, EventMap>).worldTransform !== undefined
10
+ }
11
+
12
+ export abstract class RenderableNode<C extends PixiContainer, E extends EventMap> extends GameNode<E> {
13
+ #renderer?: Renderer
14
+ _pixiContainer: C
15
+
16
+ worldTransform = new WorldTransform()
17
+ worldAlpha = new DirtyNumber(1)
18
+
19
+ constructor(pixiContainer: C) {
20
+ super()
21
+ this._pixiContainer = pixiContainer
22
+ }
23
+
24
+ protected set renderer(renderer: Renderer | undefined) {
25
+ this.#renderer = renderer
26
+
27
+ for (const child of this.children) {
28
+ if (isRenderableNode(child)) {
29
+ child.renderer = renderer
30
+ }
31
+ }
32
+ }
33
+
34
+ protected get renderer() {
35
+ return this.#renderer
36
+ }
37
+
38
+ override add(...children: GameNode<EventMap>[]) {
39
+ super.add(...children)
40
+
41
+ for (const child of children) {
42
+ if (isRenderableNode(child)) {
43
+ this._pixiContainer.addChild(child._pixiContainer)
44
+
45
+ // 렌더러 설정
46
+ if (this.#renderer) child.renderer = this.#renderer
47
+ }
48
+ }
49
+ }
50
+
51
+ override remove() {
52
+ this._pixiContainer.destroy({ children: true })
53
+ super.remove()
54
+ }
55
+
56
+ _updateWorldTransform() {
57
+ for (const child of this.children) {
58
+ if (isRenderableNode(child)) child._updateWorldTransform()
59
+ }
60
+ }
61
+
62
+ _resetWorldTransformDirty() {
63
+ for (const child of this.children) {
64
+ if (isRenderableNode(child)) child._resetWorldTransformDirty()
65
+ }
66
+ this.worldTransform.resetDirty()
67
+ this.worldAlpha.resetDirty()
68
+ }
69
+
70
+ set tint(t) { this._pixiContainer.tint = t }
71
+ get tint() { return this._pixiContainer.tint }
72
+ }
@@ -0,0 +1,82 @@
1
+ import { DirtyNumber } from './dirty-number'
2
+
3
+ export class LocalTransform {
4
+ x = 0
5
+ y = 0
6
+ scaleX = 1
7
+ scaleY = 1
8
+ pivotX = 0
9
+ pivotY = 0
10
+
11
+ #rotation = 0
12
+ #cos = 1
13
+ #sin = 0
14
+
15
+ get cos() { return this.#cos }
16
+ get sin() { return this.#sin }
17
+ get rotation() { return this.#rotation }
18
+
19
+ set rotation(v) {
20
+ if (this.#rotation !== v) {
21
+ this.#rotation = v
22
+ this.#cos = Math.cos(v)
23
+ this.#sin = Math.sin(v)
24
+ }
25
+ }
26
+ }
27
+
28
+ export class WorldTransform {
29
+ x = new DirtyNumber(NaN)
30
+ y = new DirtyNumber(NaN)
31
+ scaleX = new DirtyNumber(1)
32
+ scaleY = new DirtyNumber(1)
33
+ rotation = new DirtyNumber(0)
34
+ cos = 1
35
+ sin = 0
36
+
37
+ update(parent: WorldTransform, local: LocalTransform) {
38
+ const rx = local.x * parent.scaleX.v
39
+ const ry = local.y * parent.scaleY.v
40
+ const pCos = parent.cos
41
+ const pSin = parent.sin
42
+
43
+ this.scaleX.v = parent.scaleX.v * local.scaleX
44
+ this.scaleY.v = parent.scaleY.v * local.scaleY
45
+
46
+ const pivotX = local.pivotX * this.scaleX.v
47
+ const pivotY = local.pivotY * this.scaleY.v
48
+
49
+ // 로컬 회전
50
+ const lCos = local.cos
51
+ const lSin = local.sin
52
+ // 월드 회전(부모+자식) cos/sin — 덧셈정리
53
+ const wCos = pCos * lCos - pSin * lSin
54
+ const wSin = pSin * lCos + pCos * lSin
55
+
56
+ // 위치: 부모 회전으로 (rx,ry) 회전 + 월드 회전으로 피벗 보정
57
+ this.x.v = parent.x.v + (rx * pCos - ry * pSin) - (pivotX * wCos - pivotY * wSin)
58
+ this.y.v = parent.y.v + (rx * pSin + ry * pCos) - (pivotX * wSin + pivotY * wCos)
59
+
60
+ // 회전(스칼라 값)
61
+ const rot = parent.rotation.v + local.rotation
62
+ this.rotation.v = rot
63
+ this.cos = wCos
64
+ this.sin = wSin
65
+ }
66
+
67
+ get dirty() {
68
+ return this.x.dirty ||
69
+ this.y.dirty ||
70
+ this.scaleX.dirty ||
71
+ this.scaleY.dirty ||
72
+ this.rotation.dirty
73
+ }
74
+
75
+ resetDirty() {
76
+ this.x.resetDirty()
77
+ this.y.resetDirty()
78
+ this.scaleX.resetDirty()
79
+ this.scaleY.resetDirty()
80
+ this.rotation.resetDirty()
81
+ }
82
+ }
@@ -0,0 +1,111 @@
1
+ import { EventMap } from '@webtaku/event-emitter'
2
+ import { Container as PixiContainer } from 'pixi.js'
3
+ import { Renderer } from '../../renderer/renderer'
4
+ import { isRenderableNode, RenderableNode } from './renderable'
5
+ import { LocalTransform } from './transform'
6
+
7
+ export type TransformableNodeOptions = {
8
+ x?: number
9
+ y?: number
10
+ scale?: number
11
+ scaleX?: number
12
+ scaleY?: number
13
+ pivotX?: number
14
+ pivotY?: number
15
+ rotation?: number
16
+
17
+ alpha?: number
18
+ layer?: string
19
+ useYSort?: boolean
20
+ }
21
+
22
+ export abstract class TransformableNode<C extends PixiContainer, E extends EventMap> extends RenderableNode<C, E> {
23
+ protected localTransform = new LocalTransform()
24
+
25
+ alpha = 1
26
+ #layer?: string
27
+ #useYSort = false
28
+
29
+ constructor(pixiContainer: C, options: TransformableNodeOptions) {
30
+ super(pixiContainer)
31
+
32
+ if (options.x !== undefined) this.x = options.x
33
+ if (options.y !== undefined) this.y = options.y
34
+ if (options.scale !== undefined) this.scale = options.scale
35
+ if (options.scaleX !== undefined) this.scaleX = options.scaleX
36
+ if (options.scaleY !== undefined) this.scaleY = options.scaleY
37
+ if (options.pivotX !== undefined) this.pivotX = options.pivotX
38
+ if (options.pivotY !== undefined) this.pivotY = options.pivotY
39
+ if (options.rotation !== undefined) this.rotation = options.rotation
40
+ if (options.alpha !== undefined) this.alpha = options.alpha
41
+
42
+ this.#layer = options.layer
43
+ this.#useYSort = options.useYSort ?? false
44
+ }
45
+
46
+ protected override set renderer(renderer: Renderer | undefined) {
47
+ super.renderer = renderer
48
+
49
+ if (this.#layer && renderer) {
50
+ renderer._addToLayer(this, this.#layer)
51
+ }
52
+ }
53
+
54
+ protected override get renderer() {
55
+ return super.renderer
56
+ }
57
+
58
+ override _updateWorldTransform() {
59
+ const parent = this.parent
60
+ if (parent && isRenderableNode(parent)) {
61
+ this.worldTransform.update(parent.worldTransform, this.localTransform)
62
+ this.worldAlpha.v = parent.worldAlpha.v * this.alpha
63
+ }
64
+
65
+ const pc = this._pixiContainer
66
+ const renderer = this.renderer
67
+
68
+ // 레이어 상에 있는 경우, 독립적으로 업데이트
69
+ if (this.#layer && renderer) {
70
+ const wt = this.worldTransform
71
+ pc.position.set(wt.x.v, wt.y.v)
72
+ pc.scale.set(wt.scaleX.v, wt.scaleY.v)
73
+ pc.rotation = wt.rotation.v
74
+ pc.alpha = this.worldAlpha.v
75
+ } else {
76
+ const lt = this.localTransform
77
+ pc.position.set(lt.x, lt.y)
78
+ if (this.#useYSort) pc.zIndex = lt.y
79
+ pc.pivot.set(lt.pivotX, lt.pivotY)
80
+ pc.scale.set(lt.scaleX, lt.scaleY)
81
+ pc.rotation = lt.rotation
82
+ pc.alpha = this.alpha
83
+ }
84
+
85
+ super._updateWorldTransform()
86
+ }
87
+
88
+ set x(v) { this.localTransform.x = v }
89
+ get x() { return this.localTransform.x }
90
+
91
+ set y(v) { this.localTransform.y = v }
92
+ get y() { return this.localTransform.y }
93
+
94
+ set scale(v) { this.localTransform.scaleX = v; this.localTransform.scaleY = v }
95
+ get scale() { return this.localTransform.scaleX }
96
+
97
+ set scaleX(v) { this.localTransform.scaleX = v }
98
+ get scaleX() { return this.localTransform.scaleX }
99
+
100
+ set scaleY(v) { this.localTransform.scaleY = v }
101
+ get scaleY() { return this.localTransform.scaleY }
102
+
103
+ set pivotX(v) { this.localTransform.pivotX = v }
104
+ get pivotX() { return this.localTransform.pivotX }
105
+
106
+ set pivotY(v) { this.localTransform.pivotY = v }
107
+ get pivotY() { return this.localTransform.pivotY }
108
+
109
+ set rotation(v) { this.localTransform.rotation = v }
110
+ get rotation() { return this.localTransform.rotation }
111
+ }