@sadhaka/loom-engine 0.10.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 (219) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +344 -0
  3. package/dist/animation/animation-clip.d.ts +12 -0
  4. package/dist/animation/animation-clip.d.ts.map +1 -0
  5. package/dist/animation/animation-clip.js +85 -0
  6. package/dist/animation/animation-clip.js.map +1 -0
  7. package/dist/animation/animation-state-pool.d.ts +25 -0
  8. package/dist/animation/animation-state-pool.d.ts.map +1 -0
  9. package/dist/animation/animation-state-pool.js +113 -0
  10. package/dist/animation/animation-state-pool.js.map +1 -0
  11. package/dist/asset/sprite-sheet-loader.d.ts +41 -0
  12. package/dist/asset/sprite-sheet-loader.d.ts.map +1 -0
  13. package/dist/asset/sprite-sheet-loader.js +313 -0
  14. package/dist/asset/sprite-sheet-loader.js.map +1 -0
  15. package/dist/audio/audio-bus.d.ts +43 -0
  16. package/dist/audio/audio-bus.d.ts.map +1 -0
  17. package/dist/audio/audio-bus.js +258 -0
  18. package/dist/audio/audio-bus.js.map +1 -0
  19. package/dist/combat/mob-catalog.d.ts +29 -0
  20. package/dist/combat/mob-catalog.d.ts.map +1 -0
  21. package/dist/combat/mob-catalog.js +104 -0
  22. package/dist/combat/mob-catalog.js.map +1 -0
  23. package/dist/components/health.d.ts +28 -0
  24. package/dist/components/health.d.ts.map +1 -0
  25. package/dist/components/health.js +150 -0
  26. package/dist/components/health.js.map +1 -0
  27. package/dist/components/interactable.d.ts +30 -0
  28. package/dist/components/interactable.d.ts.map +1 -0
  29. package/dist/components/interactable.js +94 -0
  30. package/dist/components/interactable.js.map +1 -0
  31. package/dist/components/particle-emitter.d.ts +62 -0
  32. package/dist/components/particle-emitter.d.ts.map +1 -0
  33. package/dist/components/particle-emitter.js +193 -0
  34. package/dist/components/particle-emitter.js.map +1 -0
  35. package/dist/components/pursue.d.ts +23 -0
  36. package/dist/components/pursue.d.ts.map +1 -0
  37. package/dist/components/pursue.js +96 -0
  38. package/dist/components/pursue.js.map +1 -0
  39. package/dist/components/ranged-attack.d.ts +44 -0
  40. package/dist/components/ranged-attack.d.ts.map +1 -0
  41. package/dist/components/ranged-attack.js +120 -0
  42. package/dist/components/ranged-attack.js.map +1 -0
  43. package/dist/components/sprite.d.ts +27 -0
  44. package/dist/components/sprite.d.ts.map +1 -0
  45. package/dist/components/sprite.js +122 -0
  46. package/dist/components/sprite.js.map +1 -0
  47. package/dist/components/transform.d.ts +30 -0
  48. package/dist/components/transform.d.ts.map +1 -0
  49. package/dist/components/transform.js +150 -0
  50. package/dist/components/transform.js.map +1 -0
  51. package/dist/director/director-bridge.d.ts +22 -0
  52. package/dist/director/director-bridge.d.ts.map +1 -0
  53. package/dist/director/director-bridge.js +23 -0
  54. package/dist/director/director-bridge.js.map +1 -0
  55. package/dist/director/director-encounter-system.d.ts +21 -0
  56. package/dist/director/director-encounter-system.d.ts.map +1 -0
  57. package/dist/director/director-encounter-system.js +128 -0
  58. package/dist/director/director-encounter-system.js.map +1 -0
  59. package/dist/director/director-system.d.ts +19 -0
  60. package/dist/director/director-system.d.ts.map +1 -0
  61. package/dist/director/director-system.js +179 -0
  62. package/dist/director/director-system.js.map +1 -0
  63. package/dist/director/event-envelope.d.ts +144 -0
  64. package/dist/director/event-envelope.d.ts.map +1 -0
  65. package/dist/director/event-envelope.js +108 -0
  66. package/dist/director/event-envelope.js.map +1 -0
  67. package/dist/director/knot-context-resource.d.ts +25 -0
  68. package/dist/director/knot-context-resource.d.ts.map +1 -0
  69. package/dist/director/knot-context-resource.js +152 -0
  70. package/dist/director/knot-context-resource.js.map +1 -0
  71. package/dist/director/mock-director-bridge.d.ts +18 -0
  72. package/dist/director/mock-director-bridge.d.ts.map +1 -0
  73. package/dist/director/mock-director-bridge.js +75 -0
  74. package/dist/director/mock-director-bridge.js.map +1 -0
  75. package/dist/director/snapshot-recovery.d.ts +37 -0
  76. package/dist/director/snapshot-recovery.d.ts.map +1 -0
  77. package/dist/director/snapshot-recovery.js +180 -0
  78. package/dist/director/snapshot-recovery.js.map +1 -0
  79. package/dist/director/sse-director-bridge.d.ts +42 -0
  80. package/dist/director/sse-director-bridge.d.ts.map +1 -0
  81. package/dist/director/sse-director-bridge.js +280 -0
  82. package/dist/director/sse-director-bridge.js.map +1 -0
  83. package/dist/engine.d.ts +25 -0
  84. package/dist/engine.d.ts.map +1 -0
  85. package/dist/engine.js +166 -0
  86. package/dist/engine.js.map +1 -0
  87. package/dist/entity.d.ts +17 -0
  88. package/dist/entity.d.ts.map +1 -0
  89. package/dist/entity.js +77 -0
  90. package/dist/entity.js.map +1 -0
  91. package/dist/index.d.ts +85 -0
  92. package/dist/index.d.ts.map +1 -0
  93. package/dist/index.js +64 -0
  94. package/dist/index.js.map +1 -0
  95. package/dist/input/input-manager.d.ts +91 -0
  96. package/dist/input/input-manager.d.ts.map +1 -0
  97. package/dist/input/input-manager.js +349 -0
  98. package/dist/input/input-manager.js.map +1 -0
  99. package/dist/input/tap-to-walk.d.ts +27 -0
  100. package/dist/input/tap-to-walk.d.ts.map +1 -0
  101. package/dist/input/tap-to-walk.js +118 -0
  102. package/dist/input/tap-to-walk.js.map +1 -0
  103. package/dist/input/virtual-dpad.d.ts +34 -0
  104. package/dist/input/virtual-dpad.d.ts.map +1 -0
  105. package/dist/input/virtual-dpad.js +267 -0
  106. package/dist/input/virtual-dpad.js.map +1 -0
  107. package/dist/renderer/camera.d.ts +26 -0
  108. package/dist/renderer/camera.d.ts.map +1 -0
  109. package/dist/renderer/camera.js +39 -0
  110. package/dist/renderer/camera.js.map +1 -0
  111. package/dist/renderer/canvas2d-device.d.ts +26 -0
  112. package/dist/renderer/canvas2d-device.d.ts.map +1 -0
  113. package/dist/renderer/canvas2d-device.js +252 -0
  114. package/dist/renderer/canvas2d-device.js.map +1 -0
  115. package/dist/renderer/graphics-device.d.ts +36 -0
  116. package/dist/renderer/graphics-device.d.ts.map +1 -0
  117. package/dist/renderer/graphics-device.js +12 -0
  118. package/dist/renderer/graphics-device.js.map +1 -0
  119. package/dist/renderer/iso-projection.d.ts +11 -0
  120. package/dist/renderer/iso-projection.d.ts.map +1 -0
  121. package/dist/renderer/iso-projection.js +59 -0
  122. package/dist/renderer/iso-projection.js.map +1 -0
  123. package/dist/resources.d.ts +28 -0
  124. package/dist/resources.d.ts.map +1 -0
  125. package/dist/resources.js +53 -0
  126. package/dist/resources.js.map +1 -0
  127. package/dist/system.d.ts +14 -0
  128. package/dist/system.d.ts.map +1 -0
  129. package/dist/system.js +25 -0
  130. package/dist/system.js.map +1 -0
  131. package/dist/systems/animation-system.d.ts +8 -0
  132. package/dist/systems/animation-system.d.ts.map +1 -0
  133. package/dist/systems/animation-system.js +77 -0
  134. package/dist/systems/animation-system.js.map +1 -0
  135. package/dist/systems/attack-system.d.ts +17 -0
  136. package/dist/systems/attack-system.d.ts.map +1 -0
  137. package/dist/systems/attack-system.js +94 -0
  138. package/dist/systems/attack-system.js.map +1 -0
  139. package/dist/systems/damage-system.d.ts +18 -0
  140. package/dist/systems/damage-system.d.ts.map +1 -0
  141. package/dist/systems/damage-system.js +77 -0
  142. package/dist/systems/damage-system.js.map +1 -0
  143. package/dist/systems/input-system.d.ts +7 -0
  144. package/dist/systems/input-system.d.ts.map +1 -0
  145. package/dist/systems/input-system.js +27 -0
  146. package/dist/systems/input-system.js.map +1 -0
  147. package/dist/systems/interaction-system.d.ts +23 -0
  148. package/dist/systems/interaction-system.d.ts.map +1 -0
  149. package/dist/systems/interaction-system.js +120 -0
  150. package/dist/systems/interaction-system.js.map +1 -0
  151. package/dist/systems/particle-emitter-system.d.ts +8 -0
  152. package/dist/systems/particle-emitter-system.d.ts.map +1 -0
  153. package/dist/systems/particle-emitter-system.js +161 -0
  154. package/dist/systems/particle-emitter-system.js.map +1 -0
  155. package/dist/systems/particle-render-system.d.ts +7 -0
  156. package/dist/systems/particle-render-system.d.ts.map +1 -0
  157. package/dist/systems/particle-render-system.js +53 -0
  158. package/dist/systems/particle-render-system.js.map +1 -0
  159. package/dist/systems/particle-simulation-system.d.ts +8 -0
  160. package/dist/systems/particle-simulation-system.d.ts.map +1 -0
  161. package/dist/systems/particle-simulation-system.js +45 -0
  162. package/dist/systems/particle-simulation-system.js.map +1 -0
  163. package/dist/systems/projectile-render-system.d.ts +7 -0
  164. package/dist/systems/projectile-render-system.d.ts.map +1 -0
  165. package/dist/systems/projectile-render-system.js +35 -0
  166. package/dist/systems/projectile-render-system.js.map +1 -0
  167. package/dist/systems/projectile-system.d.ts +7 -0
  168. package/dist/systems/projectile-system.d.ts.map +1 -0
  169. package/dist/systems/projectile-system.js +114 -0
  170. package/dist/systems/projectile-system.js.map +1 -0
  171. package/dist/systems/pursue-system.d.ts +7 -0
  172. package/dist/systems/pursue-system.d.ts.map +1 -0
  173. package/dist/systems/pursue-system.js +83 -0
  174. package/dist/systems/pursue-system.js.map +1 -0
  175. package/dist/systems/ranged-attack-system.d.ts +7 -0
  176. package/dist/systems/ranged-attack-system.d.ts.map +1 -0
  177. package/dist/systems/ranged-attack-system.js +98 -0
  178. package/dist/systems/ranged-attack-system.js.map +1 -0
  179. package/dist/systems/sprite-render-system.d.ts +9 -0
  180. package/dist/systems/sprite-render-system.d.ts.map +1 -0
  181. package/dist/systems/sprite-render-system.js +108 -0
  182. package/dist/systems/sprite-render-system.js.map +1 -0
  183. package/dist/systems/veil-budget-system.d.ts +7 -0
  184. package/dist/systems/veil-budget-system.d.ts.map +1 -0
  185. package/dist/systems/veil-budget-system.js +37 -0
  186. package/dist/systems/veil-budget-system.js.map +1 -0
  187. package/dist/util/color.d.ts +19 -0
  188. package/dist/util/color.d.ts.map +1 -0
  189. package/dist/util/color.js +45 -0
  190. package/dist/util/color.js.map +1 -0
  191. package/dist/util/math.d.ts +26 -0
  192. package/dist/util/math.d.ts.map +1 -0
  193. package/dist/util/math.js +47 -0
  194. package/dist/util/math.js.map +1 -0
  195. package/dist/util/typed-arrays.d.ts +7 -0
  196. package/dist/util/typed-arrays.d.ts.map +1 -0
  197. package/dist/util/typed-arrays.js +42 -0
  198. package/dist/util/typed-arrays.js.map +1 -0
  199. package/dist/vfx/particle-pool.d.ts +61 -0
  200. package/dist/vfx/particle-pool.d.ts.map +1 -0
  201. package/dist/vfx/particle-pool.js +204 -0
  202. package/dist/vfx/particle-pool.js.map +1 -0
  203. package/dist/vfx/projectile-pool.d.ts +56 -0
  204. package/dist/vfx/projectile-pool.d.ts.map +1 -0
  205. package/dist/vfx/projectile-pool.js +157 -0
  206. package/dist/vfx/projectile-pool.js.map +1 -0
  207. package/dist/world.d.ts +23 -0
  208. package/dist/world.d.ts.map +1 -0
  209. package/dist/world.js +101 -0
  210. package/dist/world.js.map +1 -0
  211. package/dist/zone/zone-catalog.d.ts +17 -0
  212. package/dist/zone/zone-catalog.d.ts.map +1 -0
  213. package/dist/zone/zone-catalog.js +116 -0
  214. package/dist/zone/zone-catalog.js.map +1 -0
  215. package/dist/zone/zone-state.d.ts +18 -0
  216. package/dist/zone/zone-state.d.ts.map +1 -0
  217. package/dist/zone/zone-state.js +52 -0
  218. package/dist/zone/zone-state.js.map +1 -0
  219. package/package.json +56 -0
@@ -0,0 +1,267 @@
1
+ // VirtualDpad - on-screen 4-direction touch overlay that injects WASD
2
+ // key events into an InputManager. Lets every input-consuming system
3
+ // (movement, interaction, menu nav) keep reading keysHeld with no
4
+ // branching for "is this a touch device?" - the keys are already there.
5
+ //
6
+ // Layout: bottom-left of the viewport, a 3x3 grid where the four
7
+ // edge cells are directional buttons (up = KeyW, down = KeyS,
8
+ // left = KeyA, right = KeyD) and the center cell is a deadzone /
9
+ // label. Corners are inert. The grid is fixed-position so it stays
10
+ // pinned regardless of page scroll.
11
+ //
12
+ // Multi-touch: each direction tracks the set of touch identifiers
13
+ // currently pressing it. KeyDown injects only when the count goes
14
+ // 0->1; KeyUp injects only when it returns to 0. Fingers can slide
15
+ // off (touchcancel) without leaving a phantom held key.
16
+ //
17
+ // Visibility: by default the overlay only mounts when
18
+ // `'ontouchstart' in window` is true (or navigator.maxTouchPoints > 0).
19
+ // Callers can override via opts.visible for tests / forced display.
20
+ const KEY_FOR_DIRECTION = {
21
+ up: 'KeyW',
22
+ down: 'KeyS',
23
+ left: 'KeyA',
24
+ right: 'KeyD',
25
+ };
26
+ export class VirtualDpad {
27
+ opts;
28
+ root = null;
29
+ buttons = null;
30
+ mounted = false;
31
+ visible;
32
+ constructor(opts) {
33
+ this.opts = opts;
34
+ this.visible = opts.visible ?? VirtualDpad.detectTouchSupport();
35
+ }
36
+ // Heuristic: any modern phone / tablet exposes ontouchstart on
37
+ // window. iPad with iPadOS 13+ pretends to be desktop Safari but
38
+ // still reports navigator.maxTouchPoints > 0. Either signal is
39
+ // enough to consider the device touch-capable.
40
+ static detectTouchSupport(win) {
41
+ const w = win ?? (typeof window !== 'undefined' ? window : undefined);
42
+ if (!w)
43
+ return false;
44
+ if ('ontouchstart' in w)
45
+ return true;
46
+ const nav = w.navigator;
47
+ if (nav && typeof nav.maxTouchPoints === 'number' && nav.maxTouchPoints > 0)
48
+ return true;
49
+ return false;
50
+ }
51
+ isMounted() {
52
+ return this.mounted;
53
+ }
54
+ isVisible() {
55
+ return this.visible;
56
+ }
57
+ // Attach the overlay DOM. No-op on desktop (visible=false), so the
58
+ // caller can mount unconditionally and let the class decide.
59
+ mount() {
60
+ if (this.mounted)
61
+ return;
62
+ if (!this.visible)
63
+ return;
64
+ const doc = this.opts.document ?? (typeof document !== 'undefined' ? document : undefined);
65
+ if (!doc)
66
+ return;
67
+ const parent = this.opts.parent ?? doc.body;
68
+ if (!parent)
69
+ return;
70
+ const root = doc.createElement('div');
71
+ root.className = 'loom-virtual-dpad';
72
+ this.styleRoot(root);
73
+ const buttons = {
74
+ up: this.buildButton(doc, 'up', '▲'),
75
+ down: this.buildButton(doc, 'down', '▼'),
76
+ left: this.buildButton(doc, 'left', '◀'),
77
+ right: this.buildButton(doc, 'right', '▶'),
78
+ };
79
+ // 3x3 grid. Corners are inert spacers - cleaner press surface
80
+ // than a single round pad and easier to thumb on phones.
81
+ const grid = doc.createElement('div');
82
+ this.styleGrid(grid);
83
+ grid.appendChild(this.spacer(doc));
84
+ grid.appendChild(buttons.up.el);
85
+ grid.appendChild(this.spacer(doc));
86
+ grid.appendChild(buttons.left.el);
87
+ grid.appendChild(this.deadzone(doc));
88
+ grid.appendChild(buttons.right.el);
89
+ grid.appendChild(this.spacer(doc));
90
+ grid.appendChild(buttons.down.el);
91
+ grid.appendChild(this.spacer(doc));
92
+ root.appendChild(grid);
93
+ parent.appendChild(root);
94
+ this.root = root;
95
+ this.buttons = buttons;
96
+ this.attachListeners();
97
+ this.mounted = true;
98
+ }
99
+ // Remove the overlay and release any held WASD keys it had injected.
100
+ unmount() {
101
+ if (!this.mounted)
102
+ return;
103
+ if (this.buttons) {
104
+ for (const dir of Object.keys(this.buttons)) {
105
+ const b = this.buttons[dir];
106
+ if (b.active.size > 0) {
107
+ b.active.clear();
108
+ this.opts.inputManager.injectKeyUp(KEY_FOR_DIRECTION[dir]);
109
+ }
110
+ }
111
+ }
112
+ if (this.root && this.root.parentNode) {
113
+ this.root.parentNode.removeChild(this.root);
114
+ }
115
+ this.root = null;
116
+ this.buttons = null;
117
+ this.mounted = false;
118
+ }
119
+ // Synthetic press / release for tests. Bypasses DOM listeners but
120
+ // exercises the same accounting as a real touch.
121
+ pressDirection(dir, touchId = -1) {
122
+ const b = this.requireButton(dir);
123
+ const wasActive = b.active.size > 0;
124
+ b.active.add(touchId);
125
+ if (!wasActive) {
126
+ this.opts.inputManager.injectKeyDown(KEY_FOR_DIRECTION[dir]);
127
+ if (this.opts.onPress)
128
+ this.opts.onPress(dir);
129
+ }
130
+ }
131
+ releaseDirection(dir, touchId = -1) {
132
+ const b = this.requireButton(dir);
133
+ if (!b.active.delete(touchId))
134
+ return;
135
+ if (b.active.size === 0) {
136
+ this.opts.inputManager.injectKeyUp(KEY_FOR_DIRECTION[dir]);
137
+ }
138
+ }
139
+ // Number of unique touch IDs currently pressing a direction. Test
140
+ // helper; production code should read InputManager.snapshot().
141
+ pressedTouchCount(dir) {
142
+ if (!this.buttons)
143
+ return 0;
144
+ return this.buttons[dir].active.size;
145
+ }
146
+ requireButton(dir) {
147
+ if (!this.buttons) {
148
+ // pressDirection / releaseDirection used before mount. Build a
149
+ // headless button record so tests can drive synthetic presses
150
+ // without DOM mounting.
151
+ const headless = {
152
+ up: { el: null, active: new Set() },
153
+ down: { el: null, active: new Set() },
154
+ left: { el: null, active: new Set() },
155
+ right: { el: null, active: new Set() },
156
+ };
157
+ this.buttons = headless;
158
+ }
159
+ return this.buttons[dir];
160
+ }
161
+ buildButton(doc, dir, glyph) {
162
+ const el = doc.createElement('div');
163
+ el.className = 'loom-virtual-dpad-btn loom-virtual-dpad-' + dir;
164
+ el.textContent = glyph;
165
+ el.setAttribute('role', 'button');
166
+ el.setAttribute('aria-label', 'Move ' + dir);
167
+ this.styleButton(el);
168
+ return { el, active: new Set() };
169
+ }
170
+ spacer(doc) {
171
+ const el = doc.createElement('div');
172
+ el.className = 'loom-virtual-dpad-spacer';
173
+ el.style.pointerEvents = 'none';
174
+ return el;
175
+ }
176
+ deadzone(doc) {
177
+ const el = doc.createElement('div');
178
+ el.className = 'loom-virtual-dpad-deadzone';
179
+ el.style.pointerEvents = 'none';
180
+ el.style.display = 'flex';
181
+ el.style.alignItems = 'center';
182
+ el.style.justifyContent = 'center';
183
+ el.style.color = 'rgba(214, 198, 148, 0.45)';
184
+ el.style.fontSize = '10px';
185
+ el.style.letterSpacing = '0.08em';
186
+ el.style.textTransform = 'uppercase';
187
+ el.style.fontFamily = 'ui-monospace, Consolas, monospace';
188
+ el.textContent = 'move';
189
+ return el;
190
+ }
191
+ styleRoot(root) {
192
+ const s = root.style;
193
+ s.position = 'fixed';
194
+ // env() falls back to 12px when safe-area-inset is unsupported.
195
+ s.bottom = 'calc(12px + env(safe-area-inset-bottom, 0px))';
196
+ s.left = 'calc(12px + env(safe-area-inset-left, 0px))';
197
+ s.zIndex = '9000';
198
+ s.userSelect = 'none';
199
+ s.touchAction = 'none';
200
+ s.setProperty('-webkit-user-select', 'none');
201
+ }
202
+ styleGrid(grid) {
203
+ const s = grid.style;
204
+ s.display = 'grid';
205
+ s.gridTemplateColumns = '56px 56px 56px';
206
+ s.gridTemplateRows = '56px 56px 56px';
207
+ s.gap = '4px';
208
+ }
209
+ styleButton(btn) {
210
+ const s = btn.style;
211
+ s.display = 'flex';
212
+ s.alignItems = 'center';
213
+ s.justifyContent = 'center';
214
+ s.background = 'rgba(20, 17, 13, 0.72)';
215
+ s.border = '1px solid rgba(214, 198, 148, 0.35)';
216
+ s.borderRadius = '6px';
217
+ s.color = '#d6c694';
218
+ s.fontSize = '20px';
219
+ s.fontWeight = '700';
220
+ s.touchAction = 'none';
221
+ s.cursor = 'pointer';
222
+ s.userSelect = 'none';
223
+ s.setProperty('-webkit-user-select', 'none');
224
+ s.setProperty('-webkit-tap-highlight-color', 'transparent');
225
+ }
226
+ attachListeners() {
227
+ if (!this.buttons)
228
+ return;
229
+ const dirs = ['up', 'down', 'left', 'right'];
230
+ for (const dir of dirs) {
231
+ const b = this.buttons[dir];
232
+ // touchstart / touchend / touchcancel cover the touch case.
233
+ // mousedown / mouseup are added too so a desktop tester with a
234
+ // visible pad (opts.visible = true) can drive it from a mouse.
235
+ b.el.addEventListener('touchstart', (e) => {
236
+ const te = e;
237
+ for (let i = 0; i < te.changedTouches.length; i++) {
238
+ const t = te.changedTouches[i];
239
+ if (t)
240
+ this.pressDirection(dir, t.identifier);
241
+ }
242
+ te.preventDefault();
243
+ }, { passive: false });
244
+ const endHandler = (e) => {
245
+ const te = e;
246
+ for (let i = 0; i < te.changedTouches.length; i++) {
247
+ const t = te.changedTouches[i];
248
+ if (t)
249
+ this.releaseDirection(dir, t.identifier);
250
+ }
251
+ };
252
+ b.el.addEventListener('touchend', endHandler);
253
+ b.el.addEventListener('touchcancel', endHandler);
254
+ b.el.addEventListener('mousedown', (e) => {
255
+ this.pressDirection(dir, -1);
256
+ e.preventDefault();
257
+ });
258
+ // mouseup is on window so a press-then-drag-off-and-release
259
+ // doesn't leave a phantom held key.
260
+ const win = (typeof window !== 'undefined' ? window : undefined);
261
+ if (win) {
262
+ win.addEventListener('mouseup', () => this.releaseDirection(dir, -1));
263
+ }
264
+ }
265
+ }
266
+ }
267
+ //# sourceMappingURL=virtual-dpad.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"virtual-dpad.js","sourceRoot":"","sources":["../../src/input/virtual-dpad.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,qEAAqE;AACrE,kEAAkE;AAClE,wEAAwE;AACxE,EAAE;AACF,iEAAiE;AACjE,8DAA8D;AAC9D,iEAAiE;AACjE,mEAAmE;AACnE,oCAAoC;AACpC,EAAE;AACF,kEAAkE;AAClE,kEAAkE;AAClE,mEAAmE;AACnE,wDAAwD;AACxD,EAAE;AACF,sDAAsD;AACtD,wEAAwE;AACxE,oEAAoE;AAQpE,MAAM,iBAAiB,GAAkC;IACvD,EAAE,EAAE,MAAM;IACV,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,MAAM;CACd,CAAC;AAuBF,MAAM,OAAO,WAAW;IACd,IAAI,CAAqB;IACzB,IAAI,GAAuB,IAAI,CAAC;IAChC,OAAO,GAAkD,IAAI,CAAC;IAC9D,OAAO,GAAY,KAAK,CAAC;IACzB,OAAO,CAAU;IAEzB,YAAY,IAAwB;QAClC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,WAAW,CAAC,kBAAkB,EAAE,CAAC;IAClE,CAAC;IAED,+DAA+D;IAC/D,iEAAiE;IACjE,+DAA+D;IAC/D,+CAA+C;IAC/C,MAAM,CAAC,kBAAkB,CAAC,GAAY;QACpC,MAAM,CAAC,GAAuB,GAAG,IAAI,CAAC,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC1F,IAAI,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QACrB,IAAI,cAAc,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACrC,MAAM,GAAG,GAAG,CAAC,CAAC,SAAS,CAAC;QACxB,IAAI,GAAG,IAAI,OAAO,GAAG,CAAC,cAAc,KAAK,QAAQ,IAAI,GAAG,CAAC,cAAc,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QACzF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,mEAAmE;IACnE,6DAA6D;IAC7D,KAAK;QACH,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QACzB,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAC1B,MAAM,GAAG,GAAyB,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,OAAO,QAAQ,KAAK,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACjH,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,MAAM,MAAM,GAAgB,IAAI,CAAC,IAAI,CAAC,MAAM,IAAK,GAAG,CAAC,IAAoB,CAAC;QAC1E,IAAI,CAAC,MAAM;YAAE,OAAO;QAEpB,MAAM,IAAI,GAAgB,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACnD,IAAI,CAAC,SAAS,GAAG,mBAAmB,CAAC;QACrC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAErB,MAAM,OAAO,GAA2C;YACtD,EAAE,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC;YACpC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC;YACxC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC;YACxC,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC;SAC3C,CAAC;QAEF,8DAA8D;QAC9D,yDAAyD;QACzD,MAAM,IAAI,GAAgB,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACnD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACrB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACnC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAChC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACnC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QACrC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACnC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACnC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAEnC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACvB,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAEzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC;IAED,qEAAqE;IACrE,OAAO;QACL,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAC1B,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAoB,EAAE,CAAC;gBAC/D,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAC5B,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;oBACtB,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;oBACjB,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC7D,CAAC;YACH,CAAC;QACH,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACtC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,CAAC;QACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACvB,CAAC;IAED,kEAAkE;IAClE,iDAAiD;IACjD,cAAc,CAAC,GAAkB,EAAE,UAAkB,CAAC,CAAC;QACrD,MAAM,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;QACpC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACtB,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC;YAC7D,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO;gBAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAED,gBAAgB,CAAC,GAAkB,EAAE,UAAkB,CAAC,CAAC;QACvD,MAAM,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;YAAE,OAAO;QACtC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,kEAAkE;IAClE,+DAA+D;IAC/D,iBAAiB,CAAC,GAAkB;QAClC,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,CAAC,CAAC;QAC5B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;IACvC,CAAC;IAEO,aAAa,CAAC,GAAkB;QACtC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,+DAA+D;YAC/D,8DAA8D;YAC9D,wBAAwB;YACxB,MAAM,QAAQ,GAA2C;gBACvD,EAAE,EAAE,EAAE,EAAE,EAAE,IAA8B,EAAE,MAAM,EAAE,IAAI,GAAG,EAAE,EAAE;gBAC7D,IAAI,EAAE,EAAE,EAAE,EAAE,IAA8B,EAAE,MAAM,EAAE,IAAI,GAAG,EAAE,EAAE;gBAC/D,IAAI,EAAE,EAAE,EAAE,EAAE,IAA8B,EAAE,MAAM,EAAE,IAAI,GAAG,EAAE,EAAE;gBAC/D,KAAK,EAAE,EAAE,EAAE,EAAE,IAA8B,EAAE,MAAM,EAAE,IAAI,GAAG,EAAE,EAAE;aACjE,CAAC;YACF,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC;QAC1B,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAEO,WAAW,CAAC,GAAa,EAAE,GAAkB,EAAE,KAAa;QAClE,MAAM,EAAE,GAAgB,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACjD,EAAE,CAAC,SAAS,GAAG,0CAA0C,GAAG,GAAG,CAAC;QAChE,EAAE,CAAC,WAAW,GAAG,KAAK,CAAC;QACvB,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAClC,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,GAAG,GAAG,CAAC,CAAC;QAC7C,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACrB,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;IACnC,CAAC;IAEO,MAAM,CAAC,GAAa;QAC1B,MAAM,EAAE,GAAgB,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACjD,EAAE,CAAC,SAAS,GAAG,0BAA0B,CAAC;QAC1C,EAAE,CAAC,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC;QAChC,OAAO,EAAE,CAAC;IACZ,CAAC;IAEO,QAAQ,CAAC,GAAa;QAC5B,MAAM,EAAE,GAAgB,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACjD,EAAE,CAAC,SAAS,GAAG,4BAA4B,CAAC;QAC5C,EAAE,CAAC,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC;QAChC,EAAE,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;QAC1B,EAAE,CAAC,KAAK,CAAC,UAAU,GAAG,QAAQ,CAAC;QAC/B,EAAE,CAAC,KAAK,CAAC,cAAc,GAAG,QAAQ,CAAC;QACnC,EAAE,CAAC,KAAK,CAAC,KAAK,GAAG,2BAA2B,CAAC;QAC7C,EAAE,CAAC,KAAK,CAAC,QAAQ,GAAG,MAAM,CAAC;QAC3B,EAAE,CAAC,KAAK,CAAC,aAAa,GAAG,QAAQ,CAAC;QAClC,EAAE,CAAC,KAAK,CAAC,aAAa,GAAG,WAAW,CAAC;QACrC,EAAE,CAAC,KAAK,CAAC,UAAU,GAAG,mCAAmC,CAAC;QAC1D,EAAE,CAAC,WAAW,GAAG,MAAM,CAAC;QACxB,OAAO,EAAE,CAAC;IACZ,CAAC;IAEO,SAAS,CAAC,IAAiB;QACjC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;QACrB,CAAC,CAAC,QAAQ,GAAG,OAAO,CAAC;QACrB,gEAAgE;QAChE,CAAC,CAAC,MAAM,GAAG,+CAA+C,CAAC;QAC3D,CAAC,CAAC,IAAI,GAAG,6CAA6C,CAAC;QACvD,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC;QAClB,CAAC,CAAC,UAAU,GAAG,MAAM,CAAC;QACtB,CAAC,CAAC,WAAW,GAAG,MAAM,CAAC;QACvB,CAAC,CAAC,WAAW,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;IAC/C,CAAC;IAEO,SAAS,CAAC,IAAiB;QACjC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;QACrB,CAAC,CAAC,OAAO,GAAG,MAAM,CAAC;QACnB,CAAC,CAAC,mBAAmB,GAAG,gBAAgB,CAAC;QACzC,CAAC,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;QACtC,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC;IAChB,CAAC;IAEO,WAAW,CAAC,GAAgB;QAClC,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC;QACpB,CAAC,CAAC,OAAO,GAAG,MAAM,CAAC;QACnB,CAAC,CAAC,UAAU,GAAG,QAAQ,CAAC;QACxB,CAAC,CAAC,cAAc,GAAG,QAAQ,CAAC;QAC5B,CAAC,CAAC,UAAU,GAAG,wBAAwB,CAAC;QACxC,CAAC,CAAC,MAAM,GAAG,qCAAqC,CAAC;QACjD,CAAC,CAAC,YAAY,GAAG,KAAK,CAAC;QACvB,CAAC,CAAC,KAAK,GAAG,SAAS,CAAC;QACpB,CAAC,CAAC,QAAQ,GAAG,MAAM,CAAC;QACpB,CAAC,CAAC,UAAU,GAAG,KAAK,CAAC;QACrB,CAAC,CAAC,WAAW,GAAG,MAAM,CAAC;QACvB,CAAC,CAAC,MAAM,GAAG,SAAS,CAAC;QACrB,CAAC,CAAC,UAAU,GAAG,MAAM,CAAC;QACtB,CAAC,CAAC,WAAW,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;QAC7C,CAAC,CAAC,WAAW,CAAC,6BAA6B,EAAE,aAAa,CAAC,CAAC;IAC9D,CAAC;IAEO,eAAe;QACrB,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAC1B,MAAM,IAAI,GAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QAC9D,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC5B,4DAA4D;YAC5D,+DAA+D;YAC/D,+DAA+D;YAC/D,CAAC,CAAC,EAAE,CAAC,gBAAgB,CAAC,YAAY,EAAE,CAAC,CAAQ,EAAE,EAAE;gBAC/C,MAAM,EAAE,GAAG,CAAe,CAAC;gBAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBAClD,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;oBAC/B,IAAI,CAAC;wBAAE,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;gBAChD,CAAC;gBACD,EAAE,CAAC,cAAc,EAAE,CAAC;YACtB,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAA6B,CAAC,CAAC;YAClD,MAAM,UAAU,GAAG,CAAC,CAAQ,EAAQ,EAAE;gBACpC,MAAM,EAAE,GAAG,CAAe,CAAC;gBAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBAClD,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;oBAC/B,IAAI,CAAC;wBAAE,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;gBAClD,CAAC;YACH,CAAC,CAAC;YACF,CAAC,CAAC,EAAE,CAAC,gBAAgB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;YAC9C,CAAC,CAAC,EAAE,CAAC,gBAAgB,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;YACjD,CAAC,CAAC,EAAE,CAAC,gBAAgB,CAAC,WAAW,EAAE,CAAC,CAAQ,EAAE,EAAE;gBAC9C,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;gBAC5B,CAAgB,CAAC,cAAc,EAAE,CAAC;YACrC,CAAC,CAAC,CAAC;YACH,4DAA4D;YAC5D,oCAAoC;YACpC,MAAM,GAAG,GAAuB,CAAC,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACrF,IAAI,GAAG,EAAE,CAAC;gBACR,GAAG,CAAC,gBAAgB,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACxE,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,26 @@
1
+ import type { Rect } from '../util/math.js';
2
+ export interface CameraView {
3
+ centerX: number;
4
+ centerY: number;
5
+ zoom: number;
6
+ rotation: number;
7
+ viewportWidth: number;
8
+ viewportHeight: number;
9
+ }
10
+ export declare function createCamera(viewportWidth: number, viewportHeight: number): CameraView;
11
+ export declare function getCameraViewRect(cam: CameraView, out: Rect): Rect;
12
+ export declare function worldToScreen(cam: CameraView, worldX: number, worldY: number, out: {
13
+ x: number;
14
+ y: number;
15
+ }): {
16
+ x: number;
17
+ y: number;
18
+ };
19
+ export declare function screenToWorld(cam: CameraView, screenX: number, screenY: number, out: {
20
+ x: number;
21
+ y: number;
22
+ }): {
23
+ x: number;
24
+ y: number;
25
+ };
26
+ //# sourceMappingURL=camera.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"camera.d.ts","sourceRoot":"","sources":["../../src/renderer/camera.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE5C,MAAM,WAAW,UAAU;IAEzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAEhB,IAAI,EAAE,MAAM,CAAC;IAEb,QAAQ,EAAE,MAAM,CAAC;IAEjB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,YAAY,CAAC,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,UAAU,CAStF;AAID,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,GAAG,IAAI,CAQlE;AAID,wBAAgB,aAAa,CAC3B,GAAG,EAAE,UAAU,EACf,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,GAAG,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAI1B;AAED,wBAAgB,aAAa,CAC3B,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,GAAG,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAI1B"}
@@ -0,0 +1,39 @@
1
+ // Camera for the Loom Engine.
2
+ //
3
+ // 2D camera with optional zoom + rotation. Iso projection happens
4
+ // in iso-projection.ts; this camera produces the screen-space view
5
+ // rect that systems use for frustum culling.
6
+ export function createCamera(viewportWidth, viewportHeight) {
7
+ return {
8
+ centerX: 0,
9
+ centerY: 0,
10
+ zoom: 1,
11
+ rotation: 0,
12
+ viewportWidth,
13
+ viewportHeight,
14
+ };
15
+ }
16
+ // World-space rect that the camera currently sees. Used for frustum
17
+ // culling. Rotation is ignored in v1 (engine ships axis-aligned).
18
+ export function getCameraViewRect(cam, out) {
19
+ const halfW = cam.viewportWidth / cam.zoom / 2;
20
+ const halfH = cam.viewportHeight / cam.zoom / 2;
21
+ out.x = cam.centerX - halfW;
22
+ out.y = cam.centerY - halfH;
23
+ out.width = halfW * 2;
24
+ out.height = halfH * 2;
25
+ return out;
26
+ }
27
+ // World-space coords -> screen-space coords. Iso transform happens
28
+ // before this; this is the pure camera transform.
29
+ export function worldToScreen(cam, worldX, worldY, out) {
30
+ out.x = (worldX - cam.centerX) * cam.zoom + cam.viewportWidth / 2;
31
+ out.y = (worldY - cam.centerY) * cam.zoom + cam.viewportHeight / 2;
32
+ return out;
33
+ }
34
+ export function screenToWorld(cam, screenX, screenY, out) {
35
+ out.x = (screenX - cam.viewportWidth / 2) / cam.zoom + cam.centerX;
36
+ out.y = (screenY - cam.viewportHeight / 2) / cam.zoom + cam.centerY;
37
+ return out;
38
+ }
39
+ //# sourceMappingURL=camera.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"camera.js","sourceRoot":"","sources":["../../src/renderer/camera.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,EAAE;AACF,kEAAkE;AAClE,mEAAmE;AACnE,6CAA6C;AAiB7C,MAAM,UAAU,YAAY,CAAC,aAAqB,EAAE,cAAsB;IACxE,OAAO;QACL,OAAO,EAAE,CAAC;QACV,OAAO,EAAE,CAAC;QACV,IAAI,EAAE,CAAC;QACP,QAAQ,EAAE,CAAC;QACX,aAAa;QACb,cAAc;KACf,CAAC;AACJ,CAAC;AAED,oEAAoE;AACpE,kEAAkE;AAClE,MAAM,UAAU,iBAAiB,CAAC,GAAe,EAAE,GAAS;IAC1D,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,GAAG,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,GAAG,CAAC,cAAc,GAAG,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC;IAChD,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,OAAO,GAAG,KAAK,CAAC;IAC5B,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,OAAO,GAAG,KAAK,CAAC;IAC5B,GAAG,CAAC,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC;IACtB,GAAG,CAAC,MAAM,GAAG,KAAK,GAAG,CAAC,CAAC;IACvB,OAAO,GAAG,CAAC;AACb,CAAC;AAED,mEAAmE;AACnE,kDAAkD;AAClD,MAAM,UAAU,aAAa,CAC3B,GAAe,EACf,MAAc,EACd,MAAc,EACd,GAA6B;IAE7B,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,aAAa,GAAG,CAAC,CAAC;IAClE,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC;IACnE,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,GAAe,EACf,OAAe,EACf,OAAe,EACf,GAA6B;IAE7B,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,aAAa,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC;IACnE,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC;IACpE,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { ColorRGBA } from '../util/color.js';
2
+ import { type IGraphicsDevice, type AtlasHandle, type AtlasDescriptor, type TextStyle } from './graphics-device.js';
3
+ import { type CameraView } from './camera.js';
4
+ export declare class Canvas2DDevice implements IGraphicsDevice {
5
+ readonly canvas: HTMLCanvasElement;
6
+ readonly viewportWidth: number;
7
+ readonly viewportHeight: number;
8
+ private ctx;
9
+ private atlases;
10
+ private nextAtlasHandle;
11
+ private camera;
12
+ private drawCallCount;
13
+ private particleDisc;
14
+ constructor(canvas: HTMLCanvasElement);
15
+ beginFrame(): void;
16
+ endFrame(): void;
17
+ setCamera(cam: Readonly<CameraView>): void;
18
+ registerAtlas(desc: AtlasDescriptor): AtlasHandle;
19
+ releaseAtlas(handle: AtlasHandle): void;
20
+ drawSprite(worldX: number, worldY: number, worldZ: number, atlas: AtlasHandle, frame: number, tint?: Readonly<ColorRGBA>): void;
21
+ drawTile(tileX: number, tileY: number, atlas: AtlasHandle, frame: number): void;
22
+ drawText(worldX: number, worldY: number, text: string, style: TextStyle): void;
23
+ drawParticle(worldX: number, worldY: number, worldZ: number, size: number, color: Readonly<ColorRGBA>, additive: boolean): void;
24
+ getDrawCallCount(): number;
25
+ }
26
+ //# sourceMappingURL=canvas2d-device.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas2d-device.d.ts","sourceRoot":"","sources":["../../src/renderer/canvas2d-device.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,SAAS,EACf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,KAAK,UAAU,EAEhB,MAAM,aAAa,CAAC;AA0CrB,qBAAa,cAAe,YAAW,eAAe;IACpD,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAEhC,OAAO,CAAC,GAAG,CAA2B;IACtC,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,aAAa,CAAa;IAElC,OAAO,CAAC,YAAY,CAAkC;gBAE1C,MAAM,EAAE,iBAAiB;IAcrC,UAAU,IAAI,IAAI;IAQlB,QAAQ,IAAI,IAAI;IAIhB,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI;IAM1C,aAAa,CAAC,IAAI,EAAE,eAAe,GAAG,WAAW;IAMjD,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAQvC,UAAU,CACR,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,GACzB,IAAI;IA8CP,QAAQ,CACN,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,MAAM,GACZ,IAAI;IA4BP,QAAQ,CACN,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,SAAS,GACf,IAAI;IAoBP,YAAY,CACV,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,QAAQ,CAAC,SAAS,CAAC,EAC1B,QAAQ,EAAE,OAAO,GAChB,IAAI;IAsEP,gBAAgB,IAAI,MAAM;CAG3B"}
@@ -0,0 +1,252 @@
1
+ // Canvas2D backend for the Loom Engine.
2
+ //
3
+ // Primary backend for v1. Iso world coords -> screen coords happens
4
+ // inside the device. drawImage is the workhorse; sorting is the
5
+ // caller's responsibility (the render-graph stage submits sprites
6
+ // in depth-sort order).
7
+ //
8
+ // Babylon.js inspires the ThinEngine split: this file is the lean
9
+ // GPU-talking core. Higher-level scene logic lives elsewhere. See
10
+ // PRIOR-ART.md.
11
+ import { rgbaToCssString } from '../util/color.js';
12
+ import { worldToScreen, } from './camera.js';
13
+ import { ISO_HALF_W, ISO_HALF_H, ISO_Z_SCALE, } from './iso-projection.js';
14
+ const SCRATCH_VEC2 = { x: 0, y: 0 };
15
+ // Pre-baked particle disc - white-to-transparent radial gradient at
16
+ // 64px diameter on an offscreen canvas. drawParticle uses this with
17
+ // drawImage instead of allocating a fresh CanvasGradient per call.
18
+ // Additive blend with globalAlpha = color.a gives correct brightness
19
+ // per particle. For non-additive tinted particles the gradient path
20
+ // is preserved as a fallback (RGB tinting under straight alpha
21
+ // requires a tinted disc per color, which would need a per-color
22
+ // cache; the demo + Phase 4 emitters are all additive so this fast
23
+ // path covers the hot case).
24
+ const PARTICLE_DISC_SIZE = 64;
25
+ function bakeParticleDisc() {
26
+ if (typeof document === 'undefined')
27
+ return null;
28
+ const c = document.createElement('canvas');
29
+ c.width = PARTICLE_DISC_SIZE;
30
+ c.height = PARTICLE_DISC_SIZE;
31
+ const ctx = c.getContext('2d');
32
+ if (!ctx)
33
+ return null;
34
+ const center = PARTICLE_DISC_SIZE / 2;
35
+ const grad = ctx.createRadialGradient(center, center, 0, center, center, center);
36
+ grad.addColorStop(0, 'rgba(255,255,255,1)');
37
+ grad.addColorStop(1, 'rgba(255,255,255,0)');
38
+ ctx.fillStyle = grad;
39
+ ctx.beginPath();
40
+ ctx.arc(center, center, center, 0, Math.PI * 2);
41
+ ctx.fill();
42
+ return c;
43
+ }
44
+ export class Canvas2DDevice {
45
+ canvas;
46
+ viewportWidth;
47
+ viewportHeight;
48
+ ctx;
49
+ atlases = [];
50
+ nextAtlasHandle = 0;
51
+ camera = null;
52
+ drawCallCount = 0;
53
+ // Lazy-initialized; null in headless / non-DOM contexts.
54
+ particleDisc = null;
55
+ constructor(canvas) {
56
+ this.canvas = canvas;
57
+ this.viewportWidth = canvas.width;
58
+ this.viewportHeight = canvas.height;
59
+ const ctx = canvas.getContext('2d', { alpha: false });
60
+ if (!ctx) {
61
+ throw new Error('Canvas2DDevice: failed to acquire 2D context');
62
+ }
63
+ this.ctx = ctx;
64
+ // Pixel-art friendly defaults. Future style configurability
65
+ // belongs in a device options object; v1 ships pixel-art-first.
66
+ this.ctx.imageSmoothingEnabled = false;
67
+ }
68
+ beginFrame() {
69
+ this.drawCallCount = 0;
70
+ // Clear to opaque black. Higher-level stages can paint a sky
71
+ // color in their own clear stage if they want a different bg.
72
+ this.ctx.fillStyle = '#000';
73
+ this.ctx.fillRect(0, 0, this.viewportWidth, this.viewportHeight);
74
+ }
75
+ endFrame() {
76
+ // Immediate-mode backend - nothing to flush.
77
+ }
78
+ setCamera(cam) {
79
+ // Store a reference rather than copying. The caller owns the
80
+ // camera object; we only read it inside draw* calls.
81
+ this.camera = cam;
82
+ }
83
+ registerAtlas(desc) {
84
+ const handle = this.nextAtlasHandle++;
85
+ this.atlases[handle] = { desc, released: false };
86
+ return handle;
87
+ }
88
+ releaseAtlas(handle) {
89
+ const slot = this.atlases[handle];
90
+ if (slot) {
91
+ slot.released = true;
92
+ this.atlases[handle] = null;
93
+ }
94
+ }
95
+ drawSprite(worldX, worldY, worldZ, atlas, frame, tint) {
96
+ const slot = this.atlases[atlas];
97
+ if (!slot || slot.released)
98
+ return;
99
+ const f = slot.desc.frames[frame];
100
+ if (!f)
101
+ return;
102
+ const cam = this.camera;
103
+ if (!cam)
104
+ return;
105
+ // Iso projection: world (x,y,z) -> iso (sx,sy) before camera.
106
+ const isoX = (worldX - worldY) * ISO_HALF_W;
107
+ const isoY = (worldX + worldY) * ISO_HALF_H - worldZ * ISO_Z_SCALE;
108
+ // Camera transform: iso world -> screen.
109
+ worldToScreen(cam, isoX, isoY, SCRATCH_VEC2);
110
+ const screenX = SCRATCH_VEC2.x;
111
+ const screenY = SCRATCH_VEC2.y;
112
+ // Draw centered horizontally, anchored at the bottom (sprite's
113
+ // feet on the iso projection point). This is the standard iso
114
+ // sprite anchor.
115
+ const dw = f.w * cam.zoom;
116
+ const dh = f.h * cam.zoom;
117
+ const dx = screenX - dw / 2;
118
+ const dy = screenY - dh;
119
+ if (tint) {
120
+ this.ctx.save();
121
+ this.ctx.globalAlpha = tint.a;
122
+ // Canvas2D doesn't tint drawImage natively. For pixel-perfect
123
+ // tint we'd need to pre-bake tinted variants in an offscreen
124
+ // canvas. For v1 we use globalAlpha + a colored overlay
125
+ // composite. Optimization deferred.
126
+ this.ctx.drawImage(slot.desc.image, f.x, f.y, f.w, f.h, dx, dy, dw, dh);
127
+ if (tint.r !== 1 || tint.g !== 1 || tint.b !== 1) {
128
+ this.ctx.globalCompositeOperation = 'multiply';
129
+ this.ctx.fillStyle = rgbaToCssString(tint);
130
+ this.ctx.fillRect(dx, dy, dw, dh);
131
+ }
132
+ this.ctx.restore();
133
+ }
134
+ else {
135
+ this.ctx.drawImage(slot.desc.image, f.x, f.y, f.w, f.h, dx, dy, dw, dh);
136
+ }
137
+ this.drawCallCount++;
138
+ }
139
+ drawTile(tileX, tileY, atlas, frame) {
140
+ const slot = this.atlases[atlas];
141
+ if (!slot || slot.released)
142
+ return;
143
+ const f = slot.desc.frames[frame];
144
+ if (!f)
145
+ return;
146
+ const cam = this.camera;
147
+ if (!cam)
148
+ return;
149
+ // Tile -> iso (no Z; tiles sit on the ground plane).
150
+ const isoX = (tileX - tileY) * ISO_HALF_W;
151
+ const isoY = (tileX + tileY) * ISO_HALF_H;
152
+ worldToScreen(cam, isoX, isoY, SCRATCH_VEC2);
153
+ const screenX = SCRATCH_VEC2.x;
154
+ const screenY = SCRATCH_VEC2.y;
155
+ const dw = f.w * cam.zoom;
156
+ const dh = f.h * cam.zoom;
157
+ // Tile anchor: top of the diamond aligns with the iso point.
158
+ // Standard 2:1 dimetric. Tile draws centered horizontally on
159
+ // the projection point, top edge at the iso Y.
160
+ const dx = screenX - dw / 2;
161
+ const dy = screenY - dh / 2;
162
+ this.ctx.drawImage(slot.desc.image, f.x, f.y, f.w, f.h, dx, dy, dw, dh);
163
+ this.drawCallCount++;
164
+ }
165
+ drawText(worldX, worldY, text, style) {
166
+ const cam = this.camera;
167
+ if (!cam)
168
+ return;
169
+ // Text is treated as a 2D-overlay; no iso projection (text
170
+ // labels read left-to-right regardless of iso angle).
171
+ worldToScreen(cam, worldX, worldY, SCRATCH_VEC2);
172
+ const screenX = SCRATCH_VEC2.x;
173
+ const screenY = SCRATCH_VEC2.y;
174
+ this.ctx.save();
175
+ this.ctx.font = style.font;
176
+ this.ctx.fillStyle = rgbaToCssString(style.fill);
177
+ this.ctx.textAlign = style.align ?? 'left';
178
+ this.ctx.textBaseline = style.baseline ?? 'alphabetic';
179
+ this.ctx.fillText(text, screenX, screenY);
180
+ this.ctx.restore();
181
+ this.drawCallCount++;
182
+ }
183
+ drawParticle(worldX, worldY, worldZ, size, color, additive) {
184
+ const cam = this.camera;
185
+ if (!cam)
186
+ return;
187
+ if (size <= 0 || color.a <= 0)
188
+ return;
189
+ // Iso projection same as drawSprite: world (x,y,z) -> iso (sx,sy)
190
+ // -> screen via camera.
191
+ const isoX = (worldX - worldY) * ISO_HALF_W;
192
+ const isoY = (worldX + worldY) * ISO_HALF_H - worldZ * ISO_Z_SCALE;
193
+ worldToScreen(cam, isoX, isoY, SCRATCH_VEC2);
194
+ const sx = SCRATCH_VEC2.x;
195
+ const sy = SCRATCH_VEC2.y;
196
+ const r = (size / 2) * cam.zoom;
197
+ // Fast path for additive particles: pre-baked white soft-disc
198
+ // with globalAlpha. Under 'lighter' blend, white * alpha gives
199
+ // RGB brightness contributions and the underlying canvas color
200
+ // emerges, so additive is hue-correct enough for the demo +
201
+ // Phase 4 sparkle emitters. No per-call CanvasGradient
202
+ // allocation; drawImage hits the fast composite path.
203
+ if (additive) {
204
+ if (!this.particleDisc)
205
+ this.particleDisc = bakeParticleDisc();
206
+ if (this.particleDisc) {
207
+ this.ctx.save();
208
+ this.ctx.globalCompositeOperation = 'lighter';
209
+ // For colored additive particles, multiply by color via
210
+ // globalAlpha (intensity) AND by drawing tinted via a
211
+ // single fillStyle pre-tint pass. Simpler heuristic for
212
+ // demo: alpha = color.a * brightness factor. Hue comes
213
+ // from the underlying canvas + sequential additive layers.
214
+ // For correctness we'd want per-color discs; deferred until
215
+ // a profile shows colored particles dominate.
216
+ const dia = r * 2;
217
+ const intensity = color.a;
218
+ // RGB brightness folds into globalAlpha for additive blend
219
+ // - white * alpha = grey. For tinted additive (most common),
220
+ // we drawImage twice: once with the disc weighted by R, etc.
221
+ // Simpler: bake a single colored composite by chaining.
222
+ // Practical compromise: alpha = max(r, g, b) * a so colored
223
+ // particles aren't washed out.
224
+ const channelMax = Math.max(color.r, color.g, color.b);
225
+ this.ctx.globalAlpha = intensity * channelMax;
226
+ this.ctx.drawImage(this.particleDisc, sx - r, sy - r, dia, dia);
227
+ this.ctx.restore();
228
+ this.drawCallCount++;
229
+ return;
230
+ }
231
+ }
232
+ // Fallback: gradient path (correct color tinting for non-additive,
233
+ // or when the pre-baked disc isn't available e.g. headless / SSR).
234
+ this.ctx.save();
235
+ if (additive) {
236
+ this.ctx.globalCompositeOperation = 'lighter';
237
+ }
238
+ const grad = this.ctx.createRadialGradient(sx, sy, 0, sx, sy, r);
239
+ grad.addColorStop(0, rgbaToCssString(color));
240
+ grad.addColorStop(1, rgbaToCssString({ r: color.r, g: color.g, b: color.b, a: 0 }));
241
+ this.ctx.fillStyle = grad;
242
+ this.ctx.beginPath();
243
+ this.ctx.arc(sx, sy, r, 0, Math.PI * 2);
244
+ this.ctx.fill();
245
+ this.ctx.restore();
246
+ this.drawCallCount++;
247
+ }
248
+ getDrawCallCount() {
249
+ return this.drawCallCount;
250
+ }
251
+ }
252
+ //# sourceMappingURL=canvas2d-device.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas2d-device.js","sourceRoot":"","sources":["../../src/renderer/canvas2d-device.ts"],"names":[],"mappings":"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"}