@datamoc/mw_games 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (317) hide show
  1. package/README.md +42 -17
  2. package/dist/actors/Aura.d.ts +29 -0
  3. package/dist/actors/Aura.d.ts.map +1 -0
  4. package/dist/actors/Aura.js +69 -0
  5. package/dist/actors/Aura.js.map +1 -0
  6. package/dist/actors/ItemStatusEffect.d.ts +27 -0
  7. package/dist/actors/ItemStatusEffect.d.ts.map +1 -0
  8. package/dist/actors/ItemStatusEffect.js +35 -0
  9. package/dist/actors/ItemStatusEffect.js.map +1 -0
  10. package/dist/actors/Support.d.ts +32 -0
  11. package/dist/actors/Support.d.ts.map +1 -0
  12. package/dist/actors/Support.js +60 -0
  13. package/dist/actors/Support.js.map +1 -0
  14. package/dist/actors/Traits.d.ts +29 -0
  15. package/dist/actors/Traits.d.ts.map +1 -0
  16. package/dist/actors/Traits.js +21 -0
  17. package/dist/actors/Traits.js.map +1 -0
  18. package/dist/actors/index.d.ts +8 -0
  19. package/dist/actors/index.d.ts.map +1 -1
  20. package/dist/actors/index.js +4 -0
  21. package/dist/actors/index.js.map +1 -1
  22. package/dist/assets/Streaming.d.ts +40 -0
  23. package/dist/assets/Streaming.d.ts.map +1 -0
  24. package/dist/assets/Streaming.js +79 -0
  25. package/dist/assets/Streaming.js.map +1 -0
  26. package/dist/assets/index.d.ts +13 -0
  27. package/dist/assets/index.d.ts.map +1 -1
  28. package/dist/assets/index.js +19 -0
  29. package/dist/assets/index.js.map +1 -1
  30. package/dist/audio/Captions.d.ts +15 -0
  31. package/dist/audio/Captions.d.ts.map +1 -0
  32. package/dist/audio/Captions.js +4 -0
  33. package/dist/audio/Captions.js.map +1 -0
  34. package/dist/audio/Midi.d.ts +75 -0
  35. package/dist/audio/Midi.d.ts.map +1 -0
  36. package/dist/audio/Midi.js +186 -0
  37. package/dist/audio/Midi.js.map +1 -0
  38. package/dist/audio/Orchestrator.d.ts +40 -0
  39. package/dist/audio/Orchestrator.d.ts.map +1 -0
  40. package/dist/audio/Orchestrator.js +48 -0
  41. package/dist/audio/Orchestrator.js.map +1 -0
  42. package/dist/audio/Sound.d.ts +3 -0
  43. package/dist/audio/Sound.d.ts.map +1 -1
  44. package/dist/audio/Sound.js +4 -0
  45. package/dist/audio/Sound.js.map +1 -1
  46. package/dist/audio/Synth.d.ts +35 -0
  47. package/dist/audio/Synth.d.ts.map +1 -0
  48. package/dist/audio/Synth.js +96 -0
  49. package/dist/audio/Synth.js.map +1 -0
  50. package/dist/audio/index.d.ts +8 -0
  51. package/dist/audio/index.d.ts.map +1 -1
  52. package/dist/audio/index.js +4 -0
  53. package/dist/audio/index.js.map +1 -1
  54. package/dist/board/Army.d.ts +17 -0
  55. package/dist/board/Army.d.ts.map +1 -0
  56. package/dist/board/Army.js +48 -0
  57. package/dist/board/Army.js.map +1 -0
  58. package/dist/board/FogOfWar.d.ts +23 -0
  59. package/dist/board/FogOfWar.d.ts.map +1 -0
  60. package/dist/board/FogOfWar.js +40 -0
  61. package/dist/board/FogOfWar.js.map +1 -0
  62. package/dist/board/Tactics.d.ts +2 -0
  63. package/dist/board/Tactics.d.ts.map +1 -1
  64. package/dist/board/Tactics.js +29 -7
  65. package/dist/board/Tactics.js.map +1 -1
  66. package/dist/board/index.d.ts +5 -1
  67. package/dist/board/index.d.ts.map +1 -1
  68. package/dist/board/index.js +3 -1
  69. package/dist/board/index.js.map +1 -1
  70. package/dist/core/Feedback.d.ts +23 -0
  71. package/dist/core/Feedback.d.ts.map +1 -0
  72. package/dist/core/Feedback.js +35 -0
  73. package/dist/core/Feedback.js.map +1 -0
  74. package/dist/core/Game.d.ts +11 -0
  75. package/dist/core/Game.d.ts.map +1 -1
  76. package/dist/core/Game.js +54 -0
  77. package/dist/core/Game.js.map +1 -1
  78. package/dist/core/Input.d.ts +58 -0
  79. package/dist/core/Input.d.ts.map +1 -1
  80. package/dist/core/Input.js +135 -0
  81. package/dist/core/Input.js.map +1 -1
  82. package/dist/core/Loading.d.ts +48 -0
  83. package/dist/core/Loading.d.ts.map +1 -0
  84. package/dist/core/Loading.js +102 -0
  85. package/dist/core/Loading.js.map +1 -0
  86. package/dist/core/News.d.ts +46 -0
  87. package/dist/core/News.d.ts.map +1 -0
  88. package/dist/core/News.js +79 -0
  89. package/dist/core/News.js.map +1 -0
  90. package/dist/core/PlayerInput.d.ts +38 -0
  91. package/dist/core/PlayerInput.d.ts.map +1 -0
  92. package/dist/core/PlayerInput.js +57 -0
  93. package/dist/core/PlayerInput.js.map +1 -0
  94. package/dist/core/RunHistory.d.ts +43 -0
  95. package/dist/core/RunHistory.d.ts.map +1 -0
  96. package/dist/core/RunHistory.js +41 -0
  97. package/dist/core/RunHistory.js.map +1 -0
  98. package/dist/core/Sanitize.d.ts +56 -0
  99. package/dist/core/Sanitize.d.ts.map +1 -0
  100. package/dist/core/Sanitize.js +87 -0
  101. package/dist/core/Sanitize.js.map +1 -0
  102. package/dist/core/Save.d.ts +31 -7
  103. package/dist/core/Save.d.ts.map +1 -1
  104. package/dist/core/Save.js +56 -0
  105. package/dist/core/Save.js.map +1 -1
  106. package/dist/core/SaveSync.d.ts +26 -0
  107. package/dist/core/SaveSync.d.ts.map +1 -0
  108. package/dist/core/SaveSync.js +52 -0
  109. package/dist/core/SaveSync.js.map +1 -0
  110. package/dist/core/Scramble.d.ts +13 -0
  111. package/dist/core/Scramble.d.ts.map +1 -0
  112. package/dist/core/Scramble.js +44 -0
  113. package/dist/core/Scramble.js.map +1 -0
  114. package/dist/core/Spawner.d.ts +48 -0
  115. package/dist/core/Spawner.d.ts.map +1 -0
  116. package/dist/core/Spawner.js +65 -0
  117. package/dist/core/Spawner.js.map +1 -0
  118. package/dist/core/Tween.d.ts +25 -0
  119. package/dist/core/Tween.d.ts.map +1 -0
  120. package/dist/core/Tween.js +60 -0
  121. package/dist/core/Tween.js.map +1 -0
  122. package/dist/core/UndoHistory.d.ts +37 -0
  123. package/dist/core/UndoHistory.d.ts.map +1 -0
  124. package/dist/core/UndoHistory.js +49 -0
  125. package/dist/core/UndoHistory.js.map +1 -0
  126. package/dist/core/index.d.ts +20 -0
  127. package/dist/core/index.d.ts.map +1 -1
  128. package/dist/core/index.js +11 -0
  129. package/dist/core/index.js.map +1 -1
  130. package/dist/i18n/Fluent.d.ts +7 -0
  131. package/dist/i18n/Fluent.d.ts.map +1 -0
  132. package/dist/i18n/Fluent.js +86 -0
  133. package/dist/i18n/Fluent.js.map +1 -0
  134. package/dist/i18n/index.d.ts +15 -1
  135. package/dist/i18n/index.d.ts.map +1 -1
  136. package/dist/i18n/index.js +17 -2
  137. package/dist/i18n/index.js.map +1 -1
  138. package/dist/index.d.ts +1 -0
  139. package/dist/index.d.ts.map +1 -1
  140. package/dist/index.js +1 -0
  141. package/dist/index.js.map +1 -1
  142. package/dist/mw_games.global.js +351 -79
  143. package/dist/render/Camera.d.ts +29 -2
  144. package/dist/render/Camera.d.ts.map +1 -1
  145. package/dist/render/Camera.js +40 -11
  146. package/dist/render/Camera.js.map +1 -1
  147. package/dist/render/Capabilities.d.ts +51 -0
  148. package/dist/render/Capabilities.d.ts.map +1 -0
  149. package/dist/render/Capabilities.js +56 -0
  150. package/dist/render/Capabilities.js.map +1 -0
  151. package/dist/render/ColorBlindness.d.ts +16 -0
  152. package/dist/render/ColorBlindness.d.ts.map +1 -0
  153. package/dist/render/ColorBlindness.js +41 -0
  154. package/dist/render/ColorBlindness.js.map +1 -0
  155. package/dist/render/Minimap.d.ts +52 -0
  156. package/dist/render/Minimap.d.ts.map +1 -0
  157. package/dist/render/Minimap.js +95 -0
  158. package/dist/render/Minimap.js.map +1 -0
  159. package/dist/render/Viewport.d.ts +46 -0
  160. package/dist/render/Viewport.d.ts.map +1 -0
  161. package/dist/render/Viewport.js +52 -0
  162. package/dist/render/Viewport.js.map +1 -0
  163. package/dist/render/index.d.ts +9 -1
  164. package/dist/render/index.d.ts.map +1 -1
  165. package/dist/render/index.js +5 -1
  166. package/dist/render/index.js.map +1 -1
  167. package/dist/roguelike/Stealth.d.ts +34 -0
  168. package/dist/roguelike/Stealth.d.ts.map +1 -0
  169. package/dist/roguelike/Stealth.js +35 -0
  170. package/dist/roguelike/Stealth.js.map +1 -0
  171. package/dist/roguelike/index.d.ts +2 -0
  172. package/dist/roguelike/index.d.ts.map +1 -1
  173. package/dist/roguelike/index.js +1 -0
  174. package/dist/roguelike/index.js.map +1 -1
  175. package/dist/rpg/Collision.d.ts +42 -0
  176. package/dist/rpg/Collision.d.ts.map +1 -0
  177. package/dist/rpg/Collision.js +77 -0
  178. package/dist/rpg/Collision.js.map +1 -0
  179. package/dist/rpg/FreeMover.d.ts +45 -0
  180. package/dist/rpg/FreeMover.d.ts.map +1 -0
  181. package/dist/rpg/FreeMover.js +68 -0
  182. package/dist/rpg/FreeMover.js.map +1 -0
  183. package/dist/rpg/Marshal.d.ts +65 -0
  184. package/dist/rpg/Marshal.d.ts.map +1 -0
  185. package/dist/rpg/Marshal.js +393 -0
  186. package/dist/rpg/Marshal.js.map +1 -0
  187. package/dist/rpg/Quest.d.ts +41 -0
  188. package/dist/rpg/Quest.d.ts.map +1 -1
  189. package/dist/rpg/Quest.js +39 -6
  190. package/dist/rpg/Quest.js.map +1 -1
  191. package/dist/rpg/index.d.ts +7 -1
  192. package/dist/rpg/index.d.ts.map +1 -1
  193. package/dist/rpg/index.js +3 -0
  194. package/dist/rpg/index.js.map +1 -1
  195. package/dist/stage/DialogueStage.d.ts +1 -2
  196. package/dist/stage/DialogueStage.d.ts.map +1 -1
  197. package/dist/stage/DialogueStage.js +7 -22
  198. package/dist/stage/DialogueStage.js.map +1 -1
  199. package/dist/stage/index.d.ts +1 -1
  200. package/dist/stage/index.d.ts.map +1 -1
  201. package/dist/stage/script.d.ts +29 -0
  202. package/dist/stage/script.d.ts.map +1 -1
  203. package/dist/stage/script.js +0 -0
  204. package/dist/stage/script.js.map +1 -1
  205. package/dist/three-d/Character3D.d.ts +48 -0
  206. package/dist/three-d/Character3D.d.ts.map +1 -0
  207. package/dist/three-d/Character3D.js +96 -0
  208. package/dist/three-d/Character3D.js.map +1 -0
  209. package/dist/three-d/Engine3D.d.ts +23 -0
  210. package/dist/three-d/Engine3D.d.ts.map +1 -0
  211. package/dist/three-d/Engine3D.js +45 -0
  212. package/dist/three-d/Engine3D.js.map +1 -0
  213. package/dist/three-d/Grid.d.ts +14 -0
  214. package/dist/three-d/Grid.d.ts.map +1 -0
  215. package/dist/three-d/Grid.js +13 -0
  216. package/dist/three-d/Grid.js.map +1 -0
  217. package/dist/three-d/Heightmap.d.ts +35 -0
  218. package/dist/three-d/Heightmap.d.ts.map +1 -0
  219. package/dist/three-d/Heightmap.js +29 -0
  220. package/dist/three-d/Heightmap.js.map +1 -0
  221. package/dist/three-d/Models.d.ts +12 -0
  222. package/dist/three-d/Models.d.ts.map +1 -0
  223. package/dist/three-d/Models.js +14 -0
  224. package/dist/three-d/Models.js.map +1 -0
  225. package/dist/three-d/TileGrid3D.d.ts +21 -0
  226. package/dist/three-d/TileGrid3D.d.ts.map +1 -0
  227. package/dist/three-d/TileGrid3D.js +65 -0
  228. package/dist/three-d/TileGrid3D.js.map +1 -0
  229. package/dist/three-d/Vox.d.ts +24 -0
  230. package/dist/three-d/Vox.d.ts.map +1 -0
  231. package/dist/three-d/Vox.js +93 -0
  232. package/dist/three-d/Vox.js.map +1 -0
  233. package/dist/three-d/index.d.ts +13 -0
  234. package/dist/three-d/index.d.ts.map +1 -0
  235. package/dist/three-d/index.js +7 -0
  236. package/dist/three-d/index.js.map +1 -0
  237. package/dist/ui/Bar.d.ts +49 -0
  238. package/dist/ui/Bar.d.ts.map +1 -0
  239. package/dist/ui/Bar.js +70 -0
  240. package/dist/ui/Bar.js.map +1 -0
  241. package/dist/ui/BitmapLabel.d.ts +42 -0
  242. package/dist/ui/BitmapLabel.d.ts.map +1 -0
  243. package/dist/ui/BitmapLabel.js +59 -0
  244. package/dist/ui/BitmapLabel.js.map +1 -0
  245. package/dist/ui/Button.d.ts +52 -0
  246. package/dist/ui/Button.d.ts.map +1 -0
  247. package/dist/ui/Button.js +147 -0
  248. package/dist/ui/Button.js.map +1 -0
  249. package/dist/ui/FloatingText.d.ts +28 -0
  250. package/dist/ui/FloatingText.d.ts.map +1 -0
  251. package/dist/ui/FloatingText.js +39 -0
  252. package/dist/ui/FloatingText.js.map +1 -0
  253. package/dist/ui/HelpScreen.d.ts +29 -0
  254. package/dist/ui/HelpScreen.d.ts.map +1 -0
  255. package/dist/ui/HelpScreen.js +39 -0
  256. package/dist/ui/HelpScreen.js.map +1 -0
  257. package/dist/ui/IconGrid.d.ts +8 -0
  258. package/dist/ui/IconGrid.d.ts.map +1 -1
  259. package/dist/ui/IconGrid.js +27 -1
  260. package/dist/ui/IconGrid.js.map +1 -1
  261. package/dist/ui/Label.d.ts +9 -0
  262. package/dist/ui/Label.d.ts.map +1 -1
  263. package/dist/ui/Label.js +24 -1
  264. package/dist/ui/Label.js.map +1 -1
  265. package/dist/ui/ListView.d.ts +11 -0
  266. package/dist/ui/ListView.d.ts.map +1 -1
  267. package/dist/ui/ListView.js +55 -1
  268. package/dist/ui/ListView.js.map +1 -1
  269. package/dist/ui/LoadingScreen.d.ts +31 -0
  270. package/dist/ui/LoadingScreen.d.ts.map +1 -0
  271. package/dist/ui/LoadingScreen.js +60 -0
  272. package/dist/ui/LoadingScreen.js.map +1 -0
  273. package/dist/ui/MessageBox.d.ts +26 -0
  274. package/dist/ui/MessageBox.d.ts.map +1 -1
  275. package/dist/ui/MessageBox.js +62 -13
  276. package/dist/ui/MessageBox.js.map +1 -1
  277. package/dist/ui/RebindScreen.d.ts +55 -0
  278. package/dist/ui/RebindScreen.d.ts.map +1 -0
  279. package/dist/ui/RebindScreen.js +114 -0
  280. package/dist/ui/RebindScreen.js.map +1 -0
  281. package/dist/ui/Toast.d.ts +44 -0
  282. package/dist/ui/Toast.d.ts.map +1 -0
  283. package/dist/ui/Toast.js +89 -0
  284. package/dist/ui/Toast.js.map +1 -0
  285. package/dist/ui/VerticalLabel.d.ts +5 -0
  286. package/dist/ui/VerticalLabel.d.ts.map +1 -1
  287. package/dist/ui/VerticalLabel.js +18 -7
  288. package/dist/ui/VerticalLabel.js.map +1 -1
  289. package/dist/ui/Window.d.ts +6 -0
  290. package/dist/ui/Window.d.ts.map +1 -1
  291. package/dist/ui/Window.js +16 -1
  292. package/dist/ui/Window.js.map +1 -1
  293. package/dist/ui/WindowStack.d.ts +1 -0
  294. package/dist/ui/WindowStack.d.ts.map +1 -1
  295. package/dist/ui/WindowStack.js +4 -1
  296. package/dist/ui/WindowStack.js.map +1 -1
  297. package/dist/ui/index.d.ts +17 -1
  298. package/dist/ui/index.d.ts.map +1 -1
  299. package/dist/ui/index.js +9 -1
  300. package/dist/ui/index.js.map +1 -1
  301. package/dist/ui/theme.d.ts +21 -0
  302. package/dist/ui/theme.d.ts.map +1 -1
  303. package/dist/ui/theme.js +42 -0
  304. package/dist/ui/theme.js.map +1 -1
  305. package/dist/version.d.ts +13 -0
  306. package/dist/version.d.ts.map +1 -0
  307. package/dist/version.js +13 -0
  308. package/dist/version.js.map +1 -0
  309. package/dist/world/Environment.d.ts +35 -0
  310. package/dist/world/Environment.d.ts.map +1 -0
  311. package/dist/world/Environment.js +55 -0
  312. package/dist/world/Environment.js.map +1 -0
  313. package/dist/world/index.d.ts +2 -0
  314. package/dist/world/index.d.ts.map +1 -1
  315. package/dist/world/index.js +1 -0
  316. package/dist/world/index.js.map +1 -1
  317. package/package.json +40 -4
@@ -19,6 +19,19 @@ export interface CameraOptions {
19
19
  * grid-based game where movement is in whole tiles.
20
20
  */
21
21
  deadzone?: number;
22
+ /**
23
+ * When set, `zoom` snaps to the nearest value at which one world unit of this size lands
24
+ * on a whole number of screen pixels - a tile's own width or height, typically.
25
+ *
26
+ * `apply()` already rounds the whole camera's screen offset to a whole pixel, which stops
27
+ * pixel art shimmering as the camera moves, but at a fractional zoom each tile's *own*
28
+ * edge still lands on a different sub-pixel offset depending on its position, so
29
+ * nearest-neighbour sampling rounds one tile's edge column one way and its neighbour's
30
+ * the other - a thin seam between tiles that camera-level rounding alone cannot fix.
31
+ * Snapping zoom itself so tile-size × zoom is always a whole number closes the gap at
32
+ * its source, without a per-tile sampling flag.
33
+ */
34
+ pixelPerfectTileSize?: number;
22
35
  }
23
36
  export declare class Camera {
24
37
  /** put the map and everything in it here */
@@ -28,8 +41,11 @@ export declare class Camera {
28
41
  y: number;
29
42
  private _zoom;
30
43
  private deadzone;
44
+ private readonly pixelPerfectTileSize?;
31
45
  private viewWidth;
32
46
  private viewHeight;
47
+ private screenX;
48
+ private screenY;
33
49
  private followTarget;
34
50
  private followIntensity;
35
51
  private shakeMagnitude;
@@ -42,8 +58,13 @@ export declare class Camera {
42
58
  constructor(options?: CameraOptions);
43
59
  get zoom(): number;
44
60
  set zoom(value: number);
45
- /** the framework calls this on resize; sizes are in screen pixels */
46
- setViewport(width: number, height: number): void;
61
+ /**
62
+ * The framework calls this on resize; sizes are in screen pixels. `screenX`/`screenY`
63
+ * default to 0 (an ordinary camera starting at the corner of the canvas); a `Viewport`
64
+ * gives its camera a nonzero one so this camera's own rectangle starts partway across
65
+ * the screen instead, for a split-screen layout.
66
+ */
67
+ setViewport(width: number, height: number, screenX?: number, screenY?: number): void;
47
68
  /** the visible rectangle, in world units: use it to cull */
48
69
  get view(): {
49
70
  x: number;
@@ -84,6 +105,12 @@ export declare class Camera {
84
105
  private clampedCentre;
85
106
  private apply;
86
107
  }
108
+ /**
109
+ * The nearest zoom to `zoom` at which `tileSize * zoom` is a whole number of screen pixels -
110
+ * the pure math behind `CameraOptions.pixelPerfectTileSize`, exported so a game can snap a
111
+ * zoom value (from a slider, say) before ever handing it to a `Camera`.
112
+ */
113
+ export declare function snapZoom(zoom: number, tileSize: number): number;
87
114
  /** a camera sized to the running game's viewport, updated on every frame */
88
115
  export declare function createCamera(options?: CameraOptions): Camera;
89
116
  //# sourceMappingURL=Camera.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Camera.d.ts","sourceRoot":"","sources":["../../src/render/Camera.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAIpC;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC7B,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,MAAM;IAClB,4CAA4C;IAC5C,QAAQ,CAAC,KAAK,8CAAmB;IAEjC,yCAAyC;IACzC,CAAC,SAAK;IACN,CAAC,SAAK;IAEN,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAS;IAEzB,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,UAAU,CAAK;IAEvB,OAAO,CAAC,YAAY,CAAyC;IAG7D,OAAO,CAAC,eAAe,CAAK;IAE5B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,MAAM,CAAK;IAEnB,yFAAyF;IACzF,OAAO,CAAC,MAAM,CAA2E;IAEzF,YAAY,OAAO,GAAE,aAAkB,EAGtC;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAErB;IAED,qEAAqE;IACrE,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAG/C;IAED,4DAA4D;IAC5D,IAAI,IAAI,IAAI;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAKlE;IAED,oEAAoE;IACpE,SAAS,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,GAAG,IAAI,CAEzF;IAED,wEAAwE;IACxE,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAMjC;IAED,kCAAkC;IAClC,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,SAAI,GAAG,IAAI,CAG/C;IAED,oEAAoE;IACpE,MAAM,CAAC,MAAM,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,SAAS,SAAI,GAAG,IAAI,CAG5D;IAED,aAAa,IAAI,IAAI,CAGpB;IAED,2DAA2D;IAC3D,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,SAAM,GAAG,IAAI,CAG7C;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CA8BvB;IAED,mCAAmC;IACnC,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAKvD;IAED,oEAAoE;IACpE,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAKtD;IAID,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,KAAK;CAQb;AAMD,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,OAAO,GAAE,aAAkB,GAAG,MAAM,CAMhE"}
1
+ {"version":3,"file":"Camera.d.ts","sourceRoot":"","sources":["../../src/render/Camera.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,10 @@ export class Camera {
10
10
  this.y = 0;
11
11
  this.viewWidth = 0;
12
12
  this.viewHeight = 0;
13
+ //where this camera's own rectangle starts on screen; 0,0 for an ordinary full-screen
14
+ //camera, nonzero for one player's share of a split-screen layout (see render.Viewport)
15
+ this.screenX = 0;
16
+ this.screenY = 0;
13
17
  this.followTarget = null;
14
18
  //how fast the camera closes on its target: it covers `intensity` of the remaining
15
19
  //distance each second, so it eases in without ever quite arriving
@@ -21,19 +25,29 @@ export class Camera {
21
25
  this.shakeY = 0;
22
26
  /** clamps the view to these world bounds when set, so the map's edge is never crossed */
23
27
  this.bounds = null;
24
- this._zoom = options.zoom ?? 1;
25
28
  this.deadzone = options.deadzone ?? 0;
29
+ this.pixelPerfectTileSize = options.pixelPerfectTileSize;
30
+ this._zoom = 1;
31
+ this.zoom = options.zoom ?? 1;
26
32
  }
27
33
  get zoom() {
28
34
  return this._zoom;
29
35
  }
30
36
  set zoom(value) {
31
- this._zoom = Math.max(0.01, value);
32
- }
33
- /** the framework calls this on resize; sizes are in screen pixels */
34
- setViewport(width, height) {
37
+ const clamped = Math.max(0.01, value);
38
+ this._zoom = this.pixelPerfectTileSize ? snapZoom(clamped, this.pixelPerfectTileSize) : clamped;
39
+ }
40
+ /**
41
+ * The framework calls this on resize; sizes are in screen pixels. `screenX`/`screenY`
42
+ * default to 0 (an ordinary camera starting at the corner of the canvas); a `Viewport`
43
+ * gives its camera a nonzero one so this camera's own rectangle starts partway across
44
+ * the screen instead, for a split-screen layout.
45
+ */
46
+ setViewport(width, height, screenX = 0, screenY = 0) {
35
47
  this.viewWidth = width;
36
48
  this.viewHeight = height;
49
+ this.screenX = screenX;
50
+ this.screenY = screenY;
37
51
  }
38
52
  /** the visible rectangle, in world units: use it to cull */
39
53
  get view() {
@@ -102,16 +116,22 @@ export class Camera {
102
116
  }
103
117
  /** world point to screen pixels */
104
118
  toScreen(x, y) {
119
+ //must agree with apply()'s clamped centre (shake included), or a point converted
120
+ //with this and placed on screen lands somewhere other than where the camera
121
+ //actually drew it - exactly what happens near a bound, or on an axis the map is
122
+ //narrower than the view
123
+ const { x: centreX, y: centreY } = this.clampedCentre(this.x + this.shakeX, this.y + this.shakeY);
105
124
  return {
106
- x: (x - this.x) * this._zoom + this.viewWidth / 2,
107
- y: (y - this.y) * this._zoom + this.viewHeight / 2,
125
+ x: (x - centreX) * this._zoom + this.screenX + this.viewWidth / 2,
126
+ y: (y - centreY) * this._zoom + this.screenY + this.viewHeight / 2,
108
127
  };
109
128
  }
110
129
  /** screen pixels to world point, for turning a click into a tile */
111
130
  toWorld(x, y) {
131
+ const { x: centreX, y: centreY } = this.clampedCentre(this.x + this.shakeX, this.y + this.shakeY);
112
132
  return {
113
- x: (x - this.viewWidth / 2) / this._zoom + this.x,
114
- y: (y - this.viewHeight / 2) / this._zoom + this.y,
133
+ x: (x - this.screenX - this.viewWidth / 2) / this._zoom + centreX,
134
+ y: (y - this.screenY - this.viewHeight / 2) / this._zoom + centreY,
115
135
  };
116
136
  }
117
137
  //the bounds-clamped centre `apply()` renders at, also what `view` reports for
@@ -133,13 +153,22 @@ export class Camera {
133
153
  const { x: centreX, y: centreY } = this.clampedCentre(this.x + this.shakeX, this.y + this.shakeY);
134
154
  this.world.scale.set(this._zoom);
135
155
  //rounding to whole screen pixels stops pixel art shimmering as the camera moves
136
- this.world.x = Math.round(this.viewWidth / 2 - centreX * this._zoom);
137
- this.world.y = Math.round(this.viewHeight / 2 - centreY * this._zoom);
156
+ this.world.x = Math.round(this.screenX + this.viewWidth / 2 - centreX * this._zoom);
157
+ this.world.y = Math.round(this.screenY + this.viewHeight / 2 - centreY * this._zoom);
138
158
  }
139
159
  }
140
160
  function clamp(value, min, max) {
141
161
  return value < min ? min : value > max ? max : value;
142
162
  }
163
+ /**
164
+ * The nearest zoom to `zoom` at which `tileSize * zoom` is a whole number of screen pixels -
165
+ * the pure math behind `CameraOptions.pixelPerfectTileSize`, exported so a game can snap a
166
+ * zoom value (from a slider, say) before ever handing it to a `Camera`.
167
+ */
168
+ export function snapZoom(zoom, tileSize) {
169
+ const pixels = Math.max(1, Math.round(zoom * tileSize));
170
+ return pixels / tileSize;
171
+ }
143
172
  /** a camera sized to the running game's viewport, updated on every frame */
144
173
  export function createCamera(options = {}) {
145
174
  const camera = new Camera(options);
@@ -1 +1 @@
1
- {"version":3,"file":"Camera.js","sourceRoot":"","sources":["../../src/render/Camera.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Camera.js","sourceRoot":"","sources":["../../src/render/Camera.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ export type GraphicsWorkload = 'sprites' | 'ui' | 'custom-shaders' | 'particles' | 'instanced-terrain' | 'voxels' | 'animated-models' | 'large-3d-worlds';
2
+ export interface GraphicsCapabilities {
3
+ webgl1: boolean;
4
+ webgl2: boolean;
5
+ webgpu: boolean;
6
+ /** WGSL is usable only through a WebGPU-capable browser runtime. */
7
+ wgsl: boolean;
8
+ }
9
+ export interface GraphicsProbe {
10
+ createCanvas?(): {
11
+ getContext(kind: string): unknown;
12
+ } | null;
13
+ webgpu?: boolean;
14
+ /** whether a real WGSL shader actually compiled; see `detectWebGpu` for how to get one */
15
+ wgsl?: boolean;
16
+ }
17
+ export interface RenderingDecision {
18
+ workload: GraphicsWorkload;
19
+ preferred: string;
20
+ fallback: string;
21
+ reason: string;
22
+ }
23
+ /**
24
+ * The framework's rendering choices by workload. This is data, not a global renderer switch:
25
+ * each game imports only the module it uses and keeps 2D Pixi and optional 3D Babylon paths
26
+ * independent.
27
+ */
28
+ export declare const RENDERING_DECISIONS: readonly RenderingDecision[];
29
+ /**
30
+ * Reports browser graphics APIs without creating a renderer or selecting a fallback.
31
+ * Pass a probe in tests or host integrations; omitting it reads the current browser safely.
32
+ *
33
+ * `wgsl` cannot be checked synchronously - the only way to genuinely know a WGSL shader
34
+ * compiles is `detectWebGpu`, which requests a real device and compiles one, and every step
35
+ * of that is asynchronous. Rather than assume WGSL works just because `navigator.gpu`
36
+ * exists (a browser can expose WebGPU behind a still-broken or disabled implementation),
37
+ * this stays `false` unless a caller supplies a real result through `probe.wgsl`.
38
+ */
39
+ export declare function inspectGraphicsCapabilities(probe?: GraphicsProbe): GraphicsCapabilities;
40
+ export interface WebGpuDetection {
41
+ webgpu: boolean;
42
+ wgsl: boolean;
43
+ }
44
+ /**
45
+ * The real, asynchronous WebGPU/WGSL check `inspectGraphicsCapabilities` cannot do
46
+ * synchronously: requests an actual adapter and device, then compiles an actual shader
47
+ * module and reads back its compilation diagnostics. Feed the result to
48
+ * `inspectGraphicsCapabilities` via `probe.webgpu`/`probe.wgsl` once resolved.
49
+ */
50
+ export declare function detectWebGpu(): Promise<WebGpuDetection>;
51
+ //# sourceMappingURL=Capabilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Capabilities.d.ts","sourceRoot":"","sources":["../../src/render/Capabilities.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GACzB,SAAS,GACT,IAAI,GACJ,gBAAgB,GAChB,WAAW,GACX,mBAAmB,GACnB,QAAQ,GACR,iBAAiB,GACjB,iBAAiB,CAAC;AAErB,MAAM,WAAW,oBAAoB;IACpC,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,oEAAoE;IACpE,IAAI,EAAE,OAAO,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC7B,YAAY,CAAC,IAAI;QAAE,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAC9D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0FAA0F;IAC1F,IAAI,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IACjC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,iBAAiB,EAS3D,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,GAAE,aAAkB,GAAG,oBAAoB,CAM3F;AAED,MAAM,WAAW,eAAe;IAC/B,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;CACd;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,eAAe,CAAC,CAe7D"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * The framework's rendering choices by workload. This is data, not a global renderer switch:
3
+ * each game imports only the module it uses and keeps 2D Pixi and optional 3D Babylon paths
4
+ * independent.
5
+ */
6
+ export const RENDERING_DECISIONS = [
7
+ { workload: 'sprites', preferred: 'PixiJS WebGL/WebGPU batcher', fallback: 'PixiJS WebGL', reason: 'high-volume textured 2D batches' },
8
+ { workload: 'ui', preferred: 'PixiJS display tree', fallback: 'PixiJS display tree', reason: 'themeable 2D layout and text' },
9
+ { workload: 'custom-shaders', preferred: 'backend-specific GLSL/WGSL only when profiled', fallback: 'PixiJS filters', reason: 'avoid maintaining paired shader sources without a measured gain' },
10
+ { workload: 'particles', preferred: 'PixiJS for 2D, Babylon.js for 3D', fallback: 'instanced sprites/meshes', reason: 'match simulation and depth to the scene' },
11
+ { workload: 'instanced-terrain', preferred: 'Babylon.js thin instances', fallback: 'PixiJS TileMap for 2D', reason: 'depth-tested repeated 3D geometry' },
12
+ { workload: 'voxels', preferred: 'Babylon.js thin instances', fallback: 'batched meshes', reason: 'color-grouped 3D voxels' },
13
+ { workload: 'animated-models', preferred: 'Babylon.js glTF animation groups', fallback: 'billboard sprites', reason: 'standard 3D interchange and animation support' },
14
+ { workload: 'large-3d-worlds', preferred: 'Babylon.js with streaming/culling', fallback: 'partitioned scenes', reason: 'scene graph, depth, and instancing' },
15
+ ];
16
+ /**
17
+ * Reports browser graphics APIs without creating a renderer or selecting a fallback.
18
+ * Pass a probe in tests or host integrations; omitting it reads the current browser safely.
19
+ *
20
+ * `wgsl` cannot be checked synchronously - the only way to genuinely know a WGSL shader
21
+ * compiles is `detectWebGpu`, which requests a real device and compiles one, and every step
22
+ * of that is asynchronous. Rather than assume WGSL works just because `navigator.gpu`
23
+ * exists (a browser can expose WebGPU behind a still-broken or disabled implementation),
24
+ * this stays `false` unless a caller supplies a real result through `probe.wgsl`.
25
+ */
26
+ export function inspectGraphicsCapabilities(probe = {}) {
27
+ const canvas = probe.createCanvas?.() ?? (typeof document === 'undefined' ? null : document.createElement('canvas'));
28
+ const webgl2 = Boolean(canvas?.getContext('webgl2'));
29
+ const webgl1 = webgl2 || Boolean(canvas?.getContext('webgl') ?? canvas?.getContext('experimental-webgl'));
30
+ const webgpu = probe.webgpu ?? Boolean(globalThis.navigator?.gpu);
31
+ return { webgl1, webgl2, webgpu, wgsl: probe.wgsl ?? false };
32
+ }
33
+ /**
34
+ * The real, asynchronous WebGPU/WGSL check `inspectGraphicsCapabilities` cannot do
35
+ * synchronously: requests an actual adapter and device, then compiles an actual shader
36
+ * module and reads back its compilation diagnostics. Feed the result to
37
+ * `inspectGraphicsCapabilities` via `probe.webgpu`/`probe.wgsl` once resolved.
38
+ */
39
+ export async function detectWebGpu() {
40
+ const gpu = globalThis.navigator?.gpu;
41
+ if (!gpu)
42
+ return { webgpu: false, wgsl: false };
43
+ try {
44
+ const adapter = await gpu.requestAdapter();
45
+ const device = await adapter?.requestDevice();
46
+ if (!device)
47
+ return { webgpu: false, wgsl: false };
48
+ const shader = device.createShaderModule({ code: '@compute @workgroup_size(1) fn main() {}' });
49
+ const info = await shader.getCompilationInfo();
50
+ return { webgpu: true, wgsl: info.messages.length === 0 };
51
+ }
52
+ catch {
53
+ return { webgpu: false, wgsl: false };
54
+ }
55
+ }
56
+ //# sourceMappingURL=Capabilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Capabilities.js","sourceRoot":"","sources":["../../src/render/Capabilities.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { ColorMatrixFilter } from 'pixi.js';
2
+ import type { ColorMatrix } from 'pixi.js';
3
+ export type ColorBlindnessType = 'protanopia' | 'deuteranopia' | 'tritanopia';
4
+ export declare const COLOR_BLINDNESS_MATRICES: Record<ColorBlindnessType, ColorMatrix>;
5
+ /**
6
+ * A whole-scene filter simulating one of the three common types of colour vision deficiency.
7
+ * Assign the result to a container's `.filters` (typically a game's whole stage), the same
8
+ * way any Pixi filter is applied - nothing here is `mwg`-specific beyond the named matrices.
9
+ *
10
+ * This simulates, showing a sighted developer what a colourblind player sees - the standard
11
+ * first step toward choosing a palette that reads clearly for them. It does not correct an
12
+ * existing palette automatically; that would need the source colours' own intent (which one
13
+ * is the "danger" colour, say), not just their RGB values.
14
+ */
15
+ export declare function createColorBlindnessFilter(type: ColorBlindnessType): ColorMatrixFilter;
16
+ //# sourceMappingURL=ColorBlindness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ColorBlindness.d.ts","sourceRoot":"","sources":["../../src/render/ColorBlindness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,MAAM,MAAM,kBAAkB,GAAG,YAAY,GAAG,cAAc,GAAG,YAAY,CAAC;AAM9E,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,kBAAkB,EAAE,WAAW,CAmB5E,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,kBAAkB,GAAG,iBAAiB,CAItF"}
@@ -0,0 +1,41 @@
1
+ import { ColorMatrixFilter } from 'pixi.js';
2
+ //Brettel/Viénot-derived simulation matrices, the same values widely used by colourblindness
3
+ //simulators - a 5x4 (20-value) row-major RGBA matrix, Pixi's own `ColorMatrixFilter` format.
4
+ //Exported so the matrix data itself can be tested without constructing a `ColorMatrixFilter`,
5
+ //which (like `BitmapText`) needs a real WebGL context even to construct.
6
+ export const COLOR_BLINDNESS_MATRICES = {
7
+ protanopia: [
8
+ 0.567, 0.433, 0, 0, 0,
9
+ 0.558, 0.442, 0, 0, 0,
10
+ 0, 0.242, 0.758, 0, 0,
11
+ 0, 0, 0, 1, 0,
12
+ ],
13
+ deuteranopia: [
14
+ 0.625, 0.375, 0, 0, 0,
15
+ 0.7, 0.3, 0, 0, 0,
16
+ 0, 0.3, 0.7, 0, 0,
17
+ 0, 0, 0, 1, 0,
18
+ ],
19
+ tritanopia: [
20
+ 0.95, 0.05, 0, 0, 0,
21
+ 0, 0.433, 0.567, 0, 0,
22
+ 0, 0.475, 0.525, 0, 0,
23
+ 0, 0, 0, 1, 0,
24
+ ],
25
+ };
26
+ /**
27
+ * A whole-scene filter simulating one of the three common types of colour vision deficiency.
28
+ * Assign the result to a container's `.filters` (typically a game's whole stage), the same
29
+ * way any Pixi filter is applied - nothing here is `mwg`-specific beyond the named matrices.
30
+ *
31
+ * This simulates, showing a sighted developer what a colourblind player sees - the standard
32
+ * first step toward choosing a palette that reads clearly for them. It does not correct an
33
+ * existing palette automatically; that would need the source colours' own intent (which one
34
+ * is the "danger" colour, say), not just their RGB values.
35
+ */
36
+ export function createColorBlindnessFilter(type) {
37
+ const filter = new ColorMatrixFilter();
38
+ filter.matrix = COLOR_BLINDNESS_MATRICES[type];
39
+ return filter;
40
+ }
41
+ //# sourceMappingURL=ColorBlindness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ColorBlindness.js","sourceRoot":"","sources":["../../src/render/ColorBlindness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAK5C,4FAA4F;AAC5F,6FAA6F;AAC7F,8FAA8F;AAC9F,yEAAyE;AACzE,MAAM,CAAC,MAAM,wBAAwB,GAA4C;IAChF,UAAU,EAAE;QACX,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QACrB,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QACrB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QACrB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;KACb;IACD,YAAY,EAAE;QACb,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QACrB,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QACjB,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;QACjB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;KACb;IACD,UAAU,EAAE;QACX,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QACnB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QACrB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QACrB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;KACb;CACD,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,UAAU,0BAA0B,CAAC,IAAwB;IAClE,MAAM,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;IACvC,MAAM,CAAC,MAAM,GAAG,wBAAwB,CAAC,IAAI,CAAC,CAAC;IAC/C,OAAO,MAAM,CAAC;AACf,CAAC"}
@@ -0,0 +1,52 @@
1
+ import { Container } from 'pixi.js';
2
+ /** the cell indices in `explored` not yet baked into a minimap's texture - pure, so it can
3
+ * be tested without a renderer */
4
+ export declare function newlyRevealed(explored: ReadonlySet<number>, alreadyDrawn: ReadonlySet<number>): number[];
5
+ export interface MinimapOptions {
6
+ /** the level's own width, in cells - needed to turn a cell index back into x/y */
7
+ widthInCells: number;
8
+ heightInCells: number;
9
+ /** screen pixels per cell; defaults to 2, small enough for an always-on-screen corner HUD */
10
+ cellSize?: number;
11
+ }
12
+ /**
13
+ * A downscaled picture of a level, built from exactly the data `roguelike.FieldOfView`
14
+ * already tracks - `explored`, distinct from `visible` - plus a per-cell colour a game
15
+ * supplies, since `mwg` has no opinion on what a wall or a floor should look like.
16
+ *
17
+ * The same widget serves both sizes a map screen comes in: a small corner HUD element at a
18
+ * coarse `cellSize`, or a full, `Window`-sized pause-and-look screen at a larger one -
19
+ * nothing here is specific to either. Quest markers or a tracked-quest location (see
20
+ * `rpg.QuestLog.markerFor`/`trackedLocation`) are a game's own overlay on top of `world`,
21
+ * same as they would be over any other rendered view.
22
+ *
23
+ * Revealed cells are painted once into a persistent `RenderTexture` and never revisited -
24
+ * `sync` only rasterises what `newlyRevealed` reports as new, rather than redrawing the
25
+ * whole map from scratch on every call, which is the one open engineering question this
26
+ * item named: how an explored-cell set becomes a small texture without becoming a
27
+ * per-frame cost that grows with how much of the level has been seen.
28
+ */
29
+ export declare class Minimap extends Container {
30
+ private readonly widthInCells;
31
+ private readonly cellSize;
32
+ private renderTexture;
33
+ private sprite;
34
+ private drawn;
35
+ private marker;
36
+ constructor(options: MinimapOptions);
37
+ /** cells revealed since the last call, by width/height already given to the constructor */
38
+ get exploredCount(): number;
39
+ /**
40
+ * Bakes every cell in `explored` that has not been drawn yet, at whatever colour
41
+ * `colorFor` reports for it. A cell already baked is never revisited even if `colorFor`
42
+ * would now answer differently - explored terrain does not usually change colour, and a
43
+ * game that wants it to can `reset()` and resync from a clean texture.
44
+ */
45
+ sync(explored: ReadonlySet<number>, colorFor: (x: number, y: number) => number): void;
46
+ /** positions a marker at a cell, optionally pointing it in a facing direction (radians) */
47
+ setMarker(x: number, y: number, facing?: number, color?: number): void;
48
+ /** forgets everything baked, so the next `sync` repaints from a clean texture - a fresh floor */
49
+ reset(): void;
50
+ destroy(options?: Parameters<Container['destroy']>[0]): void;
51
+ }
52
+ //# sourceMappingURL=Minimap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Minimap.d.ts","sourceRoot":"","sources":["../../src/render/Minimap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAmC,MAAM,SAAS,CAAC;AAGrE;kCACkC;AAClC,wBAAgB,aAAa,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAMxG;AAED,MAAM,WAAW,cAAc;IAC9B,kFAAkF;IAClF,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IAEtB,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,OAAQ,SAAQ,SAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAElC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAqB;IAElC,OAAO,CAAC,MAAM,CAAkB;IAEhC,YAAY,OAAO,EAAE,cAAc,EAalC;IAED,2FAA2F;IAC3F,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED;;;;;OAKG;IACH,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAgBpF;IAED,2FAA2F;IAC3F,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,SAAW,GAAG,IAAI,CAcvE;IAED,iGAAiG;IACjG,KAAK,IAAI,IAAI,CAGZ;IAEQ,OAAO,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAGpE;CACD"}
@@ -0,0 +1,95 @@
1
+ import { Container, Graphics, RenderTexture, Sprite } from 'pixi.js';
2
+ import { Game } from '../core/Game.js';
3
+ /** the cell indices in `explored` not yet baked into a minimap's texture - pure, so it can
4
+ * be tested without a renderer */
5
+ export function newlyRevealed(explored, alreadyDrawn) {
6
+ const result = [];
7
+ for (const index of explored) {
8
+ if (!alreadyDrawn.has(index))
9
+ result.push(index);
10
+ }
11
+ return result;
12
+ }
13
+ /**
14
+ * A downscaled picture of a level, built from exactly the data `roguelike.FieldOfView`
15
+ * already tracks - `explored`, distinct from `visible` - plus a per-cell colour a game
16
+ * supplies, since `mwg` has no opinion on what a wall or a floor should look like.
17
+ *
18
+ * The same widget serves both sizes a map screen comes in: a small corner HUD element at a
19
+ * coarse `cellSize`, or a full, `Window`-sized pause-and-look screen at a larger one -
20
+ * nothing here is specific to either. Quest markers or a tracked-quest location (see
21
+ * `rpg.QuestLog.markerFor`/`trackedLocation`) are a game's own overlay on top of `world`,
22
+ * same as they would be over any other rendered view.
23
+ *
24
+ * Revealed cells are painted once into a persistent `RenderTexture` and never revisited -
25
+ * `sync` only rasterises what `newlyRevealed` reports as new, rather than redrawing the
26
+ * whole map from scratch on every call, which is the one open engineering question this
27
+ * item named: how an explored-cell set becomes a small texture without becoming a
28
+ * per-frame cost that grows with how much of the level has been seen.
29
+ */
30
+ export class Minimap extends Container {
31
+ constructor(options) {
32
+ super();
33
+ this.drawn = new Set();
34
+ this.marker = new Graphics();
35
+ this.widthInCells = options.widthInCells;
36
+ this.cellSize = options.cellSize ?? 2;
37
+ this.renderTexture = RenderTexture.create({
38
+ width: options.widthInCells * this.cellSize,
39
+ height: options.heightInCells * this.cellSize,
40
+ });
41
+ this.sprite = new Sprite(this.renderTexture);
42
+ this.addChild(this.sprite);
43
+ this.addChild(this.marker);
44
+ }
45
+ /** cells revealed since the last call, by width/height already given to the constructor */
46
+ get exploredCount() {
47
+ return this.drawn.size;
48
+ }
49
+ /**
50
+ * Bakes every cell in `explored` that has not been drawn yet, at whatever colour
51
+ * `colorFor` reports for it. A cell already baked is never revisited even if `colorFor`
52
+ * would now answer differently - explored terrain does not usually change colour, and a
53
+ * game that wants it to can `reset()` and resync from a clean texture.
54
+ */
55
+ sync(explored, colorFor) {
56
+ const cells = newlyRevealed(explored, this.drawn);
57
+ if (cells.length === 0)
58
+ return;
59
+ const patch = new Graphics();
60
+ for (const index of cells) {
61
+ this.drawn.add(index);
62
+ const x = index % this.widthInCells;
63
+ const y = Math.floor(index / this.widthInCells);
64
+ patch
65
+ .rect(x * this.cellSize, y * this.cellSize, this.cellSize, this.cellSize)
66
+ .fill({ color: colorFor(x, y) });
67
+ }
68
+ Game.current.app.renderer.render({ container: patch, target: this.renderTexture, clear: false });
69
+ patch.destroy();
70
+ }
71
+ /** positions a marker at a cell, optionally pointing it in a facing direction (radians) */
72
+ setMarker(x, y, facing, color = 0xffffff) {
73
+ this.marker.clear();
74
+ this.marker.circle(0, 0, Math.max(1, this.cellSize)).fill({ color });
75
+ if (facing !== undefined) {
76
+ const length = this.cellSize * 2;
77
+ this.marker
78
+ .moveTo(0, 0)
79
+ .lineTo(Math.cos(facing) * length, Math.sin(facing) * length)
80
+ .stroke({ color, width: 1 });
81
+ }
82
+ this.marker.x = (x + 0.5) * this.cellSize;
83
+ this.marker.y = (y + 0.5) * this.cellSize;
84
+ }
85
+ /** forgets everything baked, so the next `sync` repaints from a clean texture - a fresh floor */
86
+ reset() {
87
+ this.drawn.clear();
88
+ Game.current.app.renderer.render({ container: new Container(), target: this.renderTexture, clear: true });
89
+ }
90
+ destroy(options) {
91
+ this.renderTexture.destroy(true);
92
+ super.destroy(options);
93
+ }
94
+ }
95
+ //# sourceMappingURL=Minimap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Minimap.js","sourceRoot":"","sources":["../../src/render/Minimap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import { Container } from 'pixi.js';
2
+ import { Camera, type CameraOptions } from './Camera.ts';
3
+ export interface ViewportOptions extends CameraOptions {
4
+ /** this viewport's own rectangle of the screen, in pixels */
5
+ x: number;
6
+ y: number;
7
+ width: number;
8
+ height: number;
9
+ }
10
+ /**
11
+ * One player's own rectangle of the screen, for a same-screen local multiplayer layout: a
12
+ * `Camera` whose world is offset to start at `x`/`y` instead of the corner of the canvas,
13
+ * and clipped to `width`/`height` so it never bleeds into a neighbouring player's share of
14
+ * the screen. A game with a single `Viewport` covering the whole canvas behaves exactly like
15
+ * a game using a bare `Camera` directly - this adds a screen region and a mask around it,
16
+ * nothing else.
17
+ */
18
+ export declare class Viewport {
19
+ readonly camera: Camera;
20
+ /** add this to `Game.current.stage`, the way a single-camera game already adds `camera.world` */
21
+ readonly container: Container<import("pixi.js").ContainerChild>;
22
+ private readonly clip;
23
+ constructor(options: ViewportOptions);
24
+ /** moves and/or resizes this viewport's own rectangle of the screen */
25
+ resize(x: number, y: number, width: number, height: number): void;
26
+ update(dt: number): void;
27
+ }
28
+ /**
29
+ * The two even halves of `width`×`height` a two-player split screen typically wants -
30
+ * side by side for a landscape screen, stacked for a portrait one - as plain rectangles a
31
+ * game hands straight to two `Viewport`s (or to `resize` on a resize event). Not the only
32
+ * reasonable split, so not baked into `Viewport` itself: a game wanting an L-shaped, uneven,
33
+ * or three/four-player layout lays out its own rectangles the same way.
34
+ */
35
+ export declare function splitScreenHalves(width: number, height: number): [{
36
+ x: number;
37
+ y: number;
38
+ width: number;
39
+ height: number;
40
+ }, {
41
+ x: number;
42
+ y: number;
43
+ width: number;
44
+ height: number;
45
+ }];
46
+ //# sourceMappingURL=Viewport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Viewport.d.ts","sourceRoot":"","sources":["../../src/render/Viewport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAY,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAEzD,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACrD,6DAA6D;IAC7D,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;GAOG;AACH,qBAAa,QAAQ;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,iGAAiG;IACjG,QAAQ,CAAC,SAAS,8CAAmB;IAErC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAkB;IAEvC,YAAY,OAAO,EAAE,eAAe,EAMnC;IAED,uEAAuE;IACvE,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAGhE;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAEvB;CACD;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAChC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACZ,CAAC;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAapH"}