minimojs 1.0.0-alpha.24 → 1.0.0-alpha.25

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.
@@ -304,18 +304,21 @@ export class RenderSystem {
304
304
  ctx.restore();
305
305
  }
306
306
  /**
307
- * Draws the frozen scene being left and, over its center, a ring whose
308
- * outline fills with the share of images loaded. The ring has no fill.
307
+ * Draws the frozen scene being left, dimmed so it reads as paused, and over
308
+ * its center a ring whose outline fills with the share of images loaded.
309
+ * The ring has no fill.
309
310
  */
310
311
  renderSceneLoading(options) {
311
312
  const ctx = options.context;
312
313
  const W = options.canvas.width;
313
314
  const H = options.canvas.height;
315
+ const reveal = this.clampProgress(options.reveal);
314
316
  this.applyPageBackground(options.pageBackground);
315
317
  ctx.clearRect(0, 0, W, H);
316
318
  ctx.drawImage(options.snapshot, 0, 0, W, H);
317
- if (!options.showIndicator)
319
+ if (reveal === 0)
318
320
  return;
321
+ this.dimScene(ctx, W, H, reveal);
319
322
  const progress = this.clampProgress(options.progress);
320
323
  const radius = Math.round(Math.min(44, Math.max(20, Math.min(W, H) * 0.06)));
321
324
  const start = -Math.PI / 2;
@@ -327,18 +330,41 @@ export class RenderSystem {
327
330
  // A soft halo in the opposite tone keeps the ring legible over busy art.
328
331
  ctx.shadowColor = isDarkInk ? "rgba(255, 255, 255, 0.5)" : "rgba(0, 0, 0, 0.5)";
329
332
  ctx.shadowBlur = 6;
330
- ctx.globalAlpha = 0.25;
333
+ ctx.globalAlpha = 0.25 * reveal;
331
334
  ctx.beginPath();
332
335
  ctx.arc(W / 2, H / 2, radius, 0, Math.PI * 2);
333
336
  ctx.stroke();
334
337
  if (progress > 0) {
335
- ctx.globalAlpha = 1;
338
+ ctx.globalAlpha = reveal;
336
339
  ctx.beginPath();
337
340
  ctx.arc(W / 2, H / 2, radius, start, start + Math.PI * 2 * progress);
338
341
  ctx.stroke();
339
342
  }
340
343
  ctx.restore();
341
344
  }
345
+ /**
346
+ * Chooses the ring's color against the frozen frame as it looks once fully
347
+ * dimmed, since that is what the ring is drawn over.
348
+ */
349
+ pickSceneLoadingInk(snapshot) {
350
+ const dimmed = document.createElement("canvas");
351
+ dimmed.width = snapshot.width;
352
+ dimmed.height = snapshot.height;
353
+ const ctx = dimmed.getContext("2d");
354
+ if (!ctx)
355
+ return "#ffffff";
356
+ ctx.drawImage(snapshot, 0, 0);
357
+ this.dimScene(ctx, dimmed.width, dimmed.height, 1);
358
+ return this.pickLoadingInk(dimmed);
359
+ }
360
+ /** @internal */
361
+ dimScene(ctx, width, height, reveal) {
362
+ ctx.save();
363
+ ctx.globalAlpha = RenderSystem.SCENE_LOADING_DIM * reveal;
364
+ ctx.fillStyle = "#000000";
365
+ ctx.fillRect(0, 0, width, height);
366
+ ctx.restore();
367
+ }
342
368
  /**
343
369
  * Chooses white or near-black loading ink from the average brightness at the
344
370
  * center of `source`. Falls back to white when the pixels cannot be read,
@@ -991,3 +1017,5 @@ export class RenderSystem {
991
1017
  RenderSystem.MAX_SURFACE_CACHE_ENTRIES = 256;
992
1018
  /** @internal Stroke of the boot line and the scene ring, which match. */
993
1019
  RenderSystem.LOADING_STROKE = 3;
1020
+ /** @internal Opacity of the black veil over a scene that is loading the next one. */
1021
+ RenderSystem.SCENE_LOADING_DIM = 0.4;
package/dist/minimo.d.ts CHANGED
@@ -201,10 +201,10 @@ export interface IScene {
201
201
  * `game.onPreload`. Images that are already loaded are skipped, so replaying
202
202
  * a scene loads nothing.
203
203
  *
204
- * When images are pending, the scene being left freezes under a progress
205
- * ring until they load, and only then is this scene created. Because of
206
- * that, `reset()` and `transitionTo()` may return before this scene exists:
207
- * continue in `onCreate()`, not in the code after the call.
204
+ * When images are pending, the scene being left freezes, dimmed, under a
205
+ * progress ring until they load, and only then is this scene created.
206
+ * Because of that, `reset()` and `transitionTo()` may return before this
207
+ * scene exists: continue in `onCreate()`, not in the code after the call.
208
208
  *
209
209
  * @example
210
210
  * ```ts
@@ -1064,7 +1064,7 @@ export interface CollisionInfo {
1064
1064
  * scenes that each carry many assets of their own — typically a game with many
1065
1065
  * levels, whose player does not reach every level in a session — should give
1066
1066
  * scenes an {@link IScene.onPreload}. Entering such a scene loads its images
1067
- * first, with the scene being left frozen under a progress ring, so `reset()`
1067
+ * first, with the scene being left frozen and dimmed under a progress ring, so `reset()`
1068
1068
  * and `transitionTo()` may return before the new scene's `onCreate()` runs.
1069
1069
  *
1070
1070
  * ---
@@ -2292,7 +2292,7 @@ export declare class Game {
2292
2292
  * can rebuild synchronously.
2293
2293
  *
2294
2294
  * The exception is a scene whose {@link IScene.onPreload} registers images
2295
- * that are not loaded yet. Then the current scene freezes under a progress
2295
+ * that are not loaded yet. Then the current scene freezes and dims under a progress
2296
2296
  * ring, nothing is cleared until the images load, and `reset()` returns
2297
2297
  * before the scene is rebuilt; its `onCreate()` runs once they have loaded.
2298
2298
  * A `reset()` called while a scene is loading is ignored.
@@ -2325,7 +2325,7 @@ export declare class Game {
2325
2325
  * While the transition is active, gameplay updates are paused.
2326
2326
  *
2327
2327
  * If the target scene's {@link IScene.onPreload} registers images that are
2328
- * not loaded yet, the current scene first freezes under a progress ring
2328
+ * not loaded yet, the current scene first freezes and dims under a progress ring
2329
2329
  * until they load, and the transition plays after that. `transitionTo()`
2330
2330
  * then returns before the target scene exists; continue in its
2331
2331
  * `onCreate()` or in `onComplete`. If the player declines to retry failed
package/dist/minimo.js CHANGED
@@ -22,8 +22,10 @@ import { TextSystem } from "./internal/TextSystem.js";
22
22
  import { TrailSystem } from "./internal/TrailSystem.js";
23
23
  import { TransitionSystem } from "./internal/TransitionSystem.js";
24
24
  import { TimerSystem } from "./internal/TimerSystem.js";
25
- /** How long a scene may load before its progress ring appears, so a fast load shows none. */
25
+ /** How long a scene may load before it dims and its progress ring appears, so a fast load shows neither. */
26
26
  const SCENE_LOADING_INDICATOR_DELAY_MS = 250;
27
+ /** How long the dimming and the ring take to fade in once they appear. */
28
+ const SCENE_LOADING_FADE_MS = 200;
27
29
  // ---------------------------------------------------------------------------
28
30
  // EmojiSprite
29
31
  // ---------------------------------------------------------------------------
@@ -1103,7 +1105,7 @@ export class BackgroundLayer {
1103
1105
  * scenes that each carry many assets of their own — typically a game with many
1104
1106
  * levels, whose player does not reach every level in a session — should give
1105
1107
  * scenes an {@link IScene.onPreload}. Entering such a scene loads its images
1106
- * first, with the scene being left frozen under a progress ring, so `reset()`
1108
+ * first, with the scene being left frozen and dimmed under a progress ring, so `reset()`
1107
1109
  * and `transitionTo()` may return before the new scene's `onCreate()` runs.
1108
1110
  *
1109
1111
  * ---
@@ -2580,7 +2582,7 @@ export class Game {
2580
2582
  * can rebuild synchronously.
2581
2583
  *
2582
2584
  * The exception is a scene whose {@link IScene.onPreload} registers images
2583
- * that are not loaded yet. Then the current scene freezes under a progress
2585
+ * that are not loaded yet. Then the current scene freezes and dims under a progress
2584
2586
  * ring, nothing is cleared until the images load, and `reset()` returns
2585
2587
  * before the scene is rebuilt; its `onCreate()` runs once they have loaded.
2586
2588
  * A `reset()` called while a scene is loading is ignored.
@@ -2654,7 +2656,7 @@ export class Game {
2654
2656
  * While the transition is active, gameplay updates are paused.
2655
2657
  *
2656
2658
  * If the target scene's {@link IScene.onPreload} registers images that are
2657
- * not loaded yet, the current scene first freezes under a progress ring
2659
+ * not loaded yet, the current scene first freezes and dims under a progress ring
2658
2660
  * until they load, and the transition plays after that. `transitionTo()`
2659
2661
  * then returns before the target scene exists; continue in its
2660
2662
  * `onCreate()` or in `onComplete`. If the player declines to retry failed
@@ -2873,7 +2875,8 @@ export class Game {
2873
2875
  pageBackground: this.pageBackground,
2874
2876
  snapshot: load.snapshot,
2875
2877
  progress: load.progress,
2876
- showIndicator: performance.now() - load.startedAt >= SCENE_LOADING_INDICATOR_DELAY_MS,
2878
+ reveal: (performance.now() - load.startedAt - SCENE_LOADING_INDICATOR_DELAY_MS) /
2879
+ SCENE_LOADING_FADE_MS,
2877
2880
  ink: load.ink,
2878
2881
  });
2879
2882
  }
@@ -2915,7 +2918,7 @@ export class Game {
2915
2918
  snapshot.getContext("2d")?.drawImage(this._canvas, 0, 0);
2916
2919
  const load = {
2917
2920
  snapshot,
2918
- ink: this._renderSystem.pickLoadingInk(snapshot),
2921
+ ink: this._renderSystem.pickSceneLoadingInk(snapshot),
2919
2922
  progress: 0,
2920
2923
  startedAt: performance.now(),
2921
2924
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "minimojs",
3
- "version": "1.0.0-alpha.24",
3
+ "version": "1.0.0-alpha.25",
4
4
  "description": "MinimoJS v1 — ultra-minimal, flat, deterministic 2D web game engine. Image-first sprites with emoji as a zero-asset alternative, rAF loop, TypeScript-first, LLM-friendly.",
5
5
  "type": "module",
6
6
  "main": "dist/minimo.js",