@gamedevland/engine 0.0.8 → 0.0.9

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.0.9 — 2026-11-05
4
+
5
+ - Add opt-in `screen.dpr: 'native'` to target the viewport's physical pixels.
6
+ - Add `screen.render.maxCanvasPixels` to limit the backing canvas area.
7
+ - Apply size and resolution in one renderer resize. Existing numeric and `'auto'` DPR defaults stay the same.
8
+
3
9
  ## 0.0.8 — 2026-11-04
4
10
 
5
11
  - Publish the SDK source and package under MIT with public repository metadata.
@@ -14,4 +20,21 @@
14
20
 
15
21
  ## 0.0.7
16
22
 
23
+ - Expose runtime activity and native pointer metadata.
17
24
  - Dispose spawned prefab logical children idempotently and release their registry entries.
25
+
26
+ ## 0.0.5
27
+
28
+ - Prepare automated npm publishing.
29
+
30
+ ## 0.0.4
31
+
32
+ - Update package homepage and issue-tracker metadata.
33
+
34
+ ## 0.0.3
35
+
36
+ - Update repository metadata.
37
+
38
+ ## 0.0.2
39
+
40
+ - Add drag-end reasons and renderer-independent local node bounds.
package/README.md CHANGED
@@ -10,6 +10,12 @@ The npm package intentionally ships a compact public distribution:
10
10
 
11
11
  Source files are available in [the SDK repository](https://github.com/gamedevland/sdk/tree/main/packages/engine/src); the npm archive contains the compiled distribution.
12
12
 
13
+ ## Changelog
14
+
15
+ **0.0.9** adds opt-in viewport-native rendering and a configurable canvas pixel
16
+ budget. Existing DPR defaults stay the same.
17
+ [Full engine changelog](https://github.com/gamedevland/sdk/blob/main/packages/engine/CHANGELOG.md).
18
+
13
19
  ## Install
14
20
 
15
21
  ```bash
@@ -44,6 +50,20 @@ For `dragend` input events, `InputEventBase.dragEndReason` distinguishes a norma
44
50
 
45
51
  Layout nodes expose `getLocalBounds()` for renderer-independent local geometry queries.
46
52
 
53
+ ## Screen resolution
54
+
55
+ Logical landscape and portrait profiles define the game's coordinate system.
56
+ Set `system.screen.dpr: 'native'` to scale the backing canvas to the physical
57
+ pixels of the viewport, including when the game is embedded in an iframe.
58
+ For this mode, `maxDpr` caps the display density relative to CSS pixels.
59
+ Existing numeric `dpr` values and `'auto'` still multiply the logical canvas size.
60
+
61
+ Set `system.screen.render.maxCanvasPixels` to a positive integer to limit the
62
+ backing canvas area. The engine scales both axes together and preserves the
63
+ logical layout and pointer coordinates. Extremely small budgets may be exceeded
64
+ when required to keep both axes at least one pixel. This option caps the main
65
+ canvas independently of the optional `render.scaleFactor` pass.
66
+
47
67
  ## TypeScript
48
68
 
49
69
  ### Platform packaging and boot (0.0.8)
package/dist/sdk.d.ts CHANGED
@@ -2216,16 +2216,20 @@ export interface ScreenProfile {
2216
2216
  }
2217
2217
  export interface ScreenRenderConfig {
2218
2218
  scaleFactor?: number;
2219
+ /** Maximum backing canvas area in physical pixels. Independent of scaleFactor. */
2220
+ maxCanvasPixels?: number;
2219
2221
  }
2220
2222
  /**
2221
2223
  * Main configuration for screen behavior.
2222
2224
  * - `land`/`port`: virtual profiles for each orientation.
2223
- * - `dpr`: renderer resolution; 'auto' or a fixed number. Default is 1.
2225
+ * - `dpr`: fixed renderer resolution, 'auto' for browser DPR in virtual units,
2226
+ * or 'native' to target physical viewport pixels. Default is 1.
2227
+ * - `maxDpr`: caps the browser DPR in 'auto' and 'native' modes.
2224
2228
  */
2225
2229
  export interface ScreenConfig {
2226
2230
  land: ScreenProfile;
2227
2231
  port: ScreenProfile;
2228
- dpr?: "auto" | number;
2232
+ dpr?: "auto" | "native" | number;
2229
2233
  maxDpr?: number;
2230
2234
  render?: ScreenRenderConfig;
2231
2235
  }
@@ -2246,7 +2250,7 @@ export interface VirtualSize {
2246
2250
  export interface ScreenStateSnapshot {
2247
2251
  orientation: Orientation;
2248
2252
  viewport: ViewportSize;
2249
- /** Internal canvas size (the <canvas width/height> attributes), px. */
2253
+ /** Logical canvas size, before renderer resolution is applied. */
2250
2254
  canvas: {
2251
2255
  width: number;
2252
2256
  height: number;
@@ -2319,8 +2323,7 @@ export declare class ScreenManager {
2319
2323
  private applySnapshot;
2320
2324
  /**
2321
2325
  * Applies the current snapshot to the PIXI renderer and stage:
2322
- * - Sets device pixel ratio (renderer.resolution)
2323
- * - Resizes the internal canvas to the computed virtual size
2326
+ * - Resizes the renderer using the virtual size and backing canvas resolution
2324
2327
  * - Does NOT scale the stage: scaling is expected to be done via CSS size of the canvas
2325
2328
  */
2326
2329
  private applyToStage;
@@ -2331,12 +2334,7 @@ export declare class ScreenManager {
2331
2334
  onChange(handler: (snapshot: ScreenStateSnapshot) => void): () => void;
2332
2335
  /** Notifies subscribers with a cloned snapshot to prevent outside mutation. */
2333
2336
  private notifyChange;
2334
- /**
2335
- * Resolves the device pixel ratio to use for the renderer's resolution.
2336
- * - `dpr: 'auto'` uses the browser DPR (retina-aware).
2337
- * - numeric `dpr` uses the provided fixed value.
2338
- * - missing/invalid values fall back to 1.
2339
- */
2337
+ private resolveResolution;
2340
2338
  private resolveDpr;
2341
2339
  /**
2342
2340
  * Returns the center point of the virtual canvas in virtual coordinates.
package/dist/sdk.js CHANGED
@@ -37371,7 +37371,10 @@ var eF = class {
37371
37371
  changeHandlers = /* @__PURE__ */ new Set();
37372
37372
  requestRender;
37373
37373
  constructor(e, i) {
37374
- this.app = e, this.config = i, this.scaler = new WF(i);
37374
+ this.app = e, this.config = i;
37375
+ const s = i.render?.maxCanvasPixels;
37376
+ if (s !== void 0 && (!Number.isSafeInteger(s) || s < 1)) throw new RangeError("ScreenManager: render.maxCanvasPixels must be a positive safe integer");
37377
+ this.scaler = new WF(i);
37375
37378
  }
37376
37379
  async init() {
37377
37380
  const e = await this.awaitInitialSnapshot();
@@ -37387,14 +37390,14 @@ var eF = class {
37387
37390
  e && this.applySnapshot(e);
37388
37391
  }
37389
37392
  applySnapshot(e) {
37390
- const i = this.hasChanged(this.prev, e);
37391
- this.snapshot = e, i && (this.applyToStage(), this.prev = { ...e }, this.notifyChange());
37393
+ const i = this.resolveResolution(e), s = this.hasChanged(this.prev, e) || this.app.renderer.resolution !== i;
37394
+ this.snapshot = e, s && (this.applyToStage(i), this.prev = { ...e }, this.notifyChange());
37392
37395
  }
37393
- applyToStage() {
37394
- const { canvas: e, viewport: i } = this.snapshot, s = this.resolveDpr();
37395
- this.app.renderer.resolution = s, this.app.renderer.resize(e.width, e.height);
37396
+ applyToStage(e) {
37397
+ const { canvas: i, viewport: s } = this.snapshot;
37398
+ this.app.renderer.resize(i.width, i.height, e);
37396
37399
  const r = this.app.canvas;
37397
- r && r.style && (r.style.width = `${i.width}px`, r.style.height = `${i.height}px`), this.app.stage.scale.set(1), this.app.stage.pivot.set(0, 0), this.app.stage.position.set(0, 0), this.requestRender?.();
37400
+ r && r.style && (r.style.width = `${s.width}px`, r.style.height = `${s.height}px`), this.app.stage.scale.set(1), this.app.stage.pivot.set(0, 0), this.app.stage.position.set(0, 0), this.requestRender?.();
37398
37401
  }
37399
37402
  onChange(e) {
37400
37403
  return this.changeHandlers.add(e), () => this.changeHandlers.delete(e);
@@ -37411,14 +37414,25 @@ var eF = class {
37411
37414
  } catch {
37412
37415
  }
37413
37416
  }
37414
- resolveDpr() {
37415
- if (this.config.dpr === "auto") {
37416
- const e = window.devicePixelRatio;
37417
- if (typeof e != "number" || !Number.isFinite(e) || e <= 0) return 1;
37418
- const i = this.config.maxDpr;
37419
- return typeof i == "number" && Number.isFinite(i) && i > 0 ? Math.min(e, i) : e;
37420
- }
37421
- return typeof this.config.dpr == "number" && Number.isFinite(this.config.dpr) && this.config.dpr > 0 ? this.config.dpr : 1;
37417
+ resolveResolution(e) {
37418
+ const i = this.config.dpr;
37419
+ let s = this.resolveDpr(i);
37420
+ i === "native" && (s *= e.scale);
37421
+ const r = this.config.render?.maxCanvasPixels;
37422
+ if (r === void 0) return s;
37423
+ const { width: n, height: a } = e.canvas;
37424
+ if (Math.round(n * s) * Math.round(a * s) <= r) return s;
37425
+ const o = 0.5 / Math.min(n, a), l = o * (1 + Number.EPSILON), h = Math.max(l, Math.min(s, Math.sqrt(r / (n * a))));
37426
+ return Math.round(n * h) * Math.round(a * h) <= r ? h : Math.max(l, h - o);
37427
+ }
37428
+ resolveDpr(e) {
37429
+ if (e === "auto" || e === "native") {
37430
+ const i = window.devicePixelRatio;
37431
+ if (!Number.isFinite(i) || i <= 0) return 1;
37432
+ const s = this.config.maxDpr;
37433
+ return typeof s == "number" && Number.isFinite(s) && s > 0 ? Math.min(i, s) : i;
37434
+ }
37435
+ return typeof e == "number" && Number.isFinite(e) && e > 0 ? e : 1;
37422
37436
  }
37423
37437
  get center() {
37424
37438
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gamedevland/engine",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "type": "module",
5
5
  "description": "HTML5 game engine SDK for AI-assisted web game development.",
6
6
  "license": "MIT",
@@ -115,6 +115,7 @@
115
115
  }
116
116
  },
117
117
  "scripts": {
118
+ "test:screen": "node scripts/verify-screen.mjs",
118
119
  "test:resource-cleanup": "node scripts/verify-resource-cleanup.mjs",
119
120
  "clean": "rimraf dist *.tsbuildinfo",
120
121
  "typecheck": "tsc --noEmit",