@datamoc/mw_games 0.4.1 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/README.md +1 -1
  2. package/dist/assets/binary.d.ts +52 -0
  3. package/dist/assets/binary.d.ts.map +1 -0
  4. package/dist/assets/binary.js +57 -0
  5. package/dist/assets/binary.js.map +1 -0
  6. package/dist/assets/index.d.ts +10 -5
  7. package/dist/assets/index.d.ts.map +1 -1
  8. package/dist/assets/index.js +9 -5
  9. package/dist/assets/index.js.map +1 -1
  10. package/dist/board/Army.d.ts +75 -0
  11. package/dist/board/Army.d.ts.map +1 -1
  12. package/dist/board/Army.js +75 -0
  13. package/dist/board/Army.js.map +1 -1
  14. package/dist/board/Classics.d.ts +297 -1
  15. package/dist/board/Classics.d.ts.map +1 -1
  16. package/dist/board/Classics.js +297 -1
  17. package/dist/board/Classics.js.map +1 -1
  18. package/dist/board/Engine.d.ts +23 -0
  19. package/dist/board/Engine.d.ts.map +1 -1
  20. package/dist/board/Engine.js +23 -0
  21. package/dist/board/Engine.js.map +1 -1
  22. package/dist/board/FogOfWar.d.ts +20 -0
  23. package/dist/board/FogOfWar.d.ts.map +1 -1
  24. package/dist/board/FogOfWar.js +20 -0
  25. package/dist/board/FogOfWar.js.map +1 -1
  26. package/dist/board/Tactics.d.ts +158 -1
  27. package/dist/board/Tactics.d.ts.map +1 -1
  28. package/dist/board/Tactics.js +125 -1
  29. package/dist/board/Tactics.js.map +1 -1
  30. package/dist/board/chess.d.ts +87 -3
  31. package/dist/board/chess.d.ts.map +1 -1
  32. package/dist/board/chess.js +96 -4
  33. package/dist/board/chess.js.map +1 -1
  34. package/dist/i18n/Content.d.ts +151 -0
  35. package/dist/i18n/Content.d.ts.map +1 -0
  36. package/dist/i18n/Content.js +219 -0
  37. package/dist/i18n/Content.js.map +1 -0
  38. package/dist/i18n/index.d.ts +35 -3
  39. package/dist/i18n/index.d.ts.map +1 -1
  40. package/dist/i18n/index.js +88 -6
  41. package/dist/i18n/index.js.map +1 -1
  42. package/dist/mw_games.global.js +89 -89
  43. package/dist/roguelike/Placement.d.ts +62 -0
  44. package/dist/roguelike/Placement.d.ts.map +1 -0
  45. package/dist/roguelike/Placement.js +79 -0
  46. package/dist/roguelike/Placement.js.map +1 -0
  47. package/dist/roguelike/index.d.ts +2 -0
  48. package/dist/roguelike/index.d.ts.map +1 -1
  49. package/dist/roguelike/index.js +1 -0
  50. package/dist/roguelike/index.js.map +1 -1
  51. package/dist/three-d/Models.d.ts +38 -1
  52. package/dist/three-d/Models.d.ts.map +1 -1
  53. package/dist/three-d/Models.js +66 -3
  54. package/dist/three-d/Models.js.map +1 -1
  55. package/dist/two-d/render/ActorAnimator.d.ts +32 -0
  56. package/dist/two-d/render/ActorAnimator.d.ts.map +1 -1
  57. package/dist/two-d/render/ActorAnimator.js +21 -0
  58. package/dist/two-d/render/ActorAnimator.js.map +1 -1
  59. package/dist/two-d/render/AnimatedSprite.d.ts +24 -4
  60. package/dist/two-d/render/AnimatedSprite.d.ts.map +1 -1
  61. package/dist/two-d/render/AnimatedSprite.js +24 -4
  62. package/dist/two-d/render/AnimatedSprite.js.map +1 -1
  63. package/dist/two-d/render/Autotile.d.ts +33 -1
  64. package/dist/two-d/render/Autotile.d.ts.map +1 -1
  65. package/dist/two-d/render/Autotile.js +33 -1
  66. package/dist/two-d/render/Autotile.js.map +1 -1
  67. package/dist/two-d/render/Camera.d.ts +53 -1
  68. package/dist/two-d/render/Camera.d.ts.map +1 -1
  69. package/dist/two-d/render/Camera.js +36 -1
  70. package/dist/two-d/render/Camera.js.map +1 -1
  71. package/dist/two-d/render/Capabilities.d.ts +33 -0
  72. package/dist/two-d/render/Capabilities.d.ts.map +1 -1
  73. package/dist/two-d/render/Capabilities.js +33 -0
  74. package/dist/two-d/render/Capabilities.js.map +1 -1
  75. package/dist/two-d/render/ColorBlindness.d.ts +23 -0
  76. package/dist/two-d/render/ColorBlindness.d.ts.map +1 -1
  77. package/dist/two-d/render/ColorBlindness.js +23 -4
  78. package/dist/two-d/render/ColorBlindness.js.map +1 -1
  79. package/dist/two-d/render/ColorTransformBatcher.d.ts +67 -1
  80. package/dist/two-d/render/ColorTransformBatcher.d.ts.map +1 -1
  81. package/dist/two-d/render/ColorTransformBatcher.js +57 -1
  82. package/dist/two-d/render/ColorTransformBatcher.js.map +1 -1
  83. package/dist/two-d/render/LayeredSprite.d.ts +19 -0
  84. package/dist/two-d/render/LayeredSprite.d.ts.map +1 -1
  85. package/dist/two-d/render/LayeredSprite.js +19 -0
  86. package/dist/two-d/render/LayeredSprite.js.map +1 -1
  87. package/dist/two-d/render/Minimap.d.ts +25 -1
  88. package/dist/two-d/render/Minimap.d.ts.map +1 -1
  89. package/dist/two-d/render/Minimap.js +25 -1
  90. package/dist/two-d/render/Minimap.js.map +1 -1
  91. package/dist/two-d/render/Particles.d.ts +26 -2
  92. package/dist/two-d/render/Particles.d.ts.map +1 -1
  93. package/dist/two-d/render/Particles.js +23 -0
  94. package/dist/two-d/render/Particles.js.map +1 -1
  95. package/dist/two-d/render/Projectile.d.ts +14 -0
  96. package/dist/two-d/render/Projectile.d.ts.map +1 -1
  97. package/dist/two-d/render/Projectile.js +14 -0
  98. package/dist/two-d/render/Projectile.js.map +1 -1
  99. package/dist/two-d/render/ScreenEffects.d.ts +15 -0
  100. package/dist/two-d/render/ScreenEffects.d.ts.map +1 -1
  101. package/dist/two-d/render/ScreenEffects.js +15 -0
  102. package/dist/two-d/render/ScreenEffects.js.map +1 -1
  103. package/dist/two-d/render/Shape2D.d.ts +58 -1
  104. package/dist/two-d/render/Shape2D.d.ts.map +1 -1
  105. package/dist/two-d/render/Shape2D.js +58 -1
  106. package/dist/two-d/render/Shape2D.js.map +1 -1
  107. package/dist/two-d/render/StatusVisuals.d.ts +22 -0
  108. package/dist/two-d/render/StatusVisuals.d.ts.map +1 -1
  109. package/dist/two-d/render/StatusVisuals.js +22 -0
  110. package/dist/two-d/render/StatusVisuals.js.map +1 -1
  111. package/dist/two-d/render/TileMap.d.ts +65 -3
  112. package/dist/two-d/render/TileMap.d.ts.map +1 -1
  113. package/dist/two-d/render/TileMap.js +65 -3
  114. package/dist/two-d/render/TileMap.js.map +1 -1
  115. package/dist/two-d/render/TiledMap.d.ts +9 -3
  116. package/dist/two-d/render/TiledMap.d.ts.map +1 -1
  117. package/dist/two-d/render/TiledMap.js +9 -3
  118. package/dist/two-d/render/TiledMap.js.map +1 -1
  119. package/dist/two-d/render/TintedSprite.d.ts +9 -2
  120. package/dist/two-d/render/TintedSprite.d.ts.map +1 -1
  121. package/dist/two-d/render/TintedSprite.js +9 -2
  122. package/dist/two-d/render/TintedSprite.js.map +1 -1
  123. package/dist/two-d/render/Types2D.d.ts +14 -2
  124. package/dist/two-d/render/Types2D.d.ts.map +1 -1
  125. package/dist/two-d/render/Types2D.js +14 -2
  126. package/dist/two-d/render/Types2D.js.map +1 -1
  127. package/dist/two-d/render/Viewport.d.ts +22 -0
  128. package/dist/two-d/render/Viewport.d.ts.map +1 -1
  129. package/dist/two-d/render/Viewport.js +22 -0
  130. package/dist/two-d/render/Viewport.js.map +1 -1
  131. package/dist/two-d/ui/Bar.d.ts +16 -3
  132. package/dist/two-d/ui/Bar.d.ts.map +1 -1
  133. package/dist/two-d/ui/Bar.js +16 -1
  134. package/dist/two-d/ui/Bar.js.map +1 -1
  135. package/dist/two-d/ui/BitmapLabel.d.ts +23 -1
  136. package/dist/two-d/ui/BitmapLabel.d.ts.map +1 -1
  137. package/dist/two-d/ui/BitmapLabel.js +23 -1
  138. package/dist/two-d/ui/BitmapLabel.js.map +1 -1
  139. package/dist/two-d/ui/Button.d.ts +15 -0
  140. package/dist/two-d/ui/Button.d.ts.map +1 -1
  141. package/dist/two-d/ui/Button.js +15 -0
  142. package/dist/two-d/ui/Button.js.map +1 -1
  143. package/dist/two-d/ui/FloatingText.d.ts +15 -0
  144. package/dist/two-d/ui/FloatingText.d.ts.map +1 -1
  145. package/dist/two-d/ui/FloatingText.js +15 -0
  146. package/dist/two-d/ui/FloatingText.js.map +1 -1
  147. package/dist/two-d/ui/HelpScreen.d.ts +16 -0
  148. package/dist/two-d/ui/HelpScreen.d.ts.map +1 -1
  149. package/dist/two-d/ui/HelpScreen.js +23 -3
  150. package/dist/two-d/ui/HelpScreen.js.map +1 -1
  151. package/dist/two-d/ui/IconGrid.d.ts +25 -0
  152. package/dist/two-d/ui/IconGrid.d.ts.map +1 -1
  153. package/dist/two-d/ui/IconGrid.js +37 -5
  154. package/dist/two-d/ui/IconGrid.js.map +1 -1
  155. package/dist/two-d/ui/Label.d.ts +10 -0
  156. package/dist/two-d/ui/Label.d.ts.map +1 -1
  157. package/dist/two-d/ui/Label.js +10 -0
  158. package/dist/two-d/ui/Label.js.map +1 -1
  159. package/dist/two-d/ui/ListView.d.ts +19 -0
  160. package/dist/two-d/ui/ListView.d.ts.map +1 -1
  161. package/dist/two-d/ui/ListView.js +19 -0
  162. package/dist/two-d/ui/ListView.js.map +1 -1
  163. package/dist/two-d/ui/LoadingScreen.d.ts +24 -1
  164. package/dist/two-d/ui/LoadingScreen.d.ts.map +1 -1
  165. package/dist/two-d/ui/LoadingScreen.js +24 -1
  166. package/dist/two-d/ui/LoadingScreen.js.map +1 -1
  167. package/dist/two-d/ui/MessageBox.d.ts +21 -2
  168. package/dist/two-d/ui/MessageBox.d.ts.map +1 -1
  169. package/dist/two-d/ui/MessageBox.js +19 -0
  170. package/dist/two-d/ui/MessageBox.js.map +1 -1
  171. package/dist/two-d/ui/NinePatch.d.ts +12 -0
  172. package/dist/two-d/ui/NinePatch.d.ts.map +1 -1
  173. package/dist/two-d/ui/NinePatch.js +12 -0
  174. package/dist/two-d/ui/NinePatch.js.map +1 -1
  175. package/dist/two-d/ui/RebindScreen.d.ts +15 -0
  176. package/dist/two-d/ui/RebindScreen.d.ts.map +1 -1
  177. package/dist/two-d/ui/RebindScreen.js +15 -0
  178. package/dist/two-d/ui/RebindScreen.js.map +1 -1
  179. package/dist/two-d/ui/StatsScreen.d.ts +15 -0
  180. package/dist/two-d/ui/StatsScreen.d.ts.map +1 -1
  181. package/dist/two-d/ui/StatsScreen.js +15 -0
  182. package/dist/two-d/ui/StatsScreen.js.map +1 -1
  183. package/dist/two-d/ui/Toast.d.ts +12 -0
  184. package/dist/two-d/ui/Toast.d.ts.map +1 -1
  185. package/dist/two-d/ui/Toast.js +12 -0
  186. package/dist/two-d/ui/Toast.js.map +1 -1
  187. package/dist/two-d/ui/Tooltip.d.ts +14 -0
  188. package/dist/two-d/ui/Tooltip.d.ts.map +1 -1
  189. package/dist/two-d/ui/Tooltip.js +14 -0
  190. package/dist/two-d/ui/Tooltip.js.map +1 -1
  191. package/dist/two-d/ui/VerticalLabel.d.ts +18 -0
  192. package/dist/two-d/ui/VerticalLabel.d.ts.map +1 -1
  193. package/dist/two-d/ui/VerticalLabel.js +18 -0
  194. package/dist/two-d/ui/VerticalLabel.js.map +1 -1
  195. package/dist/two-d/ui/Window.d.ts +12 -0
  196. package/dist/two-d/ui/Window.d.ts.map +1 -1
  197. package/dist/two-d/ui/Window.js +12 -0
  198. package/dist/two-d/ui/Window.js.map +1 -1
  199. package/dist/two-d/ui/theme.d.ts +45 -1
  200. package/dist/two-d/ui/theme.d.ts.map +1 -1
  201. package/dist/two-d/ui/theme.js +45 -1
  202. package/dist/two-d/ui/theme.js.map +1 -1
  203. package/dist/version.d.ts +1 -1
  204. package/dist/version.js +1 -1
  205. package/package.json +8 -2
@@ -0,0 +1,62 @@
1
+ import type { Level } from './Level.ts';
2
+ /**
3
+ * Filters over terrain and occupancy for a placement pool - the seam a dungeon's
4
+ * feature/content hooks use to ask "which cells could this go on" without `FeatureLayer` or
5
+ * a game's own item/monster classes ever entering the picture. Every field is optional and
6
+ * narrows the pool further; omitting all of them is every cell on the level.
7
+ */
8
+ export interface PlacementFilter {
9
+ /** raw terrain kind ids eligible (indices into the `Level`'s own `kinds`); omit for any kind */
10
+ terrain?: ReadonlySet<number>;
11
+ /** cells to exclude - already taken by another feature, a monster, an item */
12
+ occupied?: ReadonlySet<number>;
13
+ /** restrict the search to these cells (a room's interior, a hand-picked region); omit for the whole level */
14
+ within?: Iterable<number>;
15
+ }
16
+ /** Every cell on `level` matching `filter` - the pool a placement selects from. */
17
+ export declare function candidateCells(level: Level, filter?: PlacementFilter): number[];
18
+ /** Cells within `radius` neighbour-steps of `center` (via `Level.neighbors`, so hex and square both work), never including `center` itself. */
19
+ export declare function cellsNear(level: Level, center: number, radius: number): number[];
20
+ export interface PlacementTraceEntry {
21
+ requested: number;
22
+ available: number;
23
+ selected: number[];
24
+ }
25
+ export interface PlacementResult {
26
+ cells: number[];
27
+ trace: PlacementTraceEntry;
28
+ }
29
+ /**
30
+ * Picks `count` distinct cells out of `candidates` without replacement, falling back to
31
+ * however many exist when fewer are available rather than throwing or looping forever - a
32
+ * crowded region just gets fewer placements, the same "fail gracefully, place fewer" shape
33
+ * `generateDungeonGraph`'s own room placement already uses. Pure: nothing is placed or
34
+ * marked taken until the caller acts on `cells` itself (typically `FeatureLayer.place`, or
35
+ * folding `cells` into the next call's own `occupied` set). `trace` is plain, JSON-safe data
36
+ * a game can push straight into `DungeonArtifacts.content` for a parity check, or persist
37
+ * across save/load the same way any other roll trace does.
38
+ *
39
+ * Composes with `candidateCells` and `cellsNear` for the three shapes a regional generator
40
+ * needs: several neighbouring items (`cellsNear` around one anchor, intersected with a
41
+ * terrain/occupancy pool, then selected from), scattered decorations across a whole region
42
+ * (`candidateCells` with a large `within`, then selected from with a larger `count`), and a
43
+ * single branch or room reward (`candidateCells` scoped to one room, `count: 1`).
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * import { candidateCells, cellsNear, selectDistinctCells } from '@datamoc/mw_games/roguelike';
48
+ *
49
+ * declare const level: import('@datamoc/mw_games/roguelike').Level;
50
+ * const FLOOR = new Set([1]);
51
+ *
52
+ * // scatter 3 decorations anywhere on the floor
53
+ * const pool = candidateCells(level, { terrain: FLOOR });
54
+ * const { cells: decorations, trace } = selectDistinctCells(pool, 3);
55
+ *
56
+ * // then release 2 more items clustered around one of those cells
57
+ * const nearby = cellsNear(level, decorations[0], 2).filter((c) => pool.includes(c));
58
+ * const { cells: cluster } = selectDistinctCells(nearby, 2);
59
+ * ```
60
+ */
61
+ export declare function selectDistinctCells(candidates: readonly number[], count: number): PlacementResult;
62
+ //# sourceMappingURL=Placement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Placement.d.ts","sourceRoot":"","sources":["../../src/roguelike/Placement.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC/B,gGAAgG;IAChG,OAAO,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAE9B,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAE/B,6GAA6G;IAC7G,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CAC1B;AAED,mFAAmF;AACnF,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,GAAE,eAAoB,GAAG,MAAM,EAAE,CAOnF;AAED,+IAA+I;AAC/I,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAoBhF;AAED,MAAM,WAAW,mBAAmB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,mBAAmB,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,CAKjG"}
@@ -0,0 +1,79 @@
1
+ import * as Random from '../core/Random.js';
2
+ /** Every cell on `level` matching `filter` - the pool a placement selects from. */
3
+ export function candidateCells(level, filter = {}) {
4
+ const source = filter.within ? [...filter.within] : range(level.cellCount);
5
+ return source.filter((cell) => {
6
+ if (filter.occupied?.has(cell))
7
+ return false;
8
+ if (filter.terrain && !filter.terrain.has(level.terrain[cell]))
9
+ return false;
10
+ return true;
11
+ });
12
+ }
13
+ /** Cells within `radius` neighbour-steps of `center` (via `Level.neighbors`, so hex and square both work), never including `center` itself. */
14
+ export function cellsNear(level, center, radius) {
15
+ const seen = new Set([center]);
16
+ let frontier = [center];
17
+ for (let step = 0; step < Math.max(0, radius); step++) {
18
+ const next = [];
19
+ for (const cell of frontier) {
20
+ for (const { x, y } of level.neighbors(level.xOf(cell), level.yOf(cell))) {
21
+ if (!level.inside(x, y))
22
+ continue;
23
+ const neighbor = level.index(x, y);
24
+ if (seen.has(neighbor))
25
+ continue;
26
+ seen.add(neighbor);
27
+ next.push(neighbor);
28
+ }
29
+ }
30
+ frontier = next;
31
+ }
32
+ seen.delete(center);
33
+ return [...seen];
34
+ }
35
+ /**
36
+ * Picks `count` distinct cells out of `candidates` without replacement, falling back to
37
+ * however many exist when fewer are available rather than throwing or looping forever - a
38
+ * crowded region just gets fewer placements, the same "fail gracefully, place fewer" shape
39
+ * `generateDungeonGraph`'s own room placement already uses. Pure: nothing is placed or
40
+ * marked taken until the caller acts on `cells` itself (typically `FeatureLayer.place`, or
41
+ * folding `cells` into the next call's own `occupied` set). `trace` is plain, JSON-safe data
42
+ * a game can push straight into `DungeonArtifacts.content` for a parity check, or persist
43
+ * across save/load the same way any other roll trace does.
44
+ *
45
+ * Composes with `candidateCells` and `cellsNear` for the three shapes a regional generator
46
+ * needs: several neighbouring items (`cellsNear` around one anchor, intersected with a
47
+ * terrain/occupancy pool, then selected from), scattered decorations across a whole region
48
+ * (`candidateCells` with a large `within`, then selected from with a larger `count`), and a
49
+ * single branch or room reward (`candidateCells` scoped to one room, `count: 1`).
50
+ *
51
+ * @example
52
+ * ```ts
53
+ * import { candidateCells, cellsNear, selectDistinctCells } from '@datamoc/mw_games/roguelike';
54
+ *
55
+ * declare const level: import('@datamoc/mw_games/roguelike').Level;
56
+ * const FLOOR = new Set([1]);
57
+ *
58
+ * // scatter 3 decorations anywhere on the floor
59
+ * const pool = candidateCells(level, { terrain: FLOOR });
60
+ * const { cells: decorations, trace } = selectDistinctCells(pool, 3);
61
+ *
62
+ * // then release 2 more items clustered around one of those cells
63
+ * const nearby = cellsNear(level, decorations[0], 2).filter((c) => pool.includes(c));
64
+ * const { cells: cluster } = selectDistinctCells(nearby, 2);
65
+ * ```
66
+ */
67
+ export function selectDistinctCells(candidates, count) {
68
+ const pool = [...new Set(candidates)];
69
+ Random.shuffle(pool);
70
+ const cells = pool.slice(0, Math.max(0, count));
71
+ return { cells, trace: { requested: count, available: pool.length, selected: cells } };
72
+ }
73
+ function range(n) {
74
+ const out = new Array(n);
75
+ for (let i = 0; i < n; i++)
76
+ out[i] = i;
77
+ return out;
78
+ }
79
+ //# sourceMappingURL=Placement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Placement.js","sourceRoot":"","sources":["../../src/roguelike/Placement.ts"],"names":[],"mappings":"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"}
@@ -34,4 +34,6 @@ export type { StealthOptions } from './Stealth.ts';
34
34
  export { TriggerTracker } from './TriggerTracker.ts';
35
35
  export { MultiStageAbility } from './MultiStageAbility.ts';
36
36
  export type { AbilityStage } from './MultiStageAbility.ts';
37
+ export { candidateCells, cellsNear, selectDistinctCells } from './Placement.ts';
38
+ export type { PlacementFilter, PlacementResult, PlacementTraceEntry } from './Placement.ts';
37
39
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/roguelike/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1E,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEhE,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACjH,YAAY,EAAE,cAAc,EAAE,sBAAsB,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAErG,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC/E,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE/G,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC/E,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEhG,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC/D,YAAY,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAE/D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAEzF,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACtG,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAChH,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAErD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE1E,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/roguelike/index.ts"],"names":[],"mappings":"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"}
@@ -19,4 +19,5 @@ export { CombatHooks } from './Combat.js';
19
19
  export { Stealth } from './Stealth.js';
20
20
  export { TriggerTracker } from './TriggerTracker.js';
21
21
  export { MultiStageAbility } from './MultiStageAbility.js';
22
+ export { candidateCells, cellsNear, selectDistinctCells } from './Placement.js';
22
23
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/roguelike/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1E,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGjH,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAG/E,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAG7C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG/E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAG/D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGjD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAEtG,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAGhH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAErD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/roguelike/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1E,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGjH,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAG/E,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAG7C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG/E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAG/D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGjD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAEtG,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAGhH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAErD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAG3D,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import '@babylonjs/loaders/glTF/index.js';
2
- import type { ImportMeshOptions, ISceneLoaderAsyncResult } from '@babylonjs/core/Loading/sceneLoader.js';
2
+ import type { ImportMeshOptions, ISceneLoaderAsyncResult, LoadAssetContainerOptions } from '@babylonjs/core/Loading/sceneLoader.js';
3
+ import type { AssetContainer } from '@babylonjs/core/assetContainer.js';
3
4
  import type { Scene } from '@babylonjs/core/scene.js';
4
5
  export type ModelSource3D = string | File | ArrayBufferView;
5
6
  /**
@@ -7,6 +8,42 @@ export type ModelSource3D = string | File | ArrayBufferView;
7
8
  * asset path is resolved through `mwg/assets` first, the same way every other loader in the
8
9
  * framework becomes `file://`-safe once assets are compiled to `data:` URIs; a URI that is
9
10
  * already resolved is passed through unchanged.
11
+ *
12
+ * For a single copy of a model this is the whole job; for several copies of the *same*
13
+ * model, `loadModelContainer3D` fetches and parses once and instantiates independent copies
14
+ * from it - calling this a second time for the same source imports and parses it again.
10
15
  */
11
16
  export declare function loadModel3D(source: ModelSource3D, scene: Scene, options?: ImportMeshOptions): Promise<ISceneLoaderAsyncResult>;
17
+ /**
18
+ * Loads a model once per resolved source and caches the in-flight/loaded `AssetContainer`,
19
+ * so a second call for the same source returns the same container instead of importing and
20
+ * parsing it again over the network. A container is not itself scene content - call
21
+ * `container.instantiateModelsToScene()` for each independent copy a game wants to place,
22
+ * which is Babylon's own way to get several unaliased instances of one loaded model without
23
+ * a second fetch; `loadModel3D` imports straight into the scene instead, for the common case
24
+ * of only ever wanting one copy.
25
+ *
26
+ * Only caches when `source` is a string (an asset path or already-resolved URI) - a `File`
27
+ * or in-memory byte view has no stable identity to key a cache on, so those always load
28
+ * fresh, the same way `loadModel3D` never tries to resolve them as a path either.
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * import { loadModelContainer3D, isModelContainerLoaded, releaseModelContainer } from '@datamoc/mw_games/3d/models';
33
+ *
34
+ * declare const scene: import('@babylonjs/core/scene.js').Scene;
35
+ *
36
+ * const container = await loadModelContainer3D('models/tree.glb', scene);
37
+ * const treeA = container.instantiateModelsToScene();
38
+ * const treeB = container.instantiateModelsToScene(); // a second, independent copy - no re-fetch
39
+ *
40
+ * console.log(isModelContainerLoaded('models/tree.glb')); // true
41
+ * releaseModelContainer('models/tree.glb'); // frees the container once every copy is placed
42
+ * ```
43
+ */
44
+ export declare function loadModelContainer3D(source: ModelSource3D, scene: Scene, options?: LoadAssetContainerOptions): Promise<AssetContainer>;
45
+ /** true once `loadModelContainer3D` has resolved for this source and it has not since been `releaseModelContainer`d */
46
+ export declare function isModelContainerLoaded(source: string): boolean;
47
+ /** disposes and forgets a cached container; a source never loaded (or already released) is silently skipped */
48
+ export declare function releaseModelContainer(source: string): Promise<void>;
12
49
  //# sourceMappingURL=Models.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Models.d.ts","sourceRoot":"","sources":["../../src/three-d/Models.ts"],"names":[],"mappings":"AAAA,OAAO,kCAAkC,CAAC;AAE1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACzG,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAItD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,IAAI,GAAG,eAAe,CAAC;AAE5D;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAG9H"}
1
+ {"version":3,"file":"Models.d.ts","sourceRoot":"","sources":["../../src/three-d/Models.ts"],"names":[],"mappings":"AAAA,OAAO,kCAAkC,CAAC;AAE1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AACpI,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAItD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,IAAI,GAAG,eAAe,CAAC;AAM5D;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAE9H;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,OAAO,CAAC,cAAc,CAAC,CAYtI;AAED,uHAAuH;AACvH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAG9D;AAED,+GAA+G;AAC/G,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQzE"}
@@ -1,14 +1,77 @@
1
1
  import '@babylonjs/loaders/glTF/index.js';
2
- import { ImportMeshAsync } from '@babylonjs/core/Loading/sceneLoader.js';
2
+ import { ImportMeshAsync, LoadAssetContainerAsync } from '@babylonjs/core/Loading/sceneLoader.js';
3
3
  import { resolve } from '../assets/paths.js';
4
+ function resolveSource(source) {
5
+ return typeof source === 'string' && !/^(?:data|blob|https?):/i.test(source) ? resolve(source) : source;
6
+ }
4
7
  /**
5
8
  * Loads glTF/GLB from an asset path, data/blob/http(s) URI, File, or in-memory byte view. An
6
9
  * asset path is resolved through `mwg/assets` first, the same way every other loader in the
7
10
  * framework becomes `file://`-safe once assets are compiled to `data:` URIs; a URI that is
8
11
  * already resolved is passed through unchanged.
12
+ *
13
+ * For a single copy of a model this is the whole job; for several copies of the *same*
14
+ * model, `loadModelContainer3D` fetches and parses once and instantiates independent copies
15
+ * from it - calling this a second time for the same source imports and parses it again.
9
16
  */
10
17
  export function loadModel3D(source, scene, options) {
11
- const resolved = typeof source === 'string' && !/^(?:data|blob|https?):/i.test(source) ? resolve(source) : source;
12
- return ImportMeshAsync(resolved, scene, options);
18
+ return ImportMeshAsync(resolveSource(source), scene, options);
19
+ }
20
+ const containerCache = new Map();
21
+ /**
22
+ * Loads a model once per resolved source and caches the in-flight/loaded `AssetContainer`,
23
+ * so a second call for the same source returns the same container instead of importing and
24
+ * parsing it again over the network. A container is not itself scene content - call
25
+ * `container.instantiateModelsToScene()` for each independent copy a game wants to place,
26
+ * which is Babylon's own way to get several unaliased instances of one loaded model without
27
+ * a second fetch; `loadModel3D` imports straight into the scene instead, for the common case
28
+ * of only ever wanting one copy.
29
+ *
30
+ * Only caches when `source` is a string (an asset path or already-resolved URI) - a `File`
31
+ * or in-memory byte view has no stable identity to key a cache on, so those always load
32
+ * fresh, the same way `loadModel3D` never tries to resolve them as a path either.
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * import { loadModelContainer3D, isModelContainerLoaded, releaseModelContainer } from '@datamoc/mw_games/3d/models';
37
+ *
38
+ * declare const scene: import('@babylonjs/core/scene.js').Scene;
39
+ *
40
+ * const container = await loadModelContainer3D('models/tree.glb', scene);
41
+ * const treeA = container.instantiateModelsToScene();
42
+ * const treeB = container.instantiateModelsToScene(); // a second, independent copy - no re-fetch
43
+ *
44
+ * console.log(isModelContainerLoaded('models/tree.glb')); // true
45
+ * releaseModelContainer('models/tree.glb'); // frees the container once every copy is placed
46
+ * ```
47
+ */
48
+ export function loadModelContainer3D(source, scene, options) {
49
+ const resolved = resolveSource(source);
50
+ if (typeof resolved !== 'string')
51
+ return LoadAssetContainerAsync(resolved, scene, options);
52
+ const cached = containerCache.get(resolved);
53
+ if (cached)
54
+ return cached;
55
+ const promise = LoadAssetContainerAsync(resolved, scene, options);
56
+ containerCache.set(resolved, promise);
57
+ //a rejected load must not poison the cache - the next call gets a fresh attempt
58
+ promise.catch(() => containerCache.delete(resolved));
59
+ return promise;
60
+ }
61
+ /** true once `loadModelContainer3D` has resolved for this source and it has not since been `releaseModelContainer`d */
62
+ export function isModelContainerLoaded(source) {
63
+ const resolved = resolveSource(source);
64
+ return typeof resolved === 'string' && containerCache.has(resolved);
65
+ }
66
+ /** disposes and forgets a cached container; a source never loaded (or already released) is silently skipped */
67
+ export async function releaseModelContainer(source) {
68
+ const resolved = resolveSource(source);
69
+ if (typeof resolved !== 'string')
70
+ return;
71
+ const cached = containerCache.get(resolved);
72
+ if (!cached)
73
+ return;
74
+ containerCache.delete(resolved);
75
+ (await cached).dispose();
13
76
  }
14
77
  //# sourceMappingURL=Models.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Models.js","sourceRoot":"","sources":["../../src/three-d/Models.ts"],"names":[],"mappings":"AAAA,OAAO,kCAAkC,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAC;AAIzE,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAI7C;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,MAAqB,EAAE,KAAY,EAAE,OAA2B;IAC3F,MAAM,QAAQ,GAAG,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAClH,OAAO,eAAe,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC"}
1
+ {"version":3,"file":"Models.js","sourceRoot":"","sources":["../../src/three-d/Models.ts"],"names":[],"mappings":"AAAA,OAAO,kCAAkC,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AAKlG,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAI7C,SAAS,aAAa,CAAC,MAAqB;IAC3C,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AACzG,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CAAC,MAAqB,EAAE,KAAY,EAAE,OAA2B;IAC3F,OAAO,eAAe,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,cAAc,GAAG,IAAI,GAAG,EAAmC,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAqB,EAAE,KAAY,EAAE,OAAmC;IAC5G,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACvC,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,uBAAuB,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAE3F,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC5C,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,MAAM,OAAO,GAAG,uBAAuB,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAClE,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACtC,gFAAgF;IAChF,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IACrD,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,uHAAuH;AACvH,MAAM,UAAU,sBAAsB,CAAC,MAAc;IACpD,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACvC,OAAO,OAAO,QAAQ,KAAK,QAAQ,IAAI,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACrE,CAAC;AAED,+GAA+G;AAC/G,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,MAAc;IACzD,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACvC,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO;IAEzC,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM;QAAE,OAAO;IACpB,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC,MAAM,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC;AAC1B,CAAC"}
@@ -1,6 +1,17 @@
1
1
  import type { AnimatedSprite } from './AnimatedSprite.ts';
2
2
  /** the three states any character's animation ever needs to be in */
3
3
  export type ActorAnimationState = 'idle' | 'move' | 'action';
4
+ /**
5
+ * @example
6
+ * ```ts
7
+ * import type { ActorAnimatorOptions } from '@datamoc/mw_games/two-d/render';
8
+ *
9
+ * const options: ActorAnimatorOptions = {
10
+ * animationName: (state, facing) => `${state}-${facing}`,
11
+ * variant: 'down',
12
+ * };
13
+ * ```
14
+ */
4
15
  export interface ActorAnimatorOptions {
5
16
  /**
6
17
  * Names a state's animation, given whatever varies it - a facing direction for a grid
@@ -30,6 +41,27 @@ export interface ActorAnimatorOptions {
30
41
  *
31
42
  * This owns the sprite's `onFinish` hook entirely; a game driving one through
32
43
  * `ActorAnimator` should not also set `onFinish` itself.
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * import { ActorAnimator, AnimatedSprite, SpriteSheet } from '@datamoc/mw_games/two-d/render';
48
+ *
49
+ * declare const sheet: SpriteSheet;
50
+ *
51
+ * const hero = new AnimatedSprite();
52
+ * hero.add('idle-down', sheet.pick(0), { fps: 2 });
53
+ * hero.add('move-down', sheet.range(1, 4), { fps: 10 });
54
+ * hero.add('action-down', sheet.range(5, 7), { fps: 12, loop: false });
55
+ *
56
+ * const animator = new ActorAnimator(hero, {
57
+ * animationName: (state, facing) => `${state}-${facing}`,
58
+ * variant: 'down',
59
+ * });
60
+ *
61
+ * animator.setMoving(true); // walk cycle starts
62
+ * animator.playAction(); // an attack swing cuts in over the walk cycle
63
+ * console.log(animator.state); // 'action' - overrides idle/move while it plays
64
+ * ```
33
65
  */
34
66
  export declare class ActorAnimator {
35
67
  private sprite;
@@ -1 +1 @@
1
- {"version":3,"file":"ActorAnimator.d.ts","sourceRoot":"","sources":["../../../src/two-d/render/ActorAnimator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,qEAAqE;AACrE,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE7D,MAAM,WAAW,oBAAoB;IACpC;;;;;;OAMG;IACH,aAAa,EAAE,CAAC,KAAK,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IAEvE,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,aAAa;IACzB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,aAAa,CAA0D;IAE/E,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,QAAQ,CAAS;IAEzB,YAAY,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,oBAAoB,EAOhE;IAED,2FAA2F;IAC3F,IAAI,KAAK,IAAI,mBAAmB,CAE/B;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IAED;;;OAGG;IACH,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAIjD;IAED;;;;;;OAMG;IACH,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,UAAQ,GAAG,IAAI,CAMlD;IAED,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,KAAK;CAIb"}
1
+ {"version":3,"file":"ActorAnimator.d.ts","sourceRoot":"","sources":["../../../src/two-d/render/ActorAnimator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,qEAAqE;AACrE,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE7D;;;;;;;;;;GAUG;AACH,MAAM,WAAW,oBAAoB;IACpC;;;;;;OAMG;IACH,aAAa,EAAE,CAAC,KAAK,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IAEvE,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,qBAAa,aAAa;IACzB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,aAAa,CAA0D;IAE/E,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,QAAQ,CAAS;IAEzB,YAAY,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,oBAAoB,EAOhE;IAED,2FAA2F;IAC3F,IAAI,KAAK,IAAI,mBAAmB,CAE/B;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IAED;;;OAGG;IACH,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAIjD;IAED;;;;;;OAMG;IACH,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,UAAQ,GAAG,IAAI,CAMlD;IAED,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,KAAK;CAIb"}
@@ -15,6 +15,27 @@
15
15
  *
16
16
  * This owns the sprite's `onFinish` hook entirely; a game driving one through
17
17
  * `ActorAnimator` should not also set `onFinish` itself.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * import { ActorAnimator, AnimatedSprite, SpriteSheet } from '@datamoc/mw_games/two-d/render';
22
+ *
23
+ * declare const sheet: SpriteSheet;
24
+ *
25
+ * const hero = new AnimatedSprite();
26
+ * hero.add('idle-down', sheet.pick(0), { fps: 2 });
27
+ * hero.add('move-down', sheet.range(1, 4), { fps: 10 });
28
+ * hero.add('action-down', sheet.range(5, 7), { fps: 12, loop: false });
29
+ *
30
+ * const animator = new ActorAnimator(hero, {
31
+ * animationName: (state, facing) => `${state}-${facing}`,
32
+ * variant: 'down',
33
+ * });
34
+ *
35
+ * animator.setMoving(true); // walk cycle starts
36
+ * animator.playAction(); // an attack swing cuts in over the walk cycle
37
+ * console.log(animator.state); // 'action' - overrides idle/move while it plays
38
+ * ```
18
39
  */
19
40
  export class ActorAnimator {
20
41
  constructor(sprite, options) {
@@ -1 +1 @@
1
- {"version":3,"file":"ActorAnimator.js","sourceRoot":"","sources":["../../../src/two-d/render/ActorAnimator.ts"],"names":[],"mappings":"AAmBA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAO,aAAa;IAQzB,YAAY,MAAsB,EAAE,OAA6B;QAHzD,eAAU,GAAoB,MAAM,CAAC;QACrC,aAAQ,GAAG,KAAK,CAAC;QAGxB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;QAC3C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;QAErC,IAAI,CAAC,MAAM,CAAC,QAAQ,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;QACnD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC7B,CAAC;IAED,2FAA2F;IAC3F,IAAI,KAAK;QACR,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;IACnD,CAAC;IAED,IAAI,WAAW;QACd,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED;;;OAGG;IACH,SAAS,CAAC,MAAe,EAAE,OAAgB;QAC1C,IAAI,OAAO,KAAK,SAAS;YAAE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QAClD,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;QAC3C,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACjD,CAAC;IAED;;;;;;OAMG;IACH,UAAU,CAAC,OAAgB,EAAE,OAAO,GAAG,KAAK;QAC3C,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC,OAAO;YAAE,OAAO;QACtC,IAAI,OAAO,KAAK,SAAS;YAAE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QAElD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACtB,CAAC;IAEO,cAAc;QACrB,gFAAgF;QAChF,iFAAiF;QACjF,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO;QAE3B,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC7B,CAAC;IAEO,KAAK,CAAC,KAA0B;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACrD,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,KAAK,QAAQ,CAAC,CAAC;IACvE,CAAC;CACD"}
1
+ {"version":3,"file":"ActorAnimator.js","sourceRoot":"","sources":["../../../src/two-d/render/ActorAnimator.ts"],"names":[],"mappings":"AA8BA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,OAAO,aAAa;IAQzB,YAAY,MAAsB,EAAE,OAA6B;QAHzD,eAAU,GAAoB,MAAM,CAAC;QACrC,aAAQ,GAAG,KAAK,CAAC;QAGxB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;QAC3C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;QAErC,IAAI,CAAC,MAAM,CAAC,QAAQ,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;QACnD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC7B,CAAC;IAED,2FAA2F;IAC3F,IAAI,KAAK;QACR,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;IACnD,CAAC;IAED,IAAI,WAAW;QACd,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED;;;OAGG;IACH,SAAS,CAAC,MAAe,EAAE,OAAgB;QAC1C,IAAI,OAAO,KAAK,SAAS;YAAE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QAClD,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;QAC3C,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACjD,CAAC;IAED;;;;;;OAMG;IACH,UAAU,CAAC,OAAgB,EAAE,OAAO,GAAG,KAAK;QAC3C,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC,OAAO;YAAE,OAAO;QACtC,IAAI,OAAO,KAAK,SAAS;YAAE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QAElD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACtB,CAAC;IAEO,cAAc;QACrB,gFAAgF;QAChF,iFAAiF;QACjF,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO;QAE3B,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC7B,CAAC;IAEO,KAAK,CAAC,KAA0B;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACrD,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,KAAK,QAAQ,CAAC,CAAC;IACvE,CAAC;CACD"}
@@ -6,6 +6,18 @@ export interface AnimationOptions {
6
6
  /** whether to start again at the end, or hold on the last frame */
7
7
  loop?: boolean;
8
8
  }
9
+ /**
10
+ * @example
11
+ * ```ts
12
+ * import { Animation } from '@datamoc/mw_games/two-d/render';
13
+ * import type { Texture2D } from '@datamoc/mw_games/two-d/render';
14
+ *
15
+ * declare const frames: Texture2D[];
16
+ *
17
+ * const walk = new Animation(frames, { fps: 10 });
18
+ * console.log(walk.duration); // frames.length / 10, in seconds
19
+ * ```
20
+ */
9
21
  export declare class Animation {
10
22
  readonly frames: readonly Texture2D[];
11
23
  readonly frameDuration: number;
@@ -17,18 +29,26 @@ export declare class Animation {
17
29
  * A sprite that plays named animations, and can still be tinted.
18
30
  *
19
31
  * Animations are registered once and played by name, which is how a character ends up
20
- * reading as `hero.play('walk')` rather than juggling frame arrays:
32
+ * reading as `hero.play('walk')` rather than juggling frame arrays.
21
33
  *
34
+ * Nothing advances on its own: call `update(dt)` from the scene, or add the sprite to a
35
+ * `SpriteGroup`, so that pausing the game pauses the animations with it.
36
+ *
37
+ * @example
22
38
  * ```ts
39
+ * import { AnimatedSprite, SpriteSheet } from '@datamoc/mw_games/two-d/render';
40
+ *
41
+ * declare const sheet: SpriteSheet;
42
+ *
23
43
  * const hero = new AnimatedSprite();
24
44
  * hero.add('idle', sheet.pick(0, 0, 0, 1), { fps: 2 });
25
45
  * hero.add('walk', sheet.range(6, 10), { fps: 10 });
26
46
  * hero.add('die', sheet.range(11, 14), { fps: 10, loop: false });
27
47
  * hero.play('idle');
28
- * ```
29
48
  *
30
- * Nothing advances on its own: call `update(dt)` from the scene, or add the sprite to a
31
- * `SpriteGroup`, so that pausing the game pauses the animations with it.
49
+ * hero.onFinish = (name) => console.log(`${name} finished`);
50
+ * hero.update(1 / 60); // advance one frame's worth of time
51
+ * ```
32
52
  */
33
53
  export declare class AnimatedSprite extends TintedSprite {
34
54
  private animations;
@@ -1 +1 @@
1
- {"version":3,"file":"AnimatedSprite.d.ts","sourceRoot":"","sources":["../../../src/two-d/render/AnimatedSprite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,WAAW,gBAAgB;IAChC,wBAAwB;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,mEAAmE;IACnE,IAAI,CAAC,EAAE,OAAO,CAAC;CACf;AAED,qBAAa,SAAS;IACrB,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAEvB,YAAY,MAAM,EAAE,SAAS,SAAS,EAAE,EAAE,EAAE,GAAQ,EAAE,IAAW,EAAE,GAAE,gBAAqB,EAKzF;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;CACD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,cAAe,SAAQ,YAAY;IAC/C,OAAO,CAAC,UAAU,CAAgC;IAElD,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,QAAQ,CAAS;IAEzB,qEAAqE;IACrE,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAEjD,MAAM,UAAS;IAEf,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,SAAS,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAGhF;IAED,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzB;IAED,IAAI,OAAO,IAAI,MAAM,GAAG,IAAI,CAE3B;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED;;;;;OAKG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,UAAQ,GAAG,IAAI,CAcxC;IAED,IAAI,IAAI,IAAI,CAGX;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAuBvB;CACD"}
1
+ {"version":3,"file":"AnimatedSprite.d.ts","sourceRoot":"","sources":["../../../src/two-d/render/AnimatedSprite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,WAAW,gBAAgB;IAChC,wBAAwB;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,mEAAmE;IACnE,IAAI,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,SAAS;IACrB,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAEvB,YAAY,MAAM,EAAE,SAAS,SAAS,EAAE,EAAE,EAAE,GAAQ,EAAE,IAAW,EAAE,GAAE,gBAAqB,EAKzF;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;CACD;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,cAAe,SAAQ,YAAY;IAC/C,OAAO,CAAC,UAAU,CAAgC;IAElD,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,QAAQ,CAAS;IAEzB,qEAAqE;IACrE,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAEjD,MAAM,UAAS;IAEf,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,SAAS,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAGhF;IAED,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzB;IAED,IAAI,OAAO,IAAI,MAAM,GAAG,IAAI,CAE3B;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED;;;;;OAKG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,UAAQ,GAAG,IAAI,CAcxC;IAED,IAAI,IAAI,IAAI,CAGX;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAuBvB;CACD"}
@@ -1,4 +1,16 @@
1
1
  import { TintedSprite } from './TintedSprite.js';
2
+ /**
3
+ * @example
4
+ * ```ts
5
+ * import { Animation } from '@datamoc/mw_games/two-d/render';
6
+ * import type { Texture2D } from '@datamoc/mw_games/two-d/render';
7
+ *
8
+ * declare const frames: Texture2D[];
9
+ *
10
+ * const walk = new Animation(frames, { fps: 10 });
11
+ * console.log(walk.duration); // frames.length / 10, in seconds
12
+ * ```
13
+ */
2
14
  export class Animation {
3
15
  constructor(frames, { fps = 10, loop = true } = {}) {
4
16
  if (frames.length === 0)
@@ -15,18 +27,26 @@ export class Animation {
15
27
  * A sprite that plays named animations, and can still be tinted.
16
28
  *
17
29
  * Animations are registered once and played by name, which is how a character ends up
18
- * reading as `hero.play('walk')` rather than juggling frame arrays:
30
+ * reading as `hero.play('walk')` rather than juggling frame arrays.
19
31
  *
32
+ * Nothing advances on its own: call `update(dt)` from the scene, or add the sprite to a
33
+ * `SpriteGroup`, so that pausing the game pauses the animations with it.
34
+ *
35
+ * @example
20
36
  * ```ts
37
+ * import { AnimatedSprite, SpriteSheet } from '@datamoc/mw_games/two-d/render';
38
+ *
39
+ * declare const sheet: SpriteSheet;
40
+ *
21
41
  * const hero = new AnimatedSprite();
22
42
  * hero.add('idle', sheet.pick(0, 0, 0, 1), { fps: 2 });
23
43
  * hero.add('walk', sheet.range(6, 10), { fps: 10 });
24
44
  * hero.add('die', sheet.range(11, 14), { fps: 10, loop: false });
25
45
  * hero.play('idle');
26
- * ```
27
46
  *
28
- * Nothing advances on its own: call `update(dt)` from the scene, or add the sprite to a
29
- * `SpriteGroup`, so that pausing the game pauses the animations with it.
47
+ * hero.onFinish = (name) => console.log(`${name} finished`);
48
+ * hero.update(1 / 60); // advance one frame's worth of time
49
+ * ```
30
50
  */
31
51
  export class AnimatedSprite extends TintedSprite {
32
52
  constructor() {
@@ -1 +1 @@
1
- {"version":3,"file":"AnimatedSprite.js","sourceRoot":"","sources":["../../../src/two-d/render/AnimatedSprite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAWjD,MAAM,OAAO,SAAS;IAKrB,YAAY,MAA4B,EAAE,EAAE,GAAG,GAAG,EAAE,EAAE,IAAI,GAAG,IAAI,EAAE,GAAqB,EAAE;QACzF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAClF,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,aAAa,GAAG,CAAC,GAAG,GAAG,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IAClB,CAAC;IAED,IAAI,QAAQ;QACX,OAAO,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IAChD,CAAC;CACD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,cAAe,SAAQ,YAAY;IAAhD;;QACS,eAAU,GAAG,IAAI,GAAG,EAAqB,CAAC;QAE1C,YAAO,GAAqB,IAAI,CAAC;QACjC,gBAAW,GAAkB,IAAI,CAAC;QAClC,eAAU,GAAG,CAAC,CAAC;QACf,UAAK,GAAG,CAAC,CAAC;QACV,aAAQ,GAAG,KAAK,CAAC;QAEzB,qEAAqE;QACrE,aAAQ,GAAoC,IAAI,CAAC;QAEjD,WAAM,GAAG,KAAK,CAAC;IAsEhB,CAAC;IApEA,GAAG,CAAC,IAAY,EAAE,MAA4B,EAAE,OAA0B;QACzE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC;IACb,CAAC;IAED,GAAG,CAAC,IAAY;QACf,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,OAAO;QACV,OAAO,IAAI,CAAC,WAAW,CAAC;IACzB,CAAC;IAED,IAAI,UAAU;QACb,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAED;;;;;OAKG;IACH,IAAI,CAAC,IAAY,EAAE,OAAO,GAAG,KAAK;QACjC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QAEzE,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,kBAAkB,CAAC,CAAC;QAE/E,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;QACzB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;QACf,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAEnC,OAAO,IAAI,CAAC;IACb,CAAC;IAED,IAAI;QACH,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IACzB,CAAC;IAED,MAAM,CAAC,EAAU;QAChB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEvD,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QAEjB,iFAAiF;QACjF,iEAAiE;QACjE,OAAO,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC,aAAa,EAAE,CAAC;YAC9C,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC,aAAa,CAAC;YAEtC,IAAI,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACnD,IAAI,CAAC,UAAU,EAAE,CAAC;YACnB,CAAC;iBAAM,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC;gBAC3B,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;YACrB,CAAC;iBAAM,CAAC;gBACP,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACrB,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,WAAY,CAAC,CAAC;gBACnC,MAAM;YACP,CAAC;QACF,CAAC;QAED,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAClD,CAAC;CACD"}
1
+ {"version":3,"file":"AnimatedSprite.js","sourceRoot":"","sources":["../../../src/two-d/render/AnimatedSprite.ts"],"names":[],"mappings":"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"}
@@ -24,9 +24,30 @@ export interface NeighborMask {
24
24
  * different engine's autotile layout will need its frames reordered into this one. What is
25
25
  * guaranteed: `BLOB_SHAPES` lists all 47 shapes in the exact order `blobIndex` returns them
26
26
  * in, so a tool (or a person, reading it once) can draw or arrange frames against it directly.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * import { BLOB_SHAPES } from '@datamoc/mw_games/two-d/render';
31
+ *
32
+ * console.log(BLOB_SHAPES.length); // 47
33
+ * console.log(BLOB_SHAPES[0]); // { n: false, e: false, s: false, w: false, ne: false, se: false, sw: false, nw: false }
34
+ * ```
27
35
  */
28
36
  export declare const BLOB_SHAPES: readonly NeighborMask[];
29
- /** the blob index (0 to 46) for one cell's 8-neighbour membership test */
37
+ /**
38
+ * the blob index (0 to 46) for one cell's 8-neighbour membership test
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * import { blobIndex } from '@datamoc/mw_games/two-d/render';
43
+ *
44
+ * const surroundedOnAllSides = blobIndex({
45
+ * n: true, e: true, s: true, w: true,
46
+ * ne: true, se: true, sw: true, nw: true,
47
+ * });
48
+ * console.log(surroundedOnAllSides); // 46 - the fully-interior shape
49
+ * ```
50
+ */
30
51
  export declare function blobIndex(neighbors: NeighborMask): number;
31
52
  /**
32
53
  * One frame per cell of a terrain, autotiled from a same-terrain test alone.
@@ -37,6 +58,17 @@ export declare function blobIndex(neighbors: NeighborMask): number;
37
58
  * @param frames the 47 frames a `blobIndex` of 0 to 46 selects between, drawn (or arranged)
38
59
  * against `BLOB_SHAPES`
39
60
  * @returns one frame index per cell, row-major, `EMPTY` wherever `sameTerrain` is false
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * import { autotileFrames, BLOB_SHAPES } from '@datamoc/mw_games/two-d/render';
65
+ *
66
+ * const water = new Set([0, 1, 10, 11]); // a 2x2 pond in a wider grid
67
+ * const frames = Array.from({ length: BLOB_SHAPES.length }, (_, index) => index); // frame N = shape N
68
+ *
69
+ * const cellFrames = autotileFrames(10, 10, (x, y) => water.has(y * 10 + x), frames);
70
+ * console.log(cellFrames[0]); // the blob frame for the pond's top-left corner
71
+ * ```
40
72
  */
41
73
  export declare function autotileFrames(width: number, height: number, sameTerrain: (x: number, y: number) => boolean, frames: readonly number[]): Int32Array;
42
74
  //# sourceMappingURL=Autotile.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Autotile.d.ts","sourceRoot":"","sources":["../../../src/two-d/render/Autotile.ts"],"names":[],"mappings":"AAEA,yFAAyF;AACzF,MAAM,WAAW,YAAY;IAC5B,CAAC,EAAE,OAAO,CAAC;IACX,CAAC,EAAE,OAAO,CAAC;IACX,CAAC,EAAE,OAAO,CAAC;IACX,CAAC,EAAE,OAAO,CAAC;IACX,EAAE,EAAE,OAAO,CAAC;IACZ,EAAE,EAAE,OAAO,CAAC;IACZ,EAAE,EAAE,OAAO,CAAC;IACZ,EAAE,EAAE,OAAO,CAAC;CACZ;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,WAAW,EAAE,SAAS,YAAY,EAAsB,CAAC;AAoEtE,0EAA0E;AAC1E,wBAAgB,SAAS,CAAC,SAAS,EAAE,YAAY,GAAG,MAAM,CAEzD;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC7B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,EAC9C,MAAM,EAAE,SAAS,MAAM,EAAE,GACvB,UAAU,CA+BZ"}
1
+ {"version":3,"file":"Autotile.d.ts","sourceRoot":"","sources":["../../../src/two-d/render/Autotile.ts"],"names":[],"mappings":"AAEA,yFAAyF;AACzF,MAAM,WAAW,YAAY;IAC5B,CAAC,EAAE,OAAO,CAAC;IACX,CAAC,EAAE,OAAO,CAAC;IACX,CAAC,EAAE,OAAO,CAAC;IACX,CAAC,EAAE,OAAO,CAAC;IACX,EAAE,EAAE,OAAO,CAAC;IACZ,EAAE,EAAE,OAAO,CAAC;IACZ,EAAE,EAAE,OAAO,CAAC;IACZ,EAAE,EAAE,OAAO,CAAC;CACZ;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,WAAW,EAAE,SAAS,YAAY,EAAsB,CAAC;AAoEtE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,YAAY,GAAG,MAAM,CAEzD;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,cAAc,CAC7B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,EAC9C,MAAM,EAAE,SAAS,MAAM,EAAE,GACvB,UAAU,CA+BZ"}