@datamoc/mw_games 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (425) hide show
  1. package/LICENSE +373 -0
  2. package/README.md +327 -0
  3. package/dist/actors/Advancement.d.ts +73 -0
  4. package/dist/actors/Advancement.d.ts.map +1 -0
  5. package/dist/actors/Advancement.js +98 -0
  6. package/dist/actors/Advancement.js.map +1 -0
  7. package/dist/actors/Affix.d.ts +44 -0
  8. package/dist/actors/Affix.d.ts.map +1 -0
  9. package/dist/actors/Affix.js +35 -0
  10. package/dist/actors/Affix.js.map +1 -0
  11. package/dist/actors/Appearances.d.ts +36 -0
  12. package/dist/actors/Appearances.d.ts.map +1 -0
  13. package/dist/actors/Appearances.js +50 -0
  14. package/dist/actors/Appearances.js.map +1 -0
  15. package/dist/actors/Charges.d.ts +31 -0
  16. package/dist/actors/Charges.d.ts.map +1 -0
  17. package/dist/actors/Charges.js +35 -0
  18. package/dist/actors/Charges.js.map +1 -0
  19. package/dist/actors/Equipment.d.ts +40 -0
  20. package/dist/actors/Equipment.d.ts.map +1 -0
  21. package/dist/actors/Equipment.js +57 -0
  22. package/dist/actors/Equipment.js.map +1 -0
  23. package/dist/actors/Inventory.d.ts +50 -0
  24. package/dist/actors/Inventory.d.ts.map +1 -0
  25. package/dist/actors/Inventory.js +56 -0
  26. package/dist/actors/Inventory.js.map +1 -0
  27. package/dist/actors/ItemState.d.ts +21 -0
  28. package/dist/actors/ItemState.d.ts.map +1 -0
  29. package/dist/actors/ItemState.js +34 -0
  30. package/dist/actors/ItemState.js.map +1 -0
  31. package/dist/actors/Loot.d.ts +24 -0
  32. package/dist/actors/Loot.d.ts.map +1 -0
  33. package/dist/actors/Loot.js +14 -0
  34. package/dist/actors/Loot.js.map +1 -0
  35. package/dist/actors/Progression.d.ts +30 -0
  36. package/dist/actors/Progression.d.ts.map +1 -0
  37. package/dist/actors/Progression.js +39 -0
  38. package/dist/actors/Progression.js.map +1 -0
  39. package/dist/actors/Resource.d.ts +23 -0
  40. package/dist/actors/Resource.d.ts.map +1 -0
  41. package/dist/actors/Resource.js +28 -0
  42. package/dist/actors/Resource.js.map +1 -0
  43. package/dist/actors/Scaling.d.ts +22 -0
  44. package/dist/actors/Scaling.d.ts.map +1 -0
  45. package/dist/actors/Scaling.js +9 -0
  46. package/dist/actors/Scaling.js.map +1 -0
  47. package/dist/actors/Shop.d.ts +25 -0
  48. package/dist/actors/Shop.d.ts.map +1 -0
  49. package/dist/actors/Shop.js +33 -0
  50. package/dist/actors/Shop.js.map +1 -0
  51. package/dist/actors/SkillPoints.d.ts +45 -0
  52. package/dist/actors/SkillPoints.d.ts.map +1 -0
  53. package/dist/actors/SkillPoints.js +58 -0
  54. package/dist/actors/SkillPoints.js.map +1 -0
  55. package/dist/actors/StatBlock.d.ts +52 -0
  56. package/dist/actors/StatBlock.d.ts.map +1 -0
  57. package/dist/actors/StatBlock.js +80 -0
  58. package/dist/actors/StatBlock.js.map +1 -0
  59. package/dist/actors/StatusEffect.d.ts +38 -0
  60. package/dist/actors/StatusEffect.d.ts.map +1 -0
  61. package/dist/actors/StatusEffect.js +28 -0
  62. package/dist/actors/StatusEffect.js.map +1 -0
  63. package/dist/actors/craft.d.ts +26 -0
  64. package/dist/actors/craft.d.ts.map +1 -0
  65. package/dist/actors/craft.js +34 -0
  66. package/dist/actors/craft.js.map +1 -0
  67. package/dist/actors/index.d.ts +33 -0
  68. package/dist/actors/index.d.ts.map +1 -0
  69. package/dist/actors/index.js +18 -0
  70. package/dist/actors/index.js.map +1 -0
  71. package/dist/actors/skillCheck.d.ts +13 -0
  72. package/dist/actors/skillCheck.d.ts.map +1 -0
  73. package/dist/actors/skillCheck.js +16 -0
  74. package/dist/actors/skillCheck.js.map +1 -0
  75. package/dist/assets/index.d.ts +37 -0
  76. package/dist/assets/index.d.ts.map +1 -0
  77. package/dist/assets/index.js +62 -0
  78. package/dist/assets/index.js.map +1 -0
  79. package/dist/audio/Music.d.ts +22 -0
  80. package/dist/audio/Music.d.ts.map +1 -0
  81. package/dist/audio/Music.js +67 -0
  82. package/dist/audio/Music.js.map +1 -0
  83. package/dist/audio/Playable.d.ts +16 -0
  84. package/dist/audio/Playable.d.ts.map +1 -0
  85. package/dist/audio/Playable.js +6 -0
  86. package/dist/audio/Playable.js.map +1 -0
  87. package/dist/audio/Sound.d.ts +23 -0
  88. package/dist/audio/Sound.d.ts.map +1 -0
  89. package/dist/audio/Sound.js +30 -0
  90. package/dist/audio/Sound.js.map +1 -0
  91. package/dist/audio/index.d.ts +7 -0
  92. package/dist/audio/index.d.ts.map +1 -0
  93. package/dist/audio/index.js +4 -0
  94. package/dist/audio/index.js.map +1 -0
  95. package/dist/battle/BattleAI.d.ts +24 -0
  96. package/dist/battle/BattleAI.d.ts.map +1 -0
  97. package/dist/battle/BattleAI.js +47 -0
  98. package/dist/battle/BattleAI.js.map +1 -0
  99. package/dist/battle/Evolution.d.ts +22 -0
  100. package/dist/battle/Evolution.d.ts.map +1 -0
  101. package/dist/battle/Evolution.js +25 -0
  102. package/dist/battle/Evolution.js.map +1 -0
  103. package/dist/battle/Field.d.ts +25 -0
  104. package/dist/battle/Field.d.ts.map +1 -0
  105. package/dist/battle/Field.js +31 -0
  106. package/dist/battle/Field.js.map +1 -0
  107. package/dist/battle/Hooks.d.ts +29 -0
  108. package/dist/battle/Hooks.d.ts.map +1 -0
  109. package/dist/battle/Hooks.js +20 -0
  110. package/dist/battle/Hooks.js.map +1 -0
  111. package/dist/battle/Move.d.ts +32 -0
  112. package/dist/battle/Move.d.ts.map +1 -0
  113. package/dist/battle/Move.js +10 -0
  114. package/dist/battle/Move.js.map +1 -0
  115. package/dist/battle/Party.d.ts +21 -0
  116. package/dist/battle/Party.d.ts.map +1 -0
  117. package/dist/battle/Party.js +49 -0
  118. package/dist/battle/Party.js.map +1 -0
  119. package/dist/battle/Species.d.ts +40 -0
  120. package/dist/battle/Species.d.ts.map +1 -0
  121. package/dist/battle/Species.js +31 -0
  122. package/dist/battle/Species.js.map +1 -0
  123. package/dist/battle/StatStages.d.ts +38 -0
  124. package/dist/battle/StatStages.d.ts.map +1 -0
  125. package/dist/battle/StatStages.js +50 -0
  126. package/dist/battle/StatStages.js.map +1 -0
  127. package/dist/battle/TypeMatrix.d.ts +14 -0
  128. package/dist/battle/TypeMatrix.d.ts.map +1 -0
  129. package/dist/battle/TypeMatrix.js +24 -0
  130. package/dist/battle/TypeMatrix.js.map +1 -0
  131. package/dist/battle/index.d.ts +16 -0
  132. package/dist/battle/index.d.ts.map +1 -0
  133. package/dist/battle/index.js +10 -0
  134. package/dist/battle/index.js.map +1 -0
  135. package/dist/board/Classics.d.ts +123 -0
  136. package/dist/board/Classics.d.ts.map +1 -0
  137. package/dist/board/Classics.js +260 -0
  138. package/dist/board/Classics.js.map +1 -0
  139. package/dist/board/Engine.d.ts +23 -0
  140. package/dist/board/Engine.d.ts.map +1 -0
  141. package/dist/board/Engine.js +87 -0
  142. package/dist/board/Engine.js.map +1 -0
  143. package/dist/board/Tactics.d.ts +46 -0
  144. package/dist/board/Tactics.d.ts.map +1 -0
  145. package/dist/board/Tactics.js +108 -0
  146. package/dist/board/Tactics.js.map +1 -0
  147. package/dist/board/chess.d.ts +67 -0
  148. package/dist/board/chess.d.ts.map +1 -0
  149. package/dist/board/chess.js +439 -0
  150. package/dist/board/chess.js.map +1 -0
  151. package/dist/board/index.d.ts +9 -0
  152. package/dist/board/index.d.ts.map +1 -0
  153. package/dist/board/index.js +5 -0
  154. package/dist/board/index.js.map +1 -0
  155. package/dist/core/Achievements.d.ts +53 -0
  156. package/dist/core/Achievements.d.ts.map +1 -0
  157. package/dist/core/Achievements.js +80 -0
  158. package/dist/core/Achievements.js.map +1 -0
  159. package/dist/core/Collection.d.ts +46 -0
  160. package/dist/core/Collection.d.ts.map +1 -0
  161. package/dist/core/Collection.js +61 -0
  162. package/dist/core/Collection.js.map +1 -0
  163. package/dist/core/Game.d.ts +115 -0
  164. package/dist/core/Game.d.ts.map +1 -0
  165. package/dist/core/Game.js +236 -0
  166. package/dist/core/Game.js.map +1 -0
  167. package/dist/core/Hex.d.ts +45 -0
  168. package/dist/core/Hex.d.ts.map +1 -0
  169. package/dist/core/Hex.js +120 -0
  170. package/dist/core/Hex.js.map +1 -0
  171. package/dist/core/Input.d.ts +41 -0
  172. package/dist/core/Input.d.ts.map +1 -0
  173. package/dist/core/Input.js +132 -0
  174. package/dist/core/Input.js.map +1 -0
  175. package/dist/core/Log.d.ts +39 -0
  176. package/dist/core/Log.d.ts.map +1 -0
  177. package/dist/core/Log.js +50 -0
  178. package/dist/core/Log.js.map +1 -0
  179. package/dist/core/Random.d.ts +64 -0
  180. package/dist/core/Random.d.ts.map +1 -0
  181. package/dist/core/Random.js +178 -0
  182. package/dist/core/Random.js.map +1 -0
  183. package/dist/core/Replay.d.ts +71 -0
  184. package/dist/core/Replay.d.ts.map +1 -0
  185. package/dist/core/Replay.js +102 -0
  186. package/dist/core/Replay.js.map +1 -0
  187. package/dist/core/Save.d.ts +52 -0
  188. package/dist/core/Save.d.ts.map +1 -0
  189. package/dist/core/Save.js +81 -0
  190. package/dist/core/Save.js.map +1 -0
  191. package/dist/core/Scene.d.ts +40 -0
  192. package/dist/core/Scene.d.ts.map +1 -0
  193. package/dist/core/Scene.js +56 -0
  194. package/dist/core/Scene.js.map +1 -0
  195. package/dist/core/SceneStack.d.ts +37 -0
  196. package/dist/core/SceneStack.d.ts.map +1 -0
  197. package/dist/core/SceneStack.js +67 -0
  198. package/dist/core/SceneStack.js.map +1 -0
  199. package/dist/core/Signal.d.ts +24 -0
  200. package/dist/core/Signal.d.ts.map +1 -0
  201. package/dist/core/Signal.js +41 -0
  202. package/dist/core/Signal.js.map +1 -0
  203. package/dist/core/index.d.ts +23 -0
  204. package/dist/core/index.d.ts.map +1 -0
  205. package/dist/core/index.js +14 -0
  206. package/dist/core/index.js.map +1 -0
  207. package/dist/i18n/index.d.ts +51 -0
  208. package/dist/i18n/index.d.ts.map +1 -0
  209. package/dist/i18n/index.js +74 -0
  210. package/dist/i18n/index.js.map +1 -0
  211. package/dist/index.d.ts +22 -0
  212. package/dist/index.d.ts.map +1 -0
  213. package/dist/index.js +22 -0
  214. package/dist/index.js.map +1 -0
  215. package/dist/mw_games.global.js +993 -0
  216. package/dist/render/ActorAnimator.d.ts +60 -0
  217. package/dist/render/ActorAnimator.d.ts.map +1 -0
  218. package/dist/render/ActorAnimator.js +76 -0
  219. package/dist/render/ActorAnimator.js.map +1 -0
  220. package/dist/render/AnimatedSprite.d.ts +57 -0
  221. package/dist/render/AnimatedSprite.d.ts.map +1 -0
  222. package/dist/render/AnimatedSprite.js +105 -0
  223. package/dist/render/AnimatedSprite.js.map +1 -0
  224. package/dist/render/Autotile.d.ts +42 -0
  225. package/dist/render/Autotile.d.ts.map +1 -0
  226. package/dist/render/Autotile.js +117 -0
  227. package/dist/render/Autotile.js.map +1 -0
  228. package/dist/render/Camera.d.ts +88 -0
  229. package/dist/render/Camera.d.ts.map +1 -0
  230. package/dist/render/Camera.js +145 -0
  231. package/dist/render/Camera.js.map +1 -0
  232. package/dist/render/ColorTransformBatcher.d.ts +57 -0
  233. package/dist/render/ColorTransformBatcher.d.ts.map +1 -0
  234. package/dist/render/ColorTransformBatcher.js +212 -0
  235. package/dist/render/ColorTransformBatcher.js.map +1 -0
  236. package/dist/render/LayeredSprite.d.ts +27 -0
  237. package/dist/render/LayeredSprite.d.ts.map +1 -0
  238. package/dist/render/LayeredSprite.js +53 -0
  239. package/dist/render/LayeredSprite.js.map +1 -0
  240. package/dist/render/Projectile.d.ts +37 -0
  241. package/dist/render/Projectile.d.ts.map +1 -0
  242. package/dist/render/Projectile.js +50 -0
  243. package/dist/render/Projectile.js.map +1 -0
  244. package/dist/render/SpriteSheet.d.ts +38 -0
  245. package/dist/render/SpriteSheet.d.ts.map +1 -0
  246. package/dist/render/SpriteSheet.js +79 -0
  247. package/dist/render/SpriteSheet.js.map +1 -0
  248. package/dist/render/TileMap.d.ts +188 -0
  249. package/dist/render/TileMap.d.ts.map +1 -0
  250. package/dist/render/TileMap.js +488 -0
  251. package/dist/render/TileMap.js.map +1 -0
  252. package/dist/render/TintedSprite.d.ts +47 -0
  253. package/dist/render/TintedSprite.d.ts.map +1 -0
  254. package/dist/render/TintedSprite.js +173 -0
  255. package/dist/render/TintedSprite.js.map +1 -0
  256. package/dist/render/index.d.ts +18 -0
  257. package/dist/render/index.d.ts.map +1 -0
  258. package/dist/render/index.js +11 -0
  259. package/dist/render/index.js.map +1 -0
  260. package/dist/roguelike/Blob.d.ts +46 -0
  261. package/dist/roguelike/Blob.d.ts.map +1 -0
  262. package/dist/roguelike/Blob.js +98 -0
  263. package/dist/roguelike/Blob.js.map +1 -0
  264. package/dist/roguelike/Boss.d.ts +67 -0
  265. package/dist/roguelike/Boss.d.ts.map +1 -0
  266. package/dist/roguelike/Boss.js +114 -0
  267. package/dist/roguelike/Boss.js.map +1 -0
  268. package/dist/roguelike/Combat.d.ts +23 -0
  269. package/dist/roguelike/Combat.d.ts.map +1 -0
  270. package/dist/roguelike/Combat.js +27 -0
  271. package/dist/roguelike/Combat.js.map +1 -0
  272. package/dist/roguelike/Doors.d.ts +60 -0
  273. package/dist/roguelike/Doors.d.ts.map +1 -0
  274. package/dist/roguelike/Doors.js +102 -0
  275. package/dist/roguelike/Doors.js.map +1 -0
  276. package/dist/roguelike/Elevation.d.ts +26 -0
  277. package/dist/roguelike/Elevation.d.ts.map +1 -0
  278. package/dist/roguelike/Elevation.js +37 -0
  279. package/dist/roguelike/Elevation.js.map +1 -0
  280. package/dist/roguelike/FieldOfView.d.ts +72 -0
  281. package/dist/roguelike/FieldOfView.d.ts.map +1 -0
  282. package/dist/roguelike/FieldOfView.js +134 -0
  283. package/dist/roguelike/FieldOfView.js.map +1 -0
  284. package/dist/roguelike/Level.d.ts +96 -0
  285. package/dist/roguelike/Level.d.ts.map +1 -0
  286. package/dist/roguelike/Level.js +137 -0
  287. package/dist/roguelike/Level.js.map +1 -0
  288. package/dist/roguelike/MonsterAI.d.ts +40 -0
  289. package/dist/roguelike/MonsterAI.d.ts.map +1 -0
  290. package/dist/roguelike/MonsterAI.js +69 -0
  291. package/dist/roguelike/MonsterAI.js.map +1 -0
  292. package/dist/roguelike/Pathfinder.d.ts +82 -0
  293. package/dist/roguelike/Pathfinder.d.ts.map +1 -0
  294. package/dist/roguelike/Pathfinder.js +192 -0
  295. package/dist/roguelike/Pathfinder.js.map +1 -0
  296. package/dist/roguelike/Scheduler.d.ts +45 -0
  297. package/dist/roguelike/Scheduler.d.ts.map +1 -0
  298. package/dist/roguelike/Scheduler.js +82 -0
  299. package/dist/roguelike/Scheduler.js.map +1 -0
  300. package/dist/roguelike/Secrets.d.ts +44 -0
  301. package/dist/roguelike/Secrets.d.ts.map +1 -0
  302. package/dist/roguelike/Secrets.js +64 -0
  303. package/dist/roguelike/Secrets.js.map +1 -0
  304. package/dist/roguelike/Targeting.d.ts +66 -0
  305. package/dist/roguelike/Targeting.d.ts.map +1 -0
  306. package/dist/roguelike/Targeting.js +150 -0
  307. package/dist/roguelike/Targeting.js.map +1 -0
  308. package/dist/roguelike/generate.d.ts +44 -0
  309. package/dist/roguelike/generate.d.ts.map +1 -0
  310. package/dist/roguelike/generate.js +88 -0
  311. package/dist/roguelike/generate.js.map +1 -0
  312. package/dist/roguelike/index.d.ts +23 -0
  313. package/dist/roguelike/index.d.ts.map +1 -0
  314. package/dist/roguelike/index.js +15 -0
  315. package/dist/roguelike/index.js.map +1 -0
  316. package/dist/rpg/Event.d.ts +33 -0
  317. package/dist/rpg/Event.d.ts.map +1 -0
  318. package/dist/rpg/Event.js +19 -0
  319. package/dist/rpg/Event.js.map +1 -0
  320. package/dist/rpg/EventRunner.d.ts +72 -0
  321. package/dist/rpg/EventRunner.d.ts.map +1 -0
  322. package/dist/rpg/EventRunner.js +76 -0
  323. package/dist/rpg/EventRunner.js.map +1 -0
  324. package/dist/rpg/GameState.d.ts +22 -0
  325. package/dist/rpg/GameState.d.ts.map +1 -0
  326. package/dist/rpg/GameState.js +35 -0
  327. package/dist/rpg/GameState.js.map +1 -0
  328. package/dist/rpg/GridMover.d.ts +51 -0
  329. package/dist/rpg/GridMover.d.ts.map +1 -0
  330. package/dist/rpg/GridMover.js +91 -0
  331. package/dist/rpg/GridMover.js.map +1 -0
  332. package/dist/rpg/Quest.d.ts +67 -0
  333. package/dist/rpg/Quest.d.ts.map +1 -0
  334. package/dist/rpg/Quest.js +92 -0
  335. package/dist/rpg/Quest.js.map +1 -0
  336. package/dist/rpg/TiledMap.d.ts +107 -0
  337. package/dist/rpg/TiledMap.d.ts.map +1 -0
  338. package/dist/rpg/TiledMap.js +123 -0
  339. package/dist/rpg/TiledMap.js.map +1 -0
  340. package/dist/rpg/automap.d.ts +40 -0
  341. package/dist/rpg/automap.d.ts.map +1 -0
  342. package/dist/rpg/automap.js +81 -0
  343. package/dist/rpg/automap.js.map +1 -0
  344. package/dist/rpg/index.d.ts +14 -0
  345. package/dist/rpg/index.d.ts.map +1 -0
  346. package/dist/rpg/index.js +8 -0
  347. package/dist/rpg/index.js.map +1 -0
  348. package/dist/stage/DialogueStage.d.ts +75 -0
  349. package/dist/stage/DialogueStage.d.ts.map +1 -0
  350. package/dist/stage/DialogueStage.js +207 -0
  351. package/dist/stage/DialogueStage.js.map +1 -0
  352. package/dist/stage/index.d.ts +7 -0
  353. package/dist/stage/index.d.ts.map +1 -0
  354. package/dist/stage/index.js +4 -0
  355. package/dist/stage/index.js.map +1 -0
  356. package/dist/stage/script.d.ts +111 -0
  357. package/dist/stage/script.d.ts.map +1 -0
  358. package/dist/stage/script.js +133 -0
  359. package/dist/stage/script.js.map +1 -0
  360. package/dist/stage/twee.d.ts +42 -0
  361. package/dist/stage/twee.d.ts.map +1 -0
  362. package/dist/stage/twee.js +169 -0
  363. package/dist/stage/twee.js.map +1 -0
  364. package/dist/ui/IconGrid.d.ts +110 -0
  365. package/dist/ui/IconGrid.d.ts.map +1 -0
  366. package/dist/ui/IconGrid.js +284 -0
  367. package/dist/ui/IconGrid.js.map +1 -0
  368. package/dist/ui/Label.d.ts +26 -0
  369. package/dist/ui/Label.d.ts.map +1 -0
  370. package/dist/ui/Label.js +41 -0
  371. package/dist/ui/Label.js.map +1 -0
  372. package/dist/ui/ListView.d.ts +67 -0
  373. package/dist/ui/ListView.d.ts.map +1 -0
  374. package/dist/ui/ListView.js +167 -0
  375. package/dist/ui/ListView.js.map +1 -0
  376. package/dist/ui/MessageBox.d.ts +66 -0
  377. package/dist/ui/MessageBox.d.ts.map +1 -0
  378. package/dist/ui/MessageBox.js +161 -0
  379. package/dist/ui/MessageBox.js.map +1 -0
  380. package/dist/ui/NinePatch.d.ts +34 -0
  381. package/dist/ui/NinePatch.d.ts.map +1 -0
  382. package/dist/ui/NinePatch.js +45 -0
  383. package/dist/ui/NinePatch.js.map +1 -0
  384. package/dist/ui/VerticalLabel.d.ts +46 -0
  385. package/dist/ui/VerticalLabel.d.ts.map +1 -0
  386. package/dist/ui/VerticalLabel.js +81 -0
  387. package/dist/ui/VerticalLabel.js.map +1 -0
  388. package/dist/ui/Window.d.ts +71 -0
  389. package/dist/ui/Window.d.ts.map +1 -0
  390. package/dist/ui/Window.js +126 -0
  391. package/dist/ui/Window.js.map +1 -0
  392. package/dist/ui/WindowStack.d.ts +40 -0
  393. package/dist/ui/WindowStack.d.ts.map +1 -0
  394. package/dist/ui/WindowStack.js +106 -0
  395. package/dist/ui/WindowStack.js.map +1 -0
  396. package/dist/ui/index.d.ts +18 -0
  397. package/dist/ui/index.d.ts.map +1 -0
  398. package/dist/ui/index.js +10 -0
  399. package/dist/ui/index.js.map +1 -0
  400. package/dist/ui/theme.d.ts +50 -0
  401. package/dist/ui/theme.d.ts.map +1 -0
  402. package/dist/ui/theme.js +36 -0
  403. package/dist/ui/theme.js.map +1 -0
  404. package/dist/world/Encounters.d.ts +20 -0
  405. package/dist/world/Encounters.d.ts.map +1 -0
  406. package/dist/world/Encounters.js +9 -0
  407. package/dist/world/Encounters.js.map +1 -0
  408. package/dist/world/Overworld.d.ts +25 -0
  409. package/dist/world/Overworld.d.ts.map +1 -0
  410. package/dist/world/Overworld.js +26 -0
  411. package/dist/world/Overworld.js.map +1 -0
  412. package/dist/world/TurnClock.d.ts +25 -0
  413. package/dist/world/TurnClock.d.ts.map +1 -0
  414. package/dist/world/TurnClock.js +33 -0
  415. package/dist/world/TurnClock.js.map +1 -0
  416. package/dist/world/World.d.ts +50 -0
  417. package/dist/world/World.d.ts.map +1 -0
  418. package/dist/world/World.js +77 -0
  419. package/dist/world/World.js.map +1 -0
  420. package/dist/world/index.d.ts +8 -0
  421. package/dist/world/index.d.ts.map +1 -0
  422. package/dist/world/index.js +5 -0
  423. package/dist/world/index.js.map +1 -0
  424. package/package.json +76 -0
  425. package/tools/compile-resources.mjs +129 -0
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Achievements: named milestones unlocked by counters crossing a target - monsters
3
+ * slain, gold collected, floors descended, runs won.
4
+ *
5
+ * The shape every badge/achievement list shares: a definition names a counter and the
6
+ * value that earns it, the game increments counters as things happen, and unlocking is
7
+ * derived (a counter at or past its target), never stored separately - so a counter
8
+ * can only ever move one way and an unlocked achievement can never disagree with the
9
+ * count behind it. Descriptions are display text `mwg` never reads; persistence is the
10
+ * usual definitions-fresh, progress-saved split (`QuestLog`'s own convention).
11
+ */
12
+ export class Achievements {
13
+ constructor() {
14
+ this.definitions = new Map();
15
+ this.counts = new Map();
16
+ /** every achievement id unlocked since the last `drainNew` call, oldest first */
17
+ this.fresh = [];
18
+ }
19
+ define(definition) {
20
+ this.definitions.set(definition.id, definition);
21
+ }
22
+ /** the current value of a counter; 0 for one nothing has touched yet */
23
+ count(counter) {
24
+ return this.counts.get(counter) ?? 0;
25
+ }
26
+ /**
27
+ * Adds to a counter, unlocking whatever that newly earns.
28
+ *
29
+ * @returns the ids unlocked by exactly this increment, so a game can announce each
30
+ * one once ("Achievement unlocked: ...") rather than re-scanning everything
31
+ */
32
+ increment(counter, amount = 1) {
33
+ const before = this.count(counter);
34
+ this.counts.set(counter, before + amount);
35
+ const earned = [];
36
+ for (const definition of this.definitions.values()) {
37
+ if (definition.counter !== counter)
38
+ continue;
39
+ if (before < definition.target && before + amount >= definition.target) {
40
+ earned.push(definition.id);
41
+ this.fresh.push(definition.id);
42
+ }
43
+ }
44
+ return earned;
45
+ }
46
+ /** whether an achievement's counter has reached its target - throws for an unknown id */
47
+ unlocked(id) {
48
+ const definition = this.definitions.get(id);
49
+ if (!definition)
50
+ throw new Error(`no such achievement: "${id}"`);
51
+ return this.count(definition.counter) >= definition.target;
52
+ }
53
+ /** progress towards an achievement: current count and target - throws for an unknown id */
54
+ progress(id) {
55
+ const definition = this.definitions.get(id);
56
+ if (!definition)
57
+ throw new Error(`no such achievement: "${id}"`);
58
+ return { count: this.count(definition.counter), target: definition.target };
59
+ }
60
+ /** every id unlocked but not yet announced, clearing the queue as it reads */
61
+ drainNew() {
62
+ const out = this.fresh;
63
+ this.fresh = [];
64
+ return out;
65
+ }
66
+ toJSON() {
67
+ return { counts: [...this.counts] };
68
+ }
69
+ /** rebuilds achievements from save data - definitions are supplied fresh, the same as `QuestLog` */
70
+ static fromJSON(definitions, data) {
71
+ const achievements = new Achievements();
72
+ for (const definition of definitions)
73
+ achievements.define(definition);
74
+ for (const [counter, count] of data.counts)
75
+ achievements.counts.set(counter, count);
76
+ //a loaded game announces nothing: whatever was earned was earned before the save
77
+ return achievements;
78
+ }
79
+ }
80
+ //# sourceMappingURL=Achievements.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Achievements.js","sourceRoot":"","sources":["../../src/core/Achievements.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import { type SaveStorage } from './Save.ts';
2
+ /**
3
+ * One JSON record in a `Collection`: a string id plus whatever fields the game
4
+ * keeps - quest stages, bestiary sightings, achievements.
5
+ */
6
+ export interface DbRecord {
7
+ id: string;
8
+ [field: string]: unknown;
9
+ }
10
+ export interface CollectionOptions {
11
+ /** key prefix, so two games sharing a browser never meet; defaults to the game's name */
12
+ namespace?: string;
13
+ /** defaults to `localStorage`, falling back to memory where it is unavailable */
14
+ storage?: SaveStorage;
15
+ }
16
+ /**
17
+ * A named collection of records, queried and filtered - the shape `SaveSystem`
18
+ * does not cover. A save slot is one blob loaded wholesale; a collection is many
19
+ * small records asked questions: `where((q) => !q.done)` is "everything not yet
20
+ * completed".
21
+ *
22
+ * Every call hits the storage directly - nothing is cached, so there is no copy
23
+ * to go stale, and two `Collection` objects over the same name agree trivially.
24
+ * Records come back in insertion order. Built for logs and bestiaries (hundreds
25
+ * of records), not for anything scanned per frame.
26
+ */
27
+ export declare class Collection {
28
+ private readonly prefix;
29
+ private readonly storage;
30
+ constructor(name: string, options?: CollectionOptions);
31
+ /** how many records the collection holds */
32
+ get size(): number;
33
+ /** every record, in insertion order */
34
+ all(): DbRecord[];
35
+ get(id: string): DbRecord | undefined;
36
+ /** inserts or replaces the record with the same id */
37
+ put(record: DbRecord): void;
38
+ remove(id: string): void;
39
+ /** the records a predicate keeps - "everything not yet completed" reads exactly like that */
40
+ where(predicate: (record: DbRecord) => boolean): DbRecord[];
41
+ /** empties this collection, and nothing else sharing the storage */
42
+ clear(): void;
43
+ private keys;
44
+ private read;
45
+ }
46
+ //# sourceMappingURL=Collection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Collection.d.ts","sourceRoot":"","sources":["../../src/core/Collection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7D;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IACjC,yFAAyF;IACzF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,OAAO,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,UAAU;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IAEtC,YAAY,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,EAIxD;IAED,4CAA4C;IAC5C,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,uCAAuC;IACvC,GAAG,IAAI,QAAQ,EAAE,CAEhB;IAED,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAGpC;IAED,sDAAsD;IACtD,GAAG,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAQ1B;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAEvB;IAED,6FAA6F;IAC7F,KAAK,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,QAAQ,KAAK,OAAO,GAAG,QAAQ,EAAE,CAE1D;IAED,oEAAoE;IACpE,KAAK,IAAI,IAAI,CAEZ;IAED,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,IAAI;CAGZ"}
@@ -0,0 +1,61 @@
1
+ import { defaultStorage } from './Save.js';
2
+ /**
3
+ * A named collection of records, queried and filtered - the shape `SaveSystem`
4
+ * does not cover. A save slot is one blob loaded wholesale; a collection is many
5
+ * small records asked questions: `where((q) => !q.done)` is "everything not yet
6
+ * completed".
7
+ *
8
+ * Every call hits the storage directly - nothing is cached, so there is no copy
9
+ * to go stale, and two `Collection` objects over the same name agree trivially.
10
+ * Records come back in insertion order. Built for logs and bestiaries (hundreds
11
+ * of records), not for anything scanned per frame.
12
+ */
13
+ export class Collection {
14
+ constructor(name, options = {}) {
15
+ if (!name)
16
+ throw new Error('a collection needs a name');
17
+ this.prefix = `mwg-db:${options.namespace ?? 'default'}:${name}:`;
18
+ this.storage = options.storage ?? defaultStorage();
19
+ }
20
+ /** how many records the collection holds */
21
+ get size() {
22
+ return this.keys().length;
23
+ }
24
+ /** every record, in insertion order */
25
+ all() {
26
+ return this.keys().map((key) => this.read(key));
27
+ }
28
+ get(id) {
29
+ const raw = this.storage.read(this.prefix + id);
30
+ return raw === null ? undefined : JSON.parse(raw);
31
+ }
32
+ /** inserts or replaces the record with the same id */
33
+ put(record) {
34
+ if (typeof record !== 'object' || record === null || Array.isArray(record)) {
35
+ throw new Error('a record must be an object with a string id');
36
+ }
37
+ if (typeof record.id !== 'string' || record.id === '') {
38
+ throw new Error('a record must be an object with a string id');
39
+ }
40
+ this.storage.write(this.prefix + record.id, JSON.stringify(record));
41
+ }
42
+ remove(id) {
43
+ this.storage.remove(this.prefix + id);
44
+ }
45
+ /** the records a predicate keeps - "everything not yet completed" reads exactly like that */
46
+ where(predicate) {
47
+ return this.all().filter(predicate);
48
+ }
49
+ /** empties this collection, and nothing else sharing the storage */
50
+ clear() {
51
+ for (const key of this.keys())
52
+ this.storage.remove(key);
53
+ }
54
+ keys() {
55
+ return this.storage.keys().filter((key) => key.startsWith(this.prefix));
56
+ }
57
+ read(key) {
58
+ return JSON.parse(this.storage.read(key));
59
+ }
60
+ }
61
+ //# sourceMappingURL=Collection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Collection.js","sourceRoot":"","sources":["../../src/core/Collection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAoB,MAAM,WAAW,CAAC;AAkB7D;;;;;;;;;;GAUG;AACH,MAAM,OAAO,UAAU;IAItB,YAAY,IAAY,EAAE,OAAO,GAAsB,EAAE;QACxD,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM,GAAG,UAAU,OAAO,CAAC,SAAS,IAAI,SAAS,IAAI,IAAI,GAAG,CAAC;QAClE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,cAAc,EAAE,CAAC;IACpD,CAAC;IAED,4CAA4C;IAC5C,IAAI,IAAI;QACP,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED,uCAAuC;IACvC,GAAG;QACF,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,GAAG,CAAC,EAAU;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;QAChD,OAAO,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAc,CAAC;IACjE,CAAC;IAED,sDAAsD;IACtD,GAAG,CAAC,MAAgB;QACnB,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5E,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QAChE,CAAC;QACD,IAAI,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ,IAAI,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;YACvD,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QAChE,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,CAAC,EAAU;QAChB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,6FAA6F;IAC7F,KAAK,CAAC,SAAwC;QAC7C,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC;IAED,oEAAoE;IACpE,KAAK;QACJ,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE;YAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACzD,CAAC;IAEO,IAAI;QACX,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACzE,CAAC;IAEO,IAAI,CAAC,GAAW;QACvB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAW,CAAa,CAAC;IACjE,CAAC;CACD"}
@@ -0,0 +1,115 @@
1
+ import { Application } from 'pixi.js';
2
+ import type { Scene, SceneClass } from './Scene.ts';
3
+ import { Signal } from './Signal.ts';
4
+ export interface GameOptions {
5
+ /** the canvas to draw into; one is created and appended if omitted */
6
+ canvas?: HTMLCanvasElement;
7
+ /** background colour behind everything, as 0xRRGGBB */
8
+ background?: number;
9
+ /**
10
+ * Longest frame the game will simulate, in seconds.
11
+ *
12
+ * A backgrounded tab reports an enormous delta on its first frame back, which would
13
+ * teleport everything that moves. Frames longer than this are treated as this long,
14
+ * so the game slows down rather than jumping.
15
+ */
16
+ maxDelta?: number;
17
+ /**
18
+ * Pixel art is never smoothed when scaled - both inside the game (texture sampling)
19
+ * and in the browser's own compositing of the canvas element onto the page, which is a
20
+ * separate step and blurs on its own if left at the default. Set false for a game whose
21
+ * art is not pixel art and should smooth when magnified.
22
+ */
23
+ pixelArt?: boolean;
24
+ /**
25
+ * What the renderer sizes itself to. Defaults to the window.
26
+ *
27
+ * Sizing to the canvas's parent looks tidier but circles: a canvas styled to fill its
28
+ * parent gives the parent no height of its own, so both collapse. Pass an element only
29
+ * when that element has a size the canvas does not depend on.
30
+ */
31
+ resizeTo?: HTMLElement | Window;
32
+ }
33
+ /**
34
+ * The application: owns the renderer, the loop, and the current scene.
35
+ *
36
+ * Construct it, `await start(FirstScene)`, and the rest is scenes.
37
+ */
38
+ export declare class Game {
39
+ private static instance;
40
+ readonly app: Application<import("pixi.js").Renderer>;
41
+ /** seconds elapsed in the previous frame, clamped by `maxDelta` */
42
+ elapsed: number;
43
+ /** total seconds since the current scene was created */
44
+ timeTotal: number;
45
+ /** multiplies elapsed time; 0 pauses the game without stopping the renderer */
46
+ timeScale: number;
47
+ /** fires after every frame's update, for systems that are not scene-owned */
48
+ readonly onFrame: Signal<number>;
49
+ private stack;
50
+ private pending;
51
+ private options;
52
+ private started;
53
+ constructor(options?: GameOptions);
54
+ /** the viewport width in css pixels, which is what scenes lay out against */
55
+ get width(): number;
56
+ get height(): number;
57
+ /** the running game, for the few places that genuinely need a global */
58
+ static get current(): Game;
59
+ start(first: SceneClass): Promise<void>;
60
+ /**
61
+ * Queues a scene change; it happens at the start of the next frame.
62
+ *
63
+ * The whole stack goes: every scene is destroyed, suspended or not, and the
64
+ * new one starts alone. For a scene that returns, push it instead.
65
+ */
66
+ switchScene(next: SceneClass): void;
67
+ /**
68
+ * Queues a scene on top of the current one; it starts at the next frame.
69
+ *
70
+ * The scene underneath suspends but is not destroyed: it stops updating and
71
+ * keeps rendering, so the new scene can layer over it or replace it
72
+ * outright, and `popScene` resumes exactly where play left off.
73
+ */
74
+ pushScene(next: SceneClass): void;
75
+ /**
76
+ * Queues the top scene's removal; it happens at the start of the next frame.
77
+ *
78
+ * @param result reported back to the resumed scene's `onResume`
79
+ */
80
+ popScene(result?: unknown): void;
81
+ /** the scene currently updating: the top of the stack */
82
+ get currentScene(): Scene | null;
83
+ /**
84
+ * Advances the game by one frame and draws it, without waiting for the browser.
85
+ *
86
+ * The loop normally runs on requestAnimationFrame, which browsers suspend while a tab
87
+ * is not visible. That is right for a game and wrong for a test or a screenshot, so
88
+ * this drives a frame directly.
89
+ *
90
+ * @param dt seconds to advance by
91
+ */
92
+ step(dt: number): void;
93
+ /**
94
+ * Publishes the running game on the global object, for tools and for the console.
95
+ *
96
+ * `__PIXI_APP__` is the name the PixiJS devtools extension looks for, so declaring it
97
+ * costs nothing and makes the scene graph inspectable. `__MWG__` is the game itself,
98
+ * which is what makes `__MWG__.step(1/60)` possible from a console — the only way to
99
+ * advance a game whose tab the browser has suspended, and the difference between
100
+ * diagnosing a frozen page and guessing at it.
101
+ *
102
+ * Neither is read by the framework. Nothing depends on them existing.
103
+ */
104
+ private expose;
105
+ private frame;
106
+ private switchNow;
107
+ /** a new scene alone: everything else is destroyed, the clocks restart */
108
+ private applySwitch;
109
+ /** a new scene over the current one, which suspends but survives underneath */
110
+ private applyPush;
111
+ /** the top scene leaves, reporting back to whatever it covered */
112
+ private applyPop;
113
+ destroy(): void;
114
+ }
115
+ //# sourceMappingURL=Game.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Game.d.ts","sourceRoot":"","sources":["../../src/core/Game.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAiB,MAAM,SAAS,CAAC;AACrD,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEpD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AA2BrC,MAAM,WAAW,WAAW;IAC3B,sEAAsE;IACtE,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAE3B,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;CAChC;AAED;;;;GAIG;AACH,qBAAa,IAAI;IAChB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAqB;IAE5C,QAAQ,CAAC,GAAG,0CAAqB;IAEjC,mEAAmE;IACnE,OAAO,SAAK;IAEZ,wDAAwD;IACxD,SAAS,SAAK;IAEd,+EAA+E;IAC/E,SAAS,SAAK;IAEd,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,iBAAwB;IAExC,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,OAAO,CAAS;IAExB,YAAY,OAAO,GAAE,WAAgB,EAuBpC;IAED,6EAA6E;IAC7E,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,wEAAwE;IACxE,MAAM,KAAK,OAAO,IAAI,IAAI,CAGzB;IAEK,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA+C5C;IAED;;;;;OAKG;IACH,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAElC;IAED;;;;;;OAMG;IACH,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAEhC;IAED;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAE/B;IAED,yDAAyD;IACzD,IAAI,YAAY,IAAI,KAAK,GAAG,IAAI,CAE/B;IAED;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAGrB;IAED;;;;;;;;;;OAUG;IACH,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,KAAK;IAoBb,OAAO,CAAC,SAAS;IAIjB,0EAA0E;IAC1E,OAAO,CAAC,WAAW;IAanB,+EAA+E;IAC/E,OAAO,CAAC,SAAS;IAYjB,kEAAkE;IAClE,OAAO,CAAC,QAAQ;IAMhB,OAAO,IAAI,IAAI,CAMd;CACD"}
@@ -0,0 +1,236 @@
1
+ import { Application, TextureSource } from 'pixi.js';
2
+ import { SceneStack } from './SceneStack.js';
3
+ import { Signal } from './Signal.js';
4
+ import { registerColorTransform } from '../render/TintedSprite.js';
5
+ import * as Input from './Input.js';
6
+ const PIXEL_ART_CLASS = 'mwg-pixel-art';
7
+ /**
8
+ * A class beats an inline `canvas.style.imageRendering` because Pixi's own `autoDensity`/
9
+ * `resizeTo` rewrite the canvas's `style` attribute wholesale (see `start()`); this rule
10
+ * lives in the CSSOM instead, in a stylesheet Pixi never touches, so it survives that.
11
+ * Injected once per page, however many `Game`s end up on it.
12
+ */
13
+ function ensurePixelArtStylesheet() {
14
+ if (document.getElementById(PIXEL_ART_CLASS))
15
+ return;
16
+ const style = document.createElement('style');
17
+ style.id = PIXEL_ART_CLASS;
18
+ style.textContent = `.${PIXEL_ART_CLASS} { image-rendering: pixelated; }`;
19
+ document.head.appendChild(style);
20
+ }
21
+ /**
22
+ * The application: owns the renderer, the loop, and the current scene.
23
+ *
24
+ * Construct it, `await start(FirstScene)`, and the rest is scenes.
25
+ */
26
+ export class Game {
27
+ static { this.instance = null; }
28
+ constructor(options = {}) {
29
+ this.app = new Application();
30
+ /** seconds elapsed in the previous frame, clamped by `maxDelta` */
31
+ this.elapsed = 0;
32
+ /** total seconds since the current scene was created */
33
+ this.timeTotal = 0;
34
+ /** multiplies elapsed time; 0 pauses the game without stopping the renderer */
35
+ this.timeScale = 1;
36
+ /** fires after every frame's update, for systems that are not scene-owned */
37
+ this.onFrame = new Signal();
38
+ this.stack = new SceneStack();
39
+ this.pending = [];
40
+ this.started = false;
41
+ this.options = {
42
+ canvas: options.canvas ?? document.createElement('canvas'),
43
+ background: options.background ?? 0x000000,
44
+ maxDelta: options.maxDelta ?? 0.25,
45
+ pixelArt: options.pixelArt ?? true,
46
+ resizeTo: options.resizeTo ?? window,
47
+ };
48
+ if (this.options.pixelArt) {
49
+ //set here rather than in start(), because textures are usually loaded before
50
+ //the game starts and each one takes the default that was current when it was
51
+ //created. nearest sampling is what keeps magnified pixel art crisp - but only
52
+ //inside the game's own rendering; the browser then does a second, entirely
53
+ //separate resize when it composites the canvas element onto the page (its
54
+ //backing buffer is rarely the same size as its CSS display size, especially at
55
+ //a devicePixelRatio other than 1), and that step defaults to smooth
56
+ //interpolation regardless of anything Pixi does - see `start()` for the other
57
+ //half of this, since `app.init()` overwrites whatever style is set here.
58
+ TextureSource.defaultOptions.scaleMode = 'nearest';
59
+ }
60
+ Game.instance = this;
61
+ }
62
+ /** the viewport width in css pixels, which is what scenes lay out against */
63
+ get width() {
64
+ return this.app.renderer.screen.width;
65
+ }
66
+ get height() {
67
+ return this.app.renderer.screen.height;
68
+ }
69
+ /** the running game, for the few places that genuinely need a global */
70
+ static get current() {
71
+ if (!Game.instance)
72
+ throw new Error('no Game has been created yet');
73
+ return Game.instance;
74
+ }
75
+ async start(first) {
76
+ if (this.started)
77
+ throw new Error('this Game has already been started');
78
+ this.started = true;
79
+ //batchers and pipes have to be registered before the renderer is built, so that
80
+ //TintedSprite has somewhere to render to
81
+ registerColorTransform();
82
+ Input.attach();
83
+ await this.app.init({
84
+ canvas: this.options.canvas,
85
+ background: this.options.background,
86
+ resizeTo: this.options.resizeTo,
87
+ antialias: false,
88
+ //the game clears and redraws every frame, so the buffer need not be preserved
89
+ preserveDrawingBuffer: false,
90
+ //drawing at device resolution is what keeps pixel art on whole device pixels
91
+ resolution: window.devicePixelRatio || 1,
92
+ autoDensity: true,
93
+ });
94
+ if (!this.options.canvas.isConnected) {
95
+ document.body.appendChild(this.options.canvas);
96
+ }
97
+ //`autoDensity` (and `resizeTo`, on its own asynchronous schedule) rewrite the canvas
98
+ //element's `style` attribute wholesale to keep its CSS size matching the backing
99
+ //buffer - which loses anything else set through `canvas.style`, including right
100
+ //after `init` and again from inside pixi's own 'resize' event. A class, rather than
101
+ //an inline style, lives in a different attribute entirely and survives that.
102
+ if (this.options.pixelArt) {
103
+ ensurePixelArtStylesheet();
104
+ this.options.canvas.classList.add(PIXEL_ART_CLASS);
105
+ }
106
+ //`screen` is the logical size in css pixels; `renderer.width` is the backing store,
107
+ //which is larger on a hidpi display. Scenes lay out in logical units, so handing
108
+ //them the backing size would push everything they centre off the screen.
109
+ this.app.renderer.on('resize', () => {
110
+ this.stack.resize(this.width, this.height);
111
+ });
112
+ this.expose();
113
+ this.switchNow(first);
114
+ //pixi's ticker drives the loop, so its own systems stay in step with the game
115
+ this.app.ticker.add((ticker) => this.frame(ticker.deltaMS / 1000));
116
+ }
117
+ /**
118
+ * Queues a scene change; it happens at the start of the next frame.
119
+ *
120
+ * The whole stack goes: every scene is destroyed, suspended or not, and the
121
+ * new one starts alone. For a scene that returns, push it instead.
122
+ */
123
+ switchScene(next) {
124
+ this.pending.push({ kind: 'switch', next });
125
+ }
126
+ /**
127
+ * Queues a scene on top of the current one; it starts at the next frame.
128
+ *
129
+ * The scene underneath suspends but is not destroyed: it stops updating and
130
+ * keeps rendering, so the new scene can layer over it or replace it
131
+ * outright, and `popScene` resumes exactly where play left off.
132
+ */
133
+ pushScene(next) {
134
+ this.pending.push({ kind: 'push', next });
135
+ }
136
+ /**
137
+ * Queues the top scene's removal; it happens at the start of the next frame.
138
+ *
139
+ * @param result reported back to the resumed scene's `onResume`
140
+ */
141
+ popScene(result) {
142
+ this.pending.push({ kind: 'pop', result });
143
+ }
144
+ /** the scene currently updating: the top of the stack */
145
+ get currentScene() {
146
+ return this.stack.current;
147
+ }
148
+ /**
149
+ * Advances the game by one frame and draws it, without waiting for the browser.
150
+ *
151
+ * The loop normally runs on requestAnimationFrame, which browsers suspend while a tab
152
+ * is not visible. That is right for a game and wrong for a test or a screenshot, so
153
+ * this drives a frame directly.
154
+ *
155
+ * @param dt seconds to advance by
156
+ */
157
+ step(dt) {
158
+ this.frame(dt);
159
+ this.app.renderer.render(this.app.stage);
160
+ }
161
+ /**
162
+ * Publishes the running game on the global object, for tools and for the console.
163
+ *
164
+ * `__PIXI_APP__` is the name the PixiJS devtools extension looks for, so declaring it
165
+ * costs nothing and makes the scene graph inspectable. `__MWG__` is the game itself,
166
+ * which is what makes `__MWG__.step(1/60)` possible from a console — the only way to
167
+ * advance a game whose tab the browser has suspended, and the difference between
168
+ * diagnosing a frozen page and guessing at it.
169
+ *
170
+ * Neither is read by the framework. Nothing depends on them existing.
171
+ */
172
+ expose() {
173
+ const target = globalThis;
174
+ target.__PIXI_APP__ = this.app;
175
+ target.__MWG__ = this;
176
+ }
177
+ frame(deltaSeconds) {
178
+ //queued scene changes run first, in order, so a frame never updates a
179
+ //scene that was already asked to leave
180
+ for (const request of this.pending) {
181
+ if (request.kind === 'switch')
182
+ this.applySwitch(request.next);
183
+ else if (request.kind === 'push')
184
+ this.applyPush(request.next);
185
+ else
186
+ this.applyPop(request.result);
187
+ }
188
+ this.pending.length = 0;
189
+ this.elapsed = Math.min(deltaSeconds, this.options.maxDelta) * this.timeScale;
190
+ this.timeTotal += this.elapsed;
191
+ this.stack.update(this.elapsed);
192
+ this.onFrame.dispatch(this.elapsed);
193
+ //after everything has had a chance to poll it, so nothing misses a press
194
+ Input.endFrame();
195
+ }
196
+ switchNow(next) {
197
+ this.applySwitch(next);
198
+ }
199
+ /** a new scene alone: everything else is destroyed, the clocks restart */
200
+ applySwitch(next) {
201
+ const scene = new next();
202
+ this.stack.replace(scene);
203
+ this.app.stage.removeChildren();
204
+ this.app.stage.addChild(scene.stage);
205
+ this.elapsed = 0;
206
+ this.timeTotal = 0;
207
+ this.timeScale = 1;
208
+ scene.resize(this.width, this.height);
209
+ }
210
+ /** a new scene over the current one, which suspends but survives underneath */
211
+ applyPush(next) {
212
+ const scene = new next();
213
+ this.stack.push(scene);
214
+ this.app.stage.addChild(scene.stage);
215
+ this.elapsed = 0;
216
+ this.timeTotal = 0;
217
+ this.timeScale = 1;
218
+ scene.resize(this.width, this.height);
219
+ }
220
+ /** the top scene leaves, reporting back to whatever it covered */
221
+ applyPop(result) {
222
+ const top = this.stack.current;
223
+ this.stack.pop(result);
224
+ if (top)
225
+ this.app.stage.removeChild(top.stage);
226
+ }
227
+ destroy() {
228
+ Input.detach();
229
+ this.stack.destroy();
230
+ this.onFrame.removeAll();
231
+ this.app.destroy(true, { children: true });
232
+ if (Game.instance === this)
233
+ Game.instance = null;
234
+ }
235
+ }
236
+ //# sourceMappingURL=Game.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Game.js","sourceRoot":"","sources":["../../src/core/Game.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAErD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AAEpC,MAAM,eAAe,GAAG,eAAe,CAAC;AAQxC;;;;;GAKG;AACH,SAAS,wBAAwB;IAChC,IAAI,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC;QAAE,OAAO;IAErD,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAC9C,KAAK,CAAC,EAAE,GAAG,eAAe,CAAC;IAC3B,KAAK,CAAC,WAAW,GAAG,IAAI,eAAe,kCAAkC,CAAC;IAC1E,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC;AAoCD;;;;GAIG;AACH,MAAM,OAAO,IAAI;aACD,aAAQ,GAAgB,IAAI,AAApB,CAAqB;IAqB5C,YAAY,OAAO,GAAgB,EAAE;QAnB5B,QAAG,GAAG,IAAI,WAAW,EAAE,CAAC;QAEjC,mEAAmE;QACnE,YAAO,GAAG,CAAC,CAAC;QAEZ,wDAAwD;QACxD,cAAS,GAAG,CAAC,CAAC;QAEd,+EAA+E;QAC/E,cAAS,GAAG,CAAC,CAAC;QAEd,6EAA6E;QACpE,YAAO,GAAG,IAAI,MAAM,EAAU,CAAC;QAEhC,UAAK,GAAG,IAAI,UAAU,EAAE,CAAC;QACzB,YAAO,GAAmB,EAAE,CAAC;QAE7B,YAAO,GAAG,KAAK,CAAC;QAGvB,IAAI,CAAC,OAAO,GAAG;YACd,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC;YAC1D,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,QAAQ;YAC1C,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,IAAI;YAClC,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,IAAI;YAClC,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,MAAM;SACpC,CAAC;QAEF,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC3B,6EAA6E;YAC7E,6EAA6E;YAC7E,8EAA8E;YAC9E,2EAA2E;YAC3E,0EAA0E;YAC1E,+EAA+E;YAC/E,oEAAoE;YACpE,8EAA8E;YAC9E,yEAAyE;YACzE,aAAa,CAAC,cAAc,CAAC,SAAS,GAAG,SAAS,CAAC;QACpD,CAAC;QAED,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;IACtB,CAAC;IAED,6EAA6E;IAC7E,IAAI,KAAK;QACR,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC;IACvC,CAAC;IAED,IAAI,MAAM;QACT,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;IACxC,CAAC;IAED,wEAAwE;IACxE,MAAM,KAAK,OAAO;QACjB,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QACpE,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,KAAiB;QAC5B,IAAI,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACxE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QAEpB,gFAAgF;QAChF,yCAAyC;QACzC,sBAAsB,EAAE,CAAC;QACzB,KAAK,CAAC,MAAM,EAAE,CAAC;QAEf,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YACnB,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;YAC3B,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU;YACnC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ;YAC/B,SAAS,EAAE,KAAK;YAChB,8EAA8E;YAC9E,qBAAqB,EAAE,KAAK;YAC5B,6EAA6E;YAC7E,UAAU,EAAE,MAAM,CAAC,gBAAgB,IAAI,CAAC;YACxC,WAAW,EAAE,IAAI;SACjB,CAAC,CAAC;QAEH,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YACtC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAChD,CAAC;QAED,qFAAqF;QACrF,iFAAiF;QACjF,gFAAgF;QAChF,oFAAoF;QACpF,6EAA6E;QAC7E,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC3B,wBAAwB,EAAE,CAAC;YAC3B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QACpD,CAAC;QAED,oFAAoF;QACpF,iFAAiF;QACjF,yEAAyE;QACzE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;YACnC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAEtB,8EAA8E;QAC9E,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC;IACpE,CAAC;IAED;;;;;OAKG;IACH,WAAW,CAAC,IAAgB;QAC3B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED;;;;;;OAMG;IACH,SAAS,CAAC,IAAgB;QACzB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED;;;;OAIG;IACH,QAAQ,CAAC,MAAgB;QACxB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED,yDAAyD;IACzD,IAAI,YAAY;QACf,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;IAC3B,CAAC;IAED;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAU;QACd,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACf,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC;IAED;;;;;;;;;;OAUG;IACK,MAAM;QACb,MAAM,MAAM,GAAG,UAAgD,CAAC;QAChE,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC;QAC/B,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;IACvB,CAAC;IAEO,KAAK,CAAC,YAAoB;QACjC,sEAAsE;QACtE,uCAAuC;QACvC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACpC,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ;gBAAE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;iBACzD,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM;gBAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;;gBAC1D,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;QAExB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC;QAC9E,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC;QAE/B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAChC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEpC,yEAAyE;QACzE,KAAK,CAAC,QAAQ,EAAE,CAAC;IAClB,CAAC;IAEO,SAAS,CAAC,IAAgB;QACjC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,0EAA0E;IAClE,WAAW,CAAC,IAAgB;QACnC,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;QACzB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;QAChC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAErC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QACjB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QAEnB,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAED,+EAA+E;IACvE,SAAS,CAAC,IAAgB;QACjC,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;QACzB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAErC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QACjB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QAEnB,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAED,kEAAkE;IAC1D,QAAQ,CAAC,MAAe;QAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACvB,IAAI,GAAG;YAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC;IAED,OAAO;QACN,KAAK,CAAC,MAAM,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACrB,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3C,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI;YAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;IAClD,CAAC;CACD"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Flat-top hexagon geometry, addressed the same way a square grid is: `x` the column, `y`
3
+ * the row, both integers - which is what lets `mwg/roguelike`'s `Level` (grid logic) and
4
+ * `mwg/render`'s `TileMap` (pixel positions) each reuse it without depending on the other.
5
+ * It lives in `mwg/core` for exactly that reason: neither of those two modules is allowed
6
+ * to depend on the other, and this needs to sit below both.
7
+ *
8
+ * Internally this converts to and from cube coordinates (`x + y + z = 0`) for every
9
+ * calculation, because the six neighbour directions are then a fixed, orientation-agnostic
10
+ * list rather than a column-parity-dependent table someone has to get right twice. The
11
+ * offset "odd-q" scheme below - odd columns pushed half a row down - is what makes that
12
+ * cube math round-trip back to integers; nothing about it is rot.js's, which is deliberate
13
+ * (see the roadmap: rot.js's own hex `Path` topology is doubled-width coordinates built for
14
+ * *pointy-top* hexagons, and does not match this orientation).
15
+ */
16
+ export interface HexCoord {
17
+ x: number;
18
+ y: number;
19
+ }
20
+ /** the six cells sharing an edge with `(x, y)` */
21
+ export declare function hexNeighbors(x: number, y: number): HexCoord[];
22
+ /** the number of hex steps between two cells */
23
+ export declare function hexDistance(a: HexCoord, b: HexCoord): number;
24
+ /**
25
+ * Every cell a straight line crosses from `a` to `b`, both included - the hex-grid analogue
26
+ * of `mwg/roguelike`'s `traceLine`, and what a simple (non-shadowcast) hex field of view is
27
+ * built from: walk the line to a candidate cell and see whether anything on it is opaque.
28
+ */
29
+ export declare function hexLine(a: HexCoord, b: HexCoord): HexCoord[];
30
+ /** every cell within `radius` hex steps of `center`, `center` itself included */
31
+ export declare function hexRange(center: HexCoord, radius: number): HexCoord[];
32
+ /** the pixel position of a hex cell's centre, for a flat-top tile of the given size */
33
+ export declare function hexToPixel(x: number, y: number, tileWidth: number, tileHeight: number): {
34
+ x: number;
35
+ y: number;
36
+ };
37
+ /**
38
+ * The hex cell under a pixel position - the inverse of `hexToPixel`.
39
+ *
40
+ * Fractional cube coordinates first, rounded only at the end (`cubeRound`), the same way
41
+ * `hexLine` resolves a fractional step to a cell - rounding column and row independently
42
+ * would round to the wrong cell right at a hex's edge.
43
+ */
44
+ export declare function pixelToHex(px: number, py: number, tileWidth: number, tileHeight: number): HexCoord;
45
+ //# sourceMappingURL=Hex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Hex.d.ts","sourceRoot":"","sources":["../../src/core/Hex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,QAAQ;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACV;AA+BD,kDAAkD;AAClD,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,QAAQ,EAAE,CAG7D;AAED,gDAAgD;AAChD,wBAAgB,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAI5D;AAoBD;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,GAAG,QAAQ,EAAE,CAsB5D;AAED,iFAAiF;AACjF,wBAAgB,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,EAAE,CAYrE;AAED,uFAAuF;AACvF,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAKhH;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,QAAQ,CASlG"}