like2d 2.7.4 → 2.8.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.
@@ -20,6 +20,13 @@ export declare class CanvasManager {
20
20
  dispose(): void;
21
21
  present(): void;
22
22
  getDisplayCanvas(): HTMLCanvasElement;
23
- transformMousePosition(cssX: number, cssY: number): Vector2;
23
+ /** Canvas to render to. Pixel canvas in pixel mode, display canvas otherwise. */
24
+ getRenderTarget(): {
25
+ canvas: HTMLCanvasElement;
26
+ ctx: CanvasRenderingContext2D;
27
+ };
28
+ /** Render target size in pixels. Pixel resolution in pixel mode, scaled size otherwise. */
29
+ getCanvasSize(): Vector2;
30
+ transformMousePosition(offsetX: number, offsetY: number): Vector2;
24
31
  }
25
32
  //# sourceMappingURL=canvas-manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"canvas-manager.d.ts","sourceRoot":"","sources":["../../src/core/canvas-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAQ,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAmB/C,qBAAa,aAAa;IAUtB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,MAAM;IAZhB,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,QAAQ,CAAyC;IAEzD,OAAO,CAAC,cAAc,CAA4B;IAE3C,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;gBAGxF,MAAM,EAAE,iBAAiB,EACzB,SAAS,EAAE,WAAW,EACtB,GAAG,EAAE,wBAAwB,EAC7B,MAAM,GAAE,UAAyD;IAW3E,OAAO,CAAC,0BAA0B;IAQlC,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI;IAKtC,OAAO,IAAI,UAAU;IAIrB,OAAO,CAAC,WAAW;IA2BnB,OAAO,CAAC,cAAc;IAwBtB,OAAO,CAAC,eAAe;IAkBvB,OAAO,IAAI,IAAI;IAQf,OAAO,IAAI,IAAI;IAaf,gBAAgB,IAAI,iBAAiB;IAIrC,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;CAiB5D"}
1
+ {"version":3,"file":"canvas-manager.d.ts","sourceRoot":"","sources":["../../src/core/canvas-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAQ,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAmB/C,qBAAa,aAAa;IAUtB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,MAAM;IAZhB,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,QAAQ,CAAyC;IAEzD,OAAO,CAAC,cAAc,CAA4B;IAE3C,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;gBAGxF,MAAM,EAAE,iBAAiB,EACzB,SAAS,EAAE,WAAW,EACtB,GAAG,EAAE,wBAAwB,EAC7B,MAAM,GAAE,UAAyD;IAW3E,OAAO,CAAC,0BAA0B;IAQlC,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI;IAKtC,OAAO,IAAI,UAAU;IAIrB,OAAO,CAAC,WAAW;IAwBnB,OAAO,CAAC,cAAc;IAqBtB,OAAO,CAAC,eAAe;IAkBvB,OAAO,IAAI,IAAI;IAQf,OAAO,IAAI,IAAI;IAaf,gBAAgB,IAAI,iBAAiB;IAIrC,iFAAiF;IACjF,eAAe,IAAI;QAAE,MAAM,EAAE,iBAAiB,CAAC;QAAC,GAAG,EAAE,wBAAwB,CAAA;KAAE;IAO/E,2FAA2F;IAC3F,aAAa,IAAI,OAAO;IAKxB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO;CAYlE"}
@@ -93,7 +93,6 @@ export class CanvasManager {
93
93
  const containerSize = document.fullscreenElement
94
94
  ? [document.fullscreenElement.clientWidth, document.fullscreenElement.clientHeight]
95
95
  : [this.container.clientWidth, this.container.clientHeight];
96
- // Always clean up pixel canvas first
97
96
  if (this.pixelCanvas) {
98
97
  this.pixelCanvas.remove();
99
98
  this.pixelCanvas = null;
@@ -105,27 +104,23 @@ export class CanvasManager {
105
104
  else {
106
105
  this.applyNativeMode(containerSize);
107
106
  }
108
- const displayCanvas = this.pixelCanvas ?? this.canvas;
109
- this.onResize?.(containerSize, [displayCanvas.width, displayCanvas.height], this.config.fullscreen);
107
+ this.onResize?.(containerSize, [this.canvas.width, this.canvas.height], this.config.fullscreen);
110
108
  }
111
109
  applyPixelMode(csize) {
112
110
  const gameSize = this.config.pixelResolution;
113
111
  const pixelRatio = window.devicePixelRatio || 1;
114
112
  const scale = Math.min(csize[0] / gameSize[0], csize[1] / gameSize[1]);
115
113
  const physicalScale = scale * pixelRatio;
116
- const intScale = Math.max(1, Math.floor(physicalScale));
114
+ const intScale = Math.max(1, Math.round(physicalScale));
117
115
  this.pixelCanvas = document.createElement('canvas');
118
116
  this.pixelCtx = this.pixelCanvas.getContext('2d');
119
- setCanvasSize(this.pixelCanvas, Vec2.mul(gameSize, intScale));
120
- setCanvasSize(this.canvas, gameSize);
121
- this.canvas.style.display = 'none';
122
- const pc = this.pixelCanvas;
123
- setCanvasDisplaySize(pc, Vec2.mul(gameSize, scale));
124
- pc.style.maxWidth = '100%';
125
- pc.style.maxHeight = '100%';
126
- pc.style.imageRendering = 'auto';
127
- centerElement(pc);
128
- this.container.appendChild(pc);
117
+ setCanvasSize(this.pixelCanvas, gameSize);
118
+ setCanvasSize(this.canvas, Vec2.mul(gameSize, intScale));
119
+ setCanvasDisplaySize(this.canvas, Vec2.mul(gameSize, scale));
120
+ this.canvas.style.maxWidth = '100%';
121
+ this.canvas.style.maxHeight = '100%';
122
+ this.canvas.style.imageRendering = 'auto';
123
+ centerElement(this.canvas);
129
124
  }
130
125
  applyNativeMode(csize) {
131
126
  const pixelRatio = window.devicePixelRatio || 1;
@@ -152,27 +147,33 @@ export class CanvasManager {
152
147
  if (!this.pixelCtx || !this.pixelCanvas) {
153
148
  return;
154
149
  }
155
- this.pixelCtx.imageSmoothingEnabled = false;
156
- this.pixelCtx.drawImage(this.canvas, 0, 0, this.canvas.width, this.canvas.height, 0, 0, this.pixelCanvas.width, this.pixelCanvas.height);
150
+ this.ctx.imageSmoothingEnabled = false;
151
+ this.ctx.drawImage(this.pixelCanvas, 0, 0, this.pixelCanvas.width, this.pixelCanvas.height, 0, 0, this.canvas.width, this.canvas.height);
157
152
  }
158
153
  getDisplayCanvas() {
159
- return this.pixelCanvas ?? this.canvas;
154
+ return this.canvas;
160
155
  }
161
- transformMousePosition(cssX, cssY) {
162
- const displayCanvas = this.getDisplayCanvas();
163
- const rect = displayCanvas.getBoundingClientRect();
164
- const relative = [cssX - rect.left, cssY - rect.top];
165
- if (this.config.pixelResolution) {
166
- // In pixel mode: CSS position (as fraction of CSS size) × game size = game position
167
- const gameSize = this.config.pixelResolution;
168
- return Vec2.mul(relative, [gameSize[0] / rect.width, gameSize[1] / rect.height]);
156
+ /** Canvas to render to. Pixel canvas in pixel mode, display canvas otherwise. */
157
+ getRenderTarget() {
158
+ if (this.pixelCanvas && this.pixelCtx) {
159
+ return { canvas: this.pixelCanvas, ctx: this.pixelCtx };
169
160
  }
170
- else {
171
- // In native mode, canvas fills the container completely at position 0,0
172
- // Mouse coordinates should be relative to the canvas, accounting for the fact
173
- // that the canvas internal pixel size != CSS size
174
- const pixelRatio = window.devicePixelRatio || 1;
175
- return Vec2.mul(relative, pixelRatio);
161
+ return { canvas: this.canvas, ctx: this.ctx };
162
+ }
163
+ /** Render target size in pixels. Pixel resolution in pixel mode, scaled size otherwise. */
164
+ getCanvasSize() {
165
+ const target = this.getRenderTarget();
166
+ return [target.canvas.width, target.canvas.height];
167
+ }
168
+ transformMousePosition(offsetX, offsetY) {
169
+ if (this.config.pixelResolution) {
170
+ const rect = this.canvas.getBoundingClientRect();
171
+ return [
172
+ offsetX * (this.config.pixelResolution[0] / rect.width),
173
+ offsetY * (this.config.pixelResolution[1] / rect.height),
174
+ ];
176
175
  }
176
+ const pixelRatio = window.devicePixelRatio || 1;
177
+ return [offsetX * pixelRatio, offsetY * pixelRatio];
177
178
  }
178
179
  }
@@ -1,4 +1,5 @@
1
1
  import type { Vector2 } from './vector2';
2
+ /** Game events. All events flow through handleEvent; these are also available as individual callbacks. */
2
3
  export type EventMap = {
3
4
  load: [];
4
5
  update: [dt: number];
@@ -6,8 +7,14 @@ export type EventMap = {
6
7
  resize: [size: Vector2, pixelSize: Vector2, fullscreen: boolean];
7
8
  keypressed: [scancode: string, keycode: string];
8
9
  keyreleased: [scancode: string, keycode: string];
9
- mousepressed: [x: number, y: number, button: number];
10
- mousereleased: [x: number, y: number, button: number];
10
+ focus: [];
11
+ blur: [];
12
+ /** Mouse moved. relative=true means pos is delta [dx, dy] (pointer lock). */
13
+ mousemoved: [pos: Vector2, relative: boolean];
14
+ /** Mouse button pressed. pos in canvas pixels. Button 1 = left, 2 = middle, 3 = right. */
15
+ mousepressed: [pos: Vector2, button: number];
16
+ /** Mouse button released. */
17
+ mousereleased: [pos: Vector2, button: number];
11
18
  gamepadpressed: [gamepadIndex: number, buttonIndex: number, buttonName: string];
12
19
  gamepadreleased: [gamepadIndex: number, buttonIndex: number, buttonName: string];
13
20
  actionpressed: [action: string];
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/core/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,EAAE,CAAC;IACT,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACrB,IAAI,EAAE,EAAE,CAAC;IACT,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IACjE,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAChD,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IACjD,YAAY,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACrD,aAAa,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACtD,cAAc,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IAChF,eAAe,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IACjF,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC;AAGvC,MAAM,MAAM,WAAW,GAAG;KACvB,CAAC,IAAI,SAAS,GAAG;QAAE,IAAI,EAAE,CAAC,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;CACpE,CAAC,SAAS,CAAC,CAAC"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/core/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,0GAA0G;AAC1G,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,EAAE,CAAC;IACT,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACrB,IAAI,EAAE,EAAE,CAAC;IACT,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IACjE,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAChD,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IACjD,KAAK,EAAE,EAAE,CAAC;IACV,IAAI,EAAE,EAAE,CAAC;IACT,6EAA6E;IAC7E,UAAU,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC9C,0FAA0F;IAC1F,YAAY,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,6BAA6B;IAC7B,aAAa,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,cAAc,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IAChF,eAAe,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IACjF,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC;AAGvC,MAAM,MAAM,WAAW,GAAG;KACvB,CAAC,IAAI,SAAS,GAAG;QAAE,IAAI,EAAE,CAAC,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;CACpE,CAAC,SAAS,CAAC,CAAC"}
@@ -56,6 +56,7 @@ export declare function getCanvasSize(s: GraphicsState): Vector2;
56
56
  export declare function newImage(_s: GraphicsState, path: string): ImageHandle;
57
57
  export declare function newCanvas(s: GraphicsState, size: Vector2): Canvas;
58
58
  export declare function setCanvas(s: GraphicsState, canvas?: Canvas | null): void;
59
+ export declare function setScreenContext(s: GraphicsState, ctx: CanvasRenderingContext2D): void;
59
60
  export declare function clip(s: GraphicsState, rect?: Rect): void;
60
61
  export declare function polygon(s: GraphicsState, mode: DrawMode, color: Color, points: Vector2[], props?: ShapeProps): void;
61
62
  export declare function points(s: GraphicsState, color: Color, pts: Vector2[]): void;
@@ -1 +1 @@
1
- {"version":3,"file":"graphics.d.ts","sourceRoot":"","sources":["../../src/core/graphics.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"graphics.d.ts","sourceRoot":"","sources":["../../src/core/graphics.ts"],"names":[],"mappings":"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"}
@@ -216,6 +216,10 @@ export function newCanvas(s, size) {
216
216
  export function setCanvas(s, canvas) {
217
217
  s.currentCtx = canvas?.ctx ?? s.screenCtx;
218
218
  }
219
+ export function setScreenContext(s, ctx) {
220
+ s.screenCtx = ctx;
221
+ s.currentCtx = ctx;
222
+ }
219
223
  export function clip(s, rect) {
220
224
  const ctx = s.currentCtx;
221
225
  ctx.beginPath();
@@ -1,10 +1,11 @@
1
1
  export declare class Keyboard {
2
2
  private pressedScancodes;
3
3
  onKeyEvent?: (scancode: string, keycode: string, type: 'keydown' | 'keyup') => void;
4
+ private canvas;
4
5
  private keydownHandler;
5
6
  private keyupHandler;
6
7
  private blurHandler;
7
- constructor();
8
+ constructor(canvas: HTMLCanvasElement | null);
8
9
  private handleKeyDown;
9
10
  private handleKeyUp;
10
11
  private handleBlur;
@@ -1 +1 @@
1
- {"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../../src/core/keyboard.ts"],"names":[],"mappings":"AAAA,qBAAa,QAAQ;IACnB,OAAO,CAAC,gBAAgB,CAAqB;IACtC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,KAAK,IAAI,CAAC;IAG3F,OAAO,CAAC,cAAc,CAAwC;IAC9D,OAAO,CAAC,YAAY,CAAwC;IAC5D,OAAO,CAAC,WAAW,CAAa;;IAchC,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,UAAU;IAIlB,OAAO,IAAI,IAAI;IAOf,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIjC,SAAS,CAAC,GAAG,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO;CAG3C"}
1
+ {"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../../src/core/keyboard.ts"],"names":[],"mappings":"AAAA,qBAAa,QAAQ;IACnB,OAAO,CAAC,gBAAgB,CAAqB;IACtC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,KAAK,IAAI,CAAC;IAC3F,OAAO,CAAC,MAAM,CAAkC;IAGhD,OAAO,CAAC,cAAc,CAAwC;IAC9D,OAAO,CAAC,YAAY,CAAwC;IAC5D,OAAO,CAAC,WAAW,CAAa;gBAEpB,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAc5C,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,UAAU;IAIlB,OAAO,IAAI,IAAI;IASf,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIjC,SAAS,CAAC,GAAG,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO;CAG3C"}
@@ -1,5 +1,5 @@
1
1
  export class Keyboard {
2
- constructor() {
2
+ constructor(canvas) {
3
3
  Object.defineProperty(this, "pressedScancodes", {
4
4
  enumerable: true,
5
5
  configurable: true,
@@ -12,6 +12,12 @@ export class Keyboard {
12
12
  writable: true,
13
13
  value: void 0
14
14
  });
15
+ Object.defineProperty(this, "canvas", {
16
+ enumerable: true,
17
+ configurable: true,
18
+ writable: true,
19
+ value: null
20
+ });
15
21
  // Event handler references for cleanup
16
22
  Object.defineProperty(this, "keydownHandler", {
17
23
  enumerable: true,
@@ -31,16 +37,21 @@ export class Keyboard {
31
37
  writable: true,
32
38
  value: void 0
33
39
  });
34
- // Bind event handlers
40
+ this.canvas = canvas;
35
41
  this.keydownHandler = this.handleKeyDown.bind(this);
36
42
  this.keyupHandler = this.handleKeyUp.bind(this);
37
43
  this.blurHandler = this.handleBlur.bind(this);
38
- // Register event listeners
39
- window.addEventListener('keydown', this.keydownHandler);
40
- window.addEventListener('keyup', this.keyupHandler);
41
- window.addEventListener('blur', this.blurHandler);
44
+ if (this.canvas) {
45
+ this.canvas.addEventListener('keydown', this.keydownHandler);
46
+ this.canvas.addEventListener('keyup', this.keyupHandler);
47
+ this.canvas.addEventListener('blur', this.blurHandler);
48
+ }
42
49
  }
43
50
  handleKeyDown(e) {
51
+ const scrollKeys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Space', 'PageUp', 'PageDown', 'Home', 'End'];
52
+ if (scrollKeys.includes(e.code)) {
53
+ e.preventDefault();
54
+ }
44
55
  if (e.code) {
45
56
  this.pressedScancodes.add(e.code);
46
57
  }
@@ -56,9 +67,11 @@ export class Keyboard {
56
67
  this.pressedScancodes.clear();
57
68
  }
58
69
  dispose() {
59
- window.removeEventListener('keydown', this.keydownHandler);
60
- window.removeEventListener('keyup', this.keyupHandler);
61
- window.removeEventListener('blur', this.blurHandler);
70
+ if (this.canvas) {
71
+ this.canvas.removeEventListener('keydown', this.keydownHandler);
72
+ this.canvas.removeEventListener('keyup', this.keyupHandler);
73
+ this.canvas.removeEventListener('blur', this.blurHandler);
74
+ }
62
75
  this.pressedScancodes.clear();
63
76
  }
64
77
  isDown(scancode) {
@@ -28,7 +28,7 @@ export interface Like {
28
28
  /** Gamepad input handling */
29
29
  readonly gamepad: Gamepad;
30
30
  /** Graphics context for rendering operations */
31
- readonly gfx: BoundGraphics;
31
+ gfx: BoundGraphics;
32
32
  /**
33
33
  * Set the canvas display mode.
34
34
  * @param mode - Partial canvas mode configuration
@@ -1 +1 @@
1
- {"version":3,"file":"like.d.ts","sourceRoot":"","sources":["../../src/core/like.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEtC;;;;;GAKG;AACH,MAAM,WAAW,IAAI;IACnB,mDAAmD;IACnD,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAEtB,qDAAqD;IACrD,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAEtB,mDAAmD;IACnD,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAEtB,8BAA8B;IAC9B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAE5B,2BAA2B;IAC3B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAEtB,6BAA6B;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAE1B,gDAAgD;IAChD,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAC;IAE5B;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAEvC;;;OAGG;IACH,OAAO,IAAI,UAAU,GAAG,SAAS,CAAC;IAElC;;;OAGG;IACH,aAAa,IAAI,OAAO,CAAC;IAEzB;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC;CACrC;AAGD,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC5D,YAAY,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC9D,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,YAAY,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAC7D,YAAY,EAAE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACxE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"like.d.ts","sourceRoot":"","sources":["../../src/core/like.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEtC;;;;;GAKG;AACH,MAAM,WAAW,IAAI;IACnB,mDAAmD;IACnD,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAEtB,qDAAqD;IACrD,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAEtB,mDAAmD;IACnD,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAEtB,8BAA8B;IAC9B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAE5B,2BAA2B;IAC3B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAEtB,6BAA6B;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAE1B,gDAAgD;IAChD,GAAG,EAAE,aAAa,CAAC;IAEnB;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAEvC;;;OAGG;IACH,OAAO,IAAI,UAAU,GAAG,SAAS,CAAC;IAElC;;;OAGG;IACH,aAAa,IAAI,OAAO,CAAC;IAEzB;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC;CACrC;AAGD,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC5D,YAAY,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC9D,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,YAAY,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAC7D,YAAY,EAAE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACxE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1,29 +1,45 @@
1
1
  import type { Vector2 } from './vector2';
2
- export type MousePositionTransform = (cssX: number, cssY: number) => Vector2;
2
+ export type MousePositionTransform = (offsetX: number, offsetY: number) => Vector2;
3
+ export type MouseMoveHandler = (pos: Vector2, relative: boolean) => void;
4
+ export type MouseButtonHandler = (pos: Vector2, button: number) => void;
5
+ /**
6
+ * Mouse input handling. Bound to canvas. Emits relative movement when pointer locked.
7
+ * Buttons: 1 = left, 2 = middle, 3 = right.
8
+ */
3
9
  export declare class Mouse {
4
10
  private x;
5
11
  private y;
6
12
  private buttons;
7
- onMouseEvent?: (clientX: number, clientY: number, button: number | undefined, type: 'mousemove' | 'mousedown' | 'mouseup') => void;
13
+ private cursorVisible;
14
+ onMouseMove?: MouseMoveHandler;
15
+ onMouseDown?: MouseButtonHandler;
16
+ onMouseUp?: MouseButtonHandler;
8
17
  private transformFn?;
18
+ private canvas;
9
19
  private mousemoveHandler;
10
20
  private mousedownHandler;
11
21
  private mouseupHandler;
12
- private blurHandler;
13
- constructor(transformFn?: MousePositionTransform);
22
+ private wheelHandler;
23
+ constructor(canvas: HTMLCanvasElement | null, transformFn?: MousePositionTransform);
14
24
  setTransform(transformFn: MousePositionTransform | undefined): void;
15
25
  private handleMouseMove;
16
26
  private handleMouseDown;
17
27
  private handleMouseUp;
18
- private handleBlur;
28
+ private handleWheel;
19
29
  dispose(): void;
30
+ /** Mouse position in canvas pixels. */
20
31
  getPosition(): Vector2;
21
- getX(): number;
22
- getY(): number;
32
+ /** Check if button is held. Button 1 = left, 2 = middle, 3 = right. */
23
33
  isDown(button: number): boolean;
34
+ /** All currently held buttons. */
24
35
  getPressedButtons(): Set<number>;
25
- isVisible(): boolean;
26
- setVisible(visible: boolean, canvas?: HTMLCanvasElement): void;
27
- getRelativeMode(): boolean;
36
+ /** True when pointer is locked to canvas. */
37
+ isPointerLocked(): boolean;
38
+ /** Lock or unlock pointer. When locked, mousemoved emits relative deltas. */
39
+ lockPointer(locked: boolean): void;
40
+ /** Show or hide cursor. Unlike pointer lock, cursor can still leave canvas. */
41
+ showCursor(visible: boolean): void;
42
+ /** Current cursor visibility state. */
43
+ isCursorVisible(): boolean;
28
44
  }
29
45
  //# sourceMappingURL=mouse.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mouse.d.ts","sourceRoot":"","sources":["../../src/core/mouse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,MAAM,sBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;AAE7E,qBAAa,KAAK;IAChB,OAAO,CAAC,CAAC,CAAK;IACd,OAAO,CAAC,CAAC,CAAK;IACd,OAAO,CAAC,OAAO,CAAqB;IAC7B,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,WAAW,GAAG,WAAW,GAAG,SAAS,KAAK,IAAI,CAAC;IAC1I,OAAO,CAAC,WAAW,CAAC,CAAyB;IAG7C,OAAO,CAAC,gBAAgB,CAAqC;IAC7D,OAAO,CAAC,gBAAgB,CAAqC;IAC7D,OAAO,CAAC,cAAc,CAAqC;IAC3D,OAAO,CAAC,WAAW,CAAa;gBAEpB,WAAW,CAAC,EAAE,sBAAsB;IAgBhD,YAAY,CAAC,WAAW,EAAE,sBAAsB,GAAG,SAAS,GAAG,IAAI;IAInE,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,eAAe;IAKvB,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,UAAU;IAIlB,OAAO,IAAI,IAAI;IAQf,WAAW,IAAI,OAAO;IAOtB,IAAI,IAAI,MAAM;IAId,IAAI,IAAI,MAAM;IAId,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAI/B,iBAAiB,IAAI,GAAG,CAAC,MAAM,CAAC;IAIhC,SAAS,IAAI,OAAO;IAIpB,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,iBAAiB,GAAG,IAAI;IAQ9D,eAAe,IAAI,OAAO;CAG3B"}
1
+ {"version":3,"file":"mouse.d.ts","sourceRoot":"","sources":["../../src/core/mouse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;AACnF,MAAM,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;AACzE,MAAM,MAAM,kBAAkB,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AAExE;;;GAGG;AACH,qBAAa,KAAK;IAChB,OAAO,CAAC,CAAC,CAAK;IACd,OAAO,CAAC,CAAC,CAAK;IACd,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,aAAa,CAAQ;IACtB,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,SAAS,CAAC,EAAE,kBAAkB,CAAC;IACtC,OAAO,CAAC,WAAW,CAAC,CAAyB;IAC7C,OAAO,CAAC,MAAM,CAAkC;IAGhD,OAAO,CAAC,gBAAgB,CAAqC;IAC7D,OAAO,CAAC,gBAAgB,CAAqC;IAC7D,OAAO,CAAC,cAAc,CAAqC;IAC3D,OAAO,CAAC,YAAY,CAA0B;gBAElC,MAAM,EAAE,iBAAiB,GAAG,IAAI,EAAE,WAAW,CAAC,EAAE,sBAAsB;IAqBlF,YAAY,CAAC,WAAW,EAAE,sBAAsB,GAAG,SAAS,GAAG,IAAI;IAInE,OAAO,CAAC,eAAe;IAavB,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,WAAW;IAInB,OAAO,IAAI,IAAI;IAUf,uCAAuC;IACvC,WAAW,IAAI,OAAO;IAOtB,uEAAuE;IACvE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAI/B,kCAAkC;IAClC,iBAAiB,IAAI,GAAG,CAAC,MAAM,CAAC;IAIhC,6CAA6C;IAC7C,eAAe,IAAI,OAAO;IAI1B,6EAA6E;IAC7E,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAUlC,+EAA+E;IAC/E,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAOlC,uCAAuC;IACvC,eAAe,IAAI,OAAO;CAG3B"}
@@ -1,5 +1,9 @@
1
+ /**
2
+ * Mouse input handling. Bound to canvas. Emits relative movement when pointer locked.
3
+ * Buttons: 1 = left, 2 = middle, 3 = right.
4
+ */
1
5
  export class Mouse {
2
- constructor(transformFn) {
6
+ constructor(canvas, transformFn) {
3
7
  Object.defineProperty(this, "x", {
4
8
  enumerable: true,
5
9
  configurable: true,
@@ -18,7 +22,25 @@ export class Mouse {
18
22
  writable: true,
19
23
  value: new Set()
20
24
  });
21
- Object.defineProperty(this, "onMouseEvent", {
25
+ Object.defineProperty(this, "cursorVisible", {
26
+ enumerable: true,
27
+ configurable: true,
28
+ writable: true,
29
+ value: true
30
+ });
31
+ Object.defineProperty(this, "onMouseMove", {
32
+ enumerable: true,
33
+ configurable: true,
34
+ writable: true,
35
+ value: void 0
36
+ });
37
+ Object.defineProperty(this, "onMouseDown", {
38
+ enumerable: true,
39
+ configurable: true,
40
+ writable: true,
41
+ value: void 0
42
+ });
43
+ Object.defineProperty(this, "onMouseUp", {
22
44
  enumerable: true,
23
45
  configurable: true,
24
46
  writable: true,
@@ -30,6 +52,12 @@ export class Mouse {
30
52
  writable: true,
31
53
  value: void 0
32
54
  });
55
+ Object.defineProperty(this, "canvas", {
56
+ enumerable: true,
57
+ configurable: true,
58
+ writable: true,
59
+ value: null
60
+ });
33
61
  // Event handler references for cleanup
34
62
  Object.defineProperty(this, "mousemoveHandler", {
35
63
  enumerable: true,
@@ -49,82 +77,106 @@ export class Mouse {
49
77
  writable: true,
50
78
  value: void 0
51
79
  });
52
- Object.defineProperty(this, "blurHandler", {
80
+ Object.defineProperty(this, "wheelHandler", {
53
81
  enumerable: true,
54
82
  configurable: true,
55
83
  writable: true,
56
84
  value: void 0
57
85
  });
86
+ this.canvas = canvas;
58
87
  this.transformFn = transformFn;
59
- // Bind event handlers
88
+ if (this.canvas) {
89
+ this.canvas.tabIndex = 0;
90
+ }
60
91
  this.mousemoveHandler = this.handleMouseMove.bind(this);
61
92
  this.mousedownHandler = this.handleMouseDown.bind(this);
62
93
  this.mouseupHandler = this.handleMouseUp.bind(this);
63
- this.blurHandler = this.handleBlur.bind(this);
64
- // Register event listeners
65
- window.addEventListener('mousemove', this.mousemoveHandler);
66
- window.addEventListener('mousedown', this.mousedownHandler);
67
- window.addEventListener('mouseup', this.mouseupHandler);
68
- window.addEventListener('blur', this.blurHandler);
94
+ this.wheelHandler = this.handleWheel.bind(this);
95
+ if (this.canvas) {
96
+ this.canvas.addEventListener('mousemove', this.mousemoveHandler);
97
+ this.canvas.addEventListener('mousedown', this.mousedownHandler);
98
+ window.addEventListener('mouseup', this.mouseupHandler);
99
+ this.canvas.addEventListener('wheel', this.wheelHandler, { passive: false });
100
+ }
69
101
  }
70
102
  setTransform(transformFn) {
71
103
  this.transformFn = transformFn;
72
104
  }
73
105
  handleMouseMove(e) {
74
- // Store raw CSS coordinates - transformation to game coordinates
75
- // should be done by the consumer using engine.transformMousePosition()
76
- this.x = e.clientX;
77
- this.y = e.clientY;
78
- this.onMouseEvent?.(e.clientX, e.clientY, undefined, 'mousemove');
106
+ if (this.isPointerLocked()) {
107
+ // When locked, emit relative movement
108
+ this.onMouseMove?.([e.movementX, e.movementY], true);
109
+ }
110
+ else {
111
+ // Normal mode: track position and emit absolute coords
112
+ this.x = e.offsetX;
113
+ this.y = e.offsetY;
114
+ const pos = this.getPosition();
115
+ this.onMouseMove?.(pos, false);
116
+ }
79
117
  }
80
118
  handleMouseDown(e) {
81
119
  this.buttons.add(e.button + 1);
82
- this.onMouseEvent?.(e.clientX, e.clientY, e.button, 'mousedown');
120
+ const pos = this.transformFn ? this.transformFn(e.offsetX, e.offsetY) : [e.offsetX, e.offsetY];
121
+ this.onMouseDown?.(pos, e.button + 1);
122
+ this.canvas?.focus();
83
123
  }
84
124
  handleMouseUp(e) {
85
125
  this.buttons.delete(e.button + 1);
86
- this.onMouseEvent?.(e.clientX, e.clientY, e.button, 'mouseup');
126
+ const pos = this.transformFn ? this.transformFn(e.offsetX, e.offsetY) : [e.offsetX, e.offsetY];
127
+ this.onMouseUp?.(pos, e.button + 1);
87
128
  }
88
- handleBlur() {
89
- this.buttons.clear();
129
+ handleWheel(e) {
130
+ e.preventDefault();
90
131
  }
91
132
  dispose() {
92
- window.removeEventListener('mousemove', this.mousemoveHandler);
93
- window.removeEventListener('mousedown', this.mousedownHandler);
133
+ if (this.canvas) {
134
+ this.canvas.removeEventListener('mousemove', this.mousemoveHandler);
135
+ this.canvas.removeEventListener('mousedown', this.mousedownHandler);
136
+ this.canvas.removeEventListener('wheel', this.wheelHandler);
137
+ }
94
138
  window.removeEventListener('mouseup', this.mouseupHandler);
95
- window.removeEventListener('blur', this.blurHandler);
96
139
  this.buttons.clear();
97
140
  }
141
+ /** Mouse position in canvas pixels. */
98
142
  getPosition() {
99
143
  if (this.transformFn) {
100
144
  return this.transformFn(this.x, this.y);
101
145
  }
102
146
  return [this.x, this.y];
103
147
  }
104
- getX() {
105
- return this.x;
106
- }
107
- getY() {
108
- return this.y;
109
- }
148
+ /** Check if button is held. Button 1 = left, 2 = middle, 3 = right. */
110
149
  isDown(button) {
111
150
  return this.buttons.has(button);
112
151
  }
152
+ /** All currently held buttons. */
113
153
  getPressedButtons() {
114
154
  return new Set(this.buttons);
115
155
  }
116
- isVisible() {
117
- return document.pointerLockElement === null;
156
+ /** True when pointer is locked to canvas. */
157
+ isPointerLocked() {
158
+ return document.pointerLockElement !== null;
118
159
  }
119
- setVisible(visible, canvas) {
120
- if (!visible && canvas) {
121
- canvas.requestPointerLock();
160
+ /** Lock or unlock pointer. When locked, mousemoved emits relative deltas. */
161
+ lockPointer(locked) {
162
+ if (!this.canvas)
163
+ return;
164
+ if (locked && document.pointerLockElement !== this.canvas) {
165
+ this.canvas.requestPointerLock();
122
166
  }
123
- else if (visible && canvas && document.pointerLockElement === canvas) {
167
+ else if (!locked && document.pointerLockElement === this.canvas) {
124
168
  document.exitPointerLock();
125
169
  }
126
170
  }
127
- getRelativeMode() {
128
- return document.pointerLockElement !== null;
171
+ /** Show or hide cursor. Unlike pointer lock, cursor can still leave canvas. */
172
+ showCursor(visible) {
173
+ this.cursorVisible = visible;
174
+ if (this.canvas) {
175
+ this.canvas.style.cursor = visible ? 'auto' : 'none';
176
+ }
177
+ }
178
+ /** Current cursor visibility state. */
179
+ isCursorVisible() {
180
+ return this.cursorVisible;
129
181
  }
130
182
  }
package/dist/engine.d.ts CHANGED
@@ -3,13 +3,18 @@ import type { PartialCanvasMode } from './core/canvas-config';
3
3
  import type { Like } from './core/like';
4
4
  export declare class Engine {
5
5
  private canvas;
6
- private ctx;
7
6
  private isRunning;
8
7
  private lastTime;
9
8
  private container;
10
9
  private canvasManager;
11
10
  private handleEvent;
12
11
  private currentScene;
12
+ private gfxState;
13
+ private windowFocusHandler;
14
+ private windowBlurHandler;
15
+ private canvasFocusHandler;
16
+ private canvasBlurHandler;
17
+ private fullscreenChangeHandler;
13
18
  readonly like: Like;
14
19
  constructor(container: HTMLElement);
15
20
  private dispatch;
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAa,MAAM,eAAe,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAIxC,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,GAAG,CAA2B;IACtC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,WAAW,CAA+C;IAClE,OAAO,CAAC,YAAY,CAAsB;IAE1C,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;gBAER,SAAS,EAAE,WAAW;IAkElC,OAAO,CAAC,QAAQ;IAchB,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI;IAWhC,KAAK,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BrE,OAAO,IAAI,IAAI;CAUhB"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAa,MAAM,eAAe,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAIxC,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,WAAW,CAA+C;IAClE,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,QAAQ,CAA8B;IAG9C,OAAO,CAAC,kBAAkB,CAA6B;IACvD,OAAO,CAAC,iBAAiB,CAA6B;IACtD,OAAO,CAAC,kBAAkB,CAA6B;IACvD,OAAO,CAAC,iBAAiB,CAA6B;IACtD,OAAO,CAAC,uBAAuB,CAA6B;IAE5D,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;gBAER,SAAS,EAAE,WAAW;IAqFlC,OAAO,CAAC,QAAQ;IAchB,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI;IAUhC,KAAK,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BrE,OAAO,IAAI,IAAI;CAiBhB"}
package/dist/engine.js CHANGED
@@ -14,12 +14,6 @@ export class Engine {
14
14
  writable: true,
15
15
  value: void 0
16
16
  });
17
- Object.defineProperty(this, "ctx", {
18
- enumerable: true,
19
- configurable: true,
20
- writable: true,
21
- value: void 0
22
- });
23
17
  Object.defineProperty(this, "isRunning", {
24
18
  enumerable: true,
25
19
  configurable: true,
@@ -56,6 +50,43 @@ export class Engine {
56
50
  writable: true,
57
51
  value: null
58
52
  });
53
+ Object.defineProperty(this, "gfxState", {
54
+ enumerable: true,
55
+ configurable: true,
56
+ writable: true,
57
+ value: void 0
58
+ });
59
+ // Event handler references for cleanup
60
+ Object.defineProperty(this, "windowFocusHandler", {
61
+ enumerable: true,
62
+ configurable: true,
63
+ writable: true,
64
+ value: null
65
+ });
66
+ Object.defineProperty(this, "windowBlurHandler", {
67
+ enumerable: true,
68
+ configurable: true,
69
+ writable: true,
70
+ value: null
71
+ });
72
+ Object.defineProperty(this, "canvasFocusHandler", {
73
+ enumerable: true,
74
+ configurable: true,
75
+ writable: true,
76
+ value: null
77
+ });
78
+ Object.defineProperty(this, "canvasBlurHandler", {
79
+ enumerable: true,
80
+ configurable: true,
81
+ writable: true,
82
+ value: null
83
+ });
84
+ Object.defineProperty(this, "fullscreenChangeHandler", {
85
+ enumerable: true,
86
+ configurable: true,
87
+ writable: true,
88
+ value: null
89
+ });
59
90
  Object.defineProperty(this, "like", {
60
91
  enumerable: true,
61
92
  configurable: true,
@@ -68,16 +99,16 @@ export class Engine {
68
99
  const ctx = this.canvas.getContext('2d');
69
100
  if (!ctx)
70
101
  throw new Error('Failed to get 2D context');
71
- this.ctx = ctx;
72
102
  this.container = container;
73
103
  this.container.appendChild(this.canvas);
74
- this.canvasManager = new CanvasManager(this.canvas, this.container, this.ctx, { pixelResolution: null, fullscreen: false });
75
- const gfxState = newState(this.ctx);
76
- const gfx = bindGraphics(gfxState);
104
+ this.canvasManager = new CanvasManager(this.canvas, this.container, ctx, { pixelResolution: null, fullscreen: false });
105
+ const renderTarget = this.canvasManager.getRenderTarget();
106
+ this.gfxState = newState(renderTarget.ctx);
107
+ let gfx = bindGraphics(this.gfxState);
77
108
  const audio = new Audio();
78
109
  const timer = new Timer();
79
- const keyboard = new Keyboard();
80
- const mouse = new Mouse((cssX, cssY) => this.canvasManager.transformMousePosition(cssX, cssY));
110
+ const keyboard = new Keyboard(this.canvas);
111
+ const mouse = new Mouse(this.canvas, (cssX, cssY) => this.canvasManager.transformMousePosition(cssX, cssY));
81
112
  const gamepad = new Gamepad();
82
113
  const input = new Input({ keyboard, mouse, gamepad });
83
114
  this.like = {
@@ -90,32 +121,48 @@ export class Engine {
90
121
  gfx,
91
122
  setMode: (m) => this.setMode(m),
92
123
  getMode: () => this.canvasManager.getMode(),
93
- getCanvasSize: () => [this.canvas.width, this.canvas.height],
124
+ getCanvasSize: () => this.canvasManager.getCanvasSize(),
94
125
  setScene: (scene) => {
95
126
  this.currentScene = scene;
96
127
  scene?.load?.(this.like);
97
128
  },
98
129
  };
130
+ this.canvasManager.onResize = () => {
131
+ const target = this.canvasManager.getRenderTarget();
132
+ this.gfxState = newState(target.ctx);
133
+ this.like.gfx = bindGraphics(this.gfxState);
134
+ };
99
135
  keyboard.onKeyEvent = (scancode, keycode, type) => {
100
136
  this.dispatch(type === 'keydown' ? 'keypressed' : 'keyreleased', [scancode, keycode]);
101
137
  };
102
- mouse.onMouseEvent = (clientX, clientY, button, type) => {
103
- const [x, y] = this.canvasManager.transformMousePosition(clientX, clientY);
104
- this.dispatch(type === 'mousedown' ? 'mousepressed' : 'mousereleased', [x, y, (button ?? 0) + 1]);
138
+ mouse.onMouseMove = (pos, relative) => {
139
+ this.dispatch('mousemoved', [pos, relative]);
140
+ };
141
+ mouse.onMouseDown = (pos, button) => {
142
+ this.dispatch('mousepressed', [pos, button]);
143
+ };
144
+ mouse.onMouseUp = (pos, button) => {
145
+ this.dispatch('mousereleased', [pos, button]);
105
146
  };
106
147
  gamepad.onButtonEvent = (gpIndex, buttonIndex, buttonName, pressed) => {
107
148
  this.dispatch(pressed ? 'gamepadpressed' : 'gamepadreleased', [gpIndex, buttonIndex, buttonName]);
108
149
  };
109
- this.canvasManager.onResize = (size, pixelSize, fullscreen) => {
110
- this.dispatch('resize', [size, pixelSize, fullscreen]);
111
- };
112
- document.addEventListener('fullscreenchange', () => {
150
+ this.windowFocusHandler = () => this.dispatch('focus', []);
151
+ this.windowBlurHandler = () => this.dispatch('blur', []);
152
+ this.canvasFocusHandler = () => this.dispatch('focus', []);
153
+ this.canvasBlurHandler = () => this.dispatch('blur', []);
154
+ this.fullscreenChangeHandler = () => {
113
155
  const mode = this.canvasManager.getMode();
114
156
  const isFullscreen = !!document.fullscreenElement;
115
157
  if (mode.fullscreen !== isFullscreen) {
116
158
  this.canvasManager.setMode({ ...mode, fullscreen: isFullscreen });
117
159
  }
118
- });
160
+ };
161
+ window.addEventListener('focus', this.windowFocusHandler);
162
+ window.addEventListener('blur', this.windowBlurHandler);
163
+ this.canvas.addEventListener('focus', this.canvasFocusHandler);
164
+ this.canvas.addEventListener('blur', this.canvasBlurHandler);
165
+ document.addEventListener('fullscreenchange', this.fullscreenChangeHandler);
119
166
  }
120
167
  dispatch(type, args) {
121
168
  if (!this.handleEvent)
@@ -132,11 +179,10 @@ export class Engine {
132
179
  }
133
180
  setMode(mode) {
134
181
  const currentMode = this.canvasManager.getMode();
135
- const mergedMode = { ...currentMode, ...mode };
136
- if (mode.fullscreen !== undefined && mode.fullscreen !== currentMode.fullscreen) {
137
- mergedMode.fullscreen ? this.container.requestFullscreen().catch(console.error) : document.exitFullscreen();
182
+ if ('fullscreen' in mode && mode.fullscreen !== currentMode.fullscreen) {
183
+ mode.fullscreen ? this.container.requestFullscreen().catch(console.error) : document.exitFullscreen();
138
184
  }
139
- this.canvasManager.setMode(mode);
185
+ this.canvasManager.setMode({ ...currentMode, ...mode });
140
186
  }
141
187
  async start(handleEvent) {
142
188
  this.handleEvent = handleEvent;
@@ -169,6 +215,16 @@ export class Engine {
169
215
  this.like.mouse.dispose();
170
216
  this.like.gamepad.dispose();
171
217
  this.canvasManager.dispose();
218
+ if (this.windowFocusHandler)
219
+ window.removeEventListener('focus', this.windowFocusHandler);
220
+ if (this.windowBlurHandler)
221
+ window.removeEventListener('blur', this.windowBlurHandler);
222
+ if (this.canvasFocusHandler)
223
+ this.canvas.removeEventListener('focus', this.canvasFocusHandler);
224
+ if (this.canvasBlurHandler)
225
+ this.canvas.removeEventListener('blur', this.canvasBlurHandler);
226
+ if (this.fullscreenChangeHandler)
227
+ document.removeEventListener('fullscreenchange', this.fullscreenChangeHandler);
172
228
  if (this.canvas.parentNode === this.container) {
173
229
  this.container.removeChild(this.canvas);
174
230
  }
@@ -13,6 +13,6 @@ export declare class StartupScene implements Scene {
13
13
  constructor(next: Scene, onDraw?: ((like: Like) => void) | undefined);
14
14
  load(like: Like): void;
15
15
  draw(like: Like): void;
16
- mousepressed(like: Like): void;
16
+ mousepressed(like: Like, _pos: [number, number], _button: number): void;
17
17
  }
18
18
  //# sourceMappingURL=startup.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"startup.d.ts","sourceRoot":"","sources":["../../src/scenes/startup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAM5C;;;;;;GAMG;AACH,qBAAa,YAAa,YAAW,KAAK;IAItC,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,MAAM,CAAC;IAJjB,OAAO,CAAC,IAAI,CAAe;gBAGjB,IAAI,EAAE,KAAK,EACX,MAAM,CAAC,GAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,aAAA;IAGvC,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAItB,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAWtB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;CAG/B"}
1
+ {"version":3,"file":"startup.d.ts","sourceRoot":"","sources":["../../src/scenes/startup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAM5C;;;;;;GAMG;AACH,qBAAa,YAAa,YAAW,KAAK;IAItC,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,MAAM,CAAC;IAJjB,OAAO,CAAC,IAAI,CAAe;gBAGjB,IAAI,EAAE,KAAK,EACX,MAAM,CAAC,GAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,aAAA;IAGvC,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAItB,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAWtB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;CAGxE"}
@@ -42,7 +42,7 @@ export class StartupScene {
42
42
  like.gfx.draw(this.logo, Vec2.div(winSize, 2), { scale, origin: Vec2.div(this.logo.size, 2) });
43
43
  }
44
44
  }
45
- mousepressed(like) {
45
+ mousepressed(like, _pos, _button) {
46
46
  like.setScene(this.next);
47
47
  }
48
48
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "like2d",
3
- "version": "2.7.4",
3
+ "version": "2.8.0",
4
4
  "description": "A web-native game framework inspired by Love2D",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",