@datamoc/mw_games 0.1.2 → 0.2.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.
- package/README.md +42 -17
- package/dist/actors/Aura.d.ts +29 -0
- package/dist/actors/Aura.d.ts.map +1 -0
- package/dist/actors/Aura.js +69 -0
- package/dist/actors/Aura.js.map +1 -0
- package/dist/actors/ItemStatusEffect.d.ts +27 -0
- package/dist/actors/ItemStatusEffect.d.ts.map +1 -0
- package/dist/actors/ItemStatusEffect.js +35 -0
- package/dist/actors/ItemStatusEffect.js.map +1 -0
- package/dist/actors/Support.d.ts +32 -0
- package/dist/actors/Support.d.ts.map +1 -0
- package/dist/actors/Support.js +60 -0
- package/dist/actors/Support.js.map +1 -0
- package/dist/actors/Traits.d.ts +29 -0
- package/dist/actors/Traits.d.ts.map +1 -0
- package/dist/actors/Traits.js +21 -0
- package/dist/actors/Traits.js.map +1 -0
- package/dist/actors/index.d.ts +8 -0
- package/dist/actors/index.d.ts.map +1 -1
- package/dist/actors/index.js +4 -0
- package/dist/actors/index.js.map +1 -1
- package/dist/assets/Streaming.d.ts +40 -0
- package/dist/assets/Streaming.d.ts.map +1 -0
- package/dist/assets/Streaming.js +79 -0
- package/dist/assets/Streaming.js.map +1 -0
- package/dist/assets/index.d.ts +13 -0
- package/dist/assets/index.d.ts.map +1 -1
- package/dist/assets/index.js +19 -0
- package/dist/assets/index.js.map +1 -1
- package/dist/audio/Captions.d.ts +15 -0
- package/dist/audio/Captions.d.ts.map +1 -0
- package/dist/audio/Captions.js +4 -0
- package/dist/audio/Captions.js.map +1 -0
- package/dist/audio/Midi.d.ts +75 -0
- package/dist/audio/Midi.d.ts.map +1 -0
- package/dist/audio/Midi.js +186 -0
- package/dist/audio/Midi.js.map +1 -0
- package/dist/audio/Orchestrator.d.ts +40 -0
- package/dist/audio/Orchestrator.d.ts.map +1 -0
- package/dist/audio/Orchestrator.js +48 -0
- package/dist/audio/Orchestrator.js.map +1 -0
- package/dist/audio/Sound.d.ts +3 -0
- package/dist/audio/Sound.d.ts.map +1 -1
- package/dist/audio/Sound.js +4 -0
- package/dist/audio/Sound.js.map +1 -1
- package/dist/audio/Synth.d.ts +35 -0
- package/dist/audio/Synth.d.ts.map +1 -0
- package/dist/audio/Synth.js +96 -0
- package/dist/audio/Synth.js.map +1 -0
- package/dist/audio/index.d.ts +8 -0
- package/dist/audio/index.d.ts.map +1 -1
- package/dist/audio/index.js +4 -0
- package/dist/audio/index.js.map +1 -1
- package/dist/board/Army.d.ts +17 -0
- package/dist/board/Army.d.ts.map +1 -0
- package/dist/board/Army.js +48 -0
- package/dist/board/Army.js.map +1 -0
- package/dist/board/FogOfWar.d.ts +23 -0
- package/dist/board/FogOfWar.d.ts.map +1 -0
- package/dist/board/FogOfWar.js +40 -0
- package/dist/board/FogOfWar.js.map +1 -0
- package/dist/board/Tactics.d.ts +2 -0
- package/dist/board/Tactics.d.ts.map +1 -1
- package/dist/board/Tactics.js +29 -7
- package/dist/board/Tactics.js.map +1 -1
- package/dist/board/index.d.ts +5 -1
- package/dist/board/index.d.ts.map +1 -1
- package/dist/board/index.js +3 -1
- package/dist/board/index.js.map +1 -1
- package/dist/core/Feedback.d.ts +23 -0
- package/dist/core/Feedback.d.ts.map +1 -0
- package/dist/core/Feedback.js +35 -0
- package/dist/core/Feedback.js.map +1 -0
- package/dist/core/Game.d.ts +11 -0
- package/dist/core/Game.d.ts.map +1 -1
- package/dist/core/Game.js +54 -0
- package/dist/core/Game.js.map +1 -1
- package/dist/core/Input.d.ts +58 -0
- package/dist/core/Input.d.ts.map +1 -1
- package/dist/core/Input.js +135 -0
- package/dist/core/Input.js.map +1 -1
- package/dist/core/Loading.d.ts +48 -0
- package/dist/core/Loading.d.ts.map +1 -0
- package/dist/core/Loading.js +102 -0
- package/dist/core/Loading.js.map +1 -0
- package/dist/core/News.d.ts +46 -0
- package/dist/core/News.d.ts.map +1 -0
- package/dist/core/News.js +79 -0
- package/dist/core/News.js.map +1 -0
- package/dist/core/PlayerInput.d.ts +38 -0
- package/dist/core/PlayerInput.d.ts.map +1 -0
- package/dist/core/PlayerInput.js +57 -0
- package/dist/core/PlayerInput.js.map +1 -0
- package/dist/core/RunHistory.d.ts +43 -0
- package/dist/core/RunHistory.d.ts.map +1 -0
- package/dist/core/RunHistory.js +41 -0
- package/dist/core/RunHistory.js.map +1 -0
- package/dist/core/Sanitize.d.ts +56 -0
- package/dist/core/Sanitize.d.ts.map +1 -0
- package/dist/core/Sanitize.js +87 -0
- package/dist/core/Sanitize.js.map +1 -0
- package/dist/core/Save.d.ts +31 -7
- package/dist/core/Save.d.ts.map +1 -1
- package/dist/core/Save.js +56 -0
- package/dist/core/Save.js.map +1 -1
- package/dist/core/SaveSync.d.ts +26 -0
- package/dist/core/SaveSync.d.ts.map +1 -0
- package/dist/core/SaveSync.js +52 -0
- package/dist/core/SaveSync.js.map +1 -0
- package/dist/core/Scramble.d.ts +13 -0
- package/dist/core/Scramble.d.ts.map +1 -0
- package/dist/core/Scramble.js +44 -0
- package/dist/core/Scramble.js.map +1 -0
- package/dist/core/Spawner.d.ts +48 -0
- package/dist/core/Spawner.d.ts.map +1 -0
- package/dist/core/Spawner.js +65 -0
- package/dist/core/Spawner.js.map +1 -0
- package/dist/core/Tween.d.ts +25 -0
- package/dist/core/Tween.d.ts.map +1 -0
- package/dist/core/Tween.js +60 -0
- package/dist/core/Tween.js.map +1 -0
- package/dist/core/UndoHistory.d.ts +37 -0
- package/dist/core/UndoHistory.d.ts.map +1 -0
- package/dist/core/UndoHistory.js +49 -0
- package/dist/core/UndoHistory.js.map +1 -0
- package/dist/core/index.d.ts +20 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +11 -0
- package/dist/core/index.js.map +1 -1
- package/dist/i18n/Fluent.d.ts +7 -0
- package/dist/i18n/Fluent.d.ts.map +1 -0
- package/dist/i18n/Fluent.js +86 -0
- package/dist/i18n/Fluent.js.map +1 -0
- package/dist/i18n/index.d.ts +15 -1
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +17 -2
- package/dist/i18n/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/mw_games.global.js +351 -79
- package/dist/render/Camera.d.ts +29 -2
- package/dist/render/Camera.d.ts.map +1 -1
- package/dist/render/Camera.js +40 -11
- package/dist/render/Camera.js.map +1 -1
- package/dist/render/Capabilities.d.ts +51 -0
- package/dist/render/Capabilities.d.ts.map +1 -0
- package/dist/render/Capabilities.js +56 -0
- package/dist/render/Capabilities.js.map +1 -0
- package/dist/render/ColorBlindness.d.ts +16 -0
- package/dist/render/ColorBlindness.d.ts.map +1 -0
- package/dist/render/ColorBlindness.js +41 -0
- package/dist/render/ColorBlindness.js.map +1 -0
- package/dist/render/Minimap.d.ts +52 -0
- package/dist/render/Minimap.d.ts.map +1 -0
- package/dist/render/Minimap.js +95 -0
- package/dist/render/Minimap.js.map +1 -0
- package/dist/render/Viewport.d.ts +46 -0
- package/dist/render/Viewport.d.ts.map +1 -0
- package/dist/render/Viewport.js +52 -0
- package/dist/render/Viewport.js.map +1 -0
- package/dist/render/index.d.ts +9 -1
- package/dist/render/index.d.ts.map +1 -1
- package/dist/render/index.js +5 -1
- package/dist/render/index.js.map +1 -1
- package/dist/roguelike/Stealth.d.ts +34 -0
- package/dist/roguelike/Stealth.d.ts.map +1 -0
- package/dist/roguelike/Stealth.js +35 -0
- package/dist/roguelike/Stealth.js.map +1 -0
- package/dist/roguelike/index.d.ts +2 -0
- package/dist/roguelike/index.d.ts.map +1 -1
- package/dist/roguelike/index.js +1 -0
- package/dist/roguelike/index.js.map +1 -1
- package/dist/rpg/Collision.d.ts +42 -0
- package/dist/rpg/Collision.d.ts.map +1 -0
- package/dist/rpg/Collision.js +77 -0
- package/dist/rpg/Collision.js.map +1 -0
- package/dist/rpg/FreeMover.d.ts +45 -0
- package/dist/rpg/FreeMover.d.ts.map +1 -0
- package/dist/rpg/FreeMover.js +68 -0
- package/dist/rpg/FreeMover.js.map +1 -0
- package/dist/rpg/Marshal.d.ts +65 -0
- package/dist/rpg/Marshal.d.ts.map +1 -0
- package/dist/rpg/Marshal.js +393 -0
- package/dist/rpg/Marshal.js.map +1 -0
- package/dist/rpg/Quest.d.ts +41 -0
- package/dist/rpg/Quest.d.ts.map +1 -1
- package/dist/rpg/Quest.js +39 -6
- package/dist/rpg/Quest.js.map +1 -1
- package/dist/rpg/index.d.ts +7 -1
- package/dist/rpg/index.d.ts.map +1 -1
- package/dist/rpg/index.js +3 -0
- package/dist/rpg/index.js.map +1 -1
- package/dist/stage/DialogueStage.d.ts +1 -2
- package/dist/stage/DialogueStage.d.ts.map +1 -1
- package/dist/stage/DialogueStage.js +7 -22
- package/dist/stage/DialogueStage.js.map +1 -1
- package/dist/stage/index.d.ts +1 -1
- package/dist/stage/index.d.ts.map +1 -1
- package/dist/stage/script.d.ts +29 -0
- package/dist/stage/script.d.ts.map +1 -1
- package/dist/stage/script.js +0 -0
- package/dist/stage/script.js.map +1 -1
- package/dist/three-d/Character3D.d.ts +48 -0
- package/dist/three-d/Character3D.d.ts.map +1 -0
- package/dist/three-d/Character3D.js +96 -0
- package/dist/three-d/Character3D.js.map +1 -0
- package/dist/three-d/Engine3D.d.ts +23 -0
- package/dist/three-d/Engine3D.d.ts.map +1 -0
- package/dist/three-d/Engine3D.js +45 -0
- package/dist/three-d/Engine3D.js.map +1 -0
- package/dist/three-d/Grid.d.ts +14 -0
- package/dist/three-d/Grid.d.ts.map +1 -0
- package/dist/three-d/Grid.js +13 -0
- package/dist/three-d/Grid.js.map +1 -0
- package/dist/three-d/Heightmap.d.ts +35 -0
- package/dist/three-d/Heightmap.d.ts.map +1 -0
- package/dist/three-d/Heightmap.js +29 -0
- package/dist/three-d/Heightmap.js.map +1 -0
- package/dist/three-d/Models.d.ts +12 -0
- package/dist/three-d/Models.d.ts.map +1 -0
- package/dist/three-d/Models.js +14 -0
- package/dist/three-d/Models.js.map +1 -0
- package/dist/three-d/TileGrid3D.d.ts +21 -0
- package/dist/three-d/TileGrid3D.d.ts.map +1 -0
- package/dist/three-d/TileGrid3D.js +65 -0
- package/dist/three-d/TileGrid3D.js.map +1 -0
- package/dist/three-d/Vox.d.ts +24 -0
- package/dist/three-d/Vox.d.ts.map +1 -0
- package/dist/three-d/Vox.js +93 -0
- package/dist/three-d/Vox.js.map +1 -0
- package/dist/three-d/index.d.ts +13 -0
- package/dist/three-d/index.d.ts.map +1 -0
- package/dist/three-d/index.js +7 -0
- package/dist/three-d/index.js.map +1 -0
- package/dist/ui/Bar.d.ts +49 -0
- package/dist/ui/Bar.d.ts.map +1 -0
- package/dist/ui/Bar.js +70 -0
- package/dist/ui/Bar.js.map +1 -0
- package/dist/ui/BitmapLabel.d.ts +42 -0
- package/dist/ui/BitmapLabel.d.ts.map +1 -0
- package/dist/ui/BitmapLabel.js +59 -0
- package/dist/ui/BitmapLabel.js.map +1 -0
- package/dist/ui/Button.d.ts +52 -0
- package/dist/ui/Button.d.ts.map +1 -0
- package/dist/ui/Button.js +147 -0
- package/dist/ui/Button.js.map +1 -0
- package/dist/ui/FloatingText.d.ts +28 -0
- package/dist/ui/FloatingText.d.ts.map +1 -0
- package/dist/ui/FloatingText.js +39 -0
- package/dist/ui/FloatingText.js.map +1 -0
- package/dist/ui/HelpScreen.d.ts +29 -0
- package/dist/ui/HelpScreen.d.ts.map +1 -0
- package/dist/ui/HelpScreen.js +39 -0
- package/dist/ui/HelpScreen.js.map +1 -0
- package/dist/ui/IconGrid.d.ts +8 -0
- package/dist/ui/IconGrid.d.ts.map +1 -1
- package/dist/ui/IconGrid.js +27 -1
- package/dist/ui/IconGrid.js.map +1 -1
- package/dist/ui/Label.d.ts +9 -0
- package/dist/ui/Label.d.ts.map +1 -1
- package/dist/ui/Label.js +24 -1
- package/dist/ui/Label.js.map +1 -1
- package/dist/ui/ListView.d.ts +11 -0
- package/dist/ui/ListView.d.ts.map +1 -1
- package/dist/ui/ListView.js +55 -1
- package/dist/ui/ListView.js.map +1 -1
- package/dist/ui/LoadingScreen.d.ts +31 -0
- package/dist/ui/LoadingScreen.d.ts.map +1 -0
- package/dist/ui/LoadingScreen.js +60 -0
- package/dist/ui/LoadingScreen.js.map +1 -0
- package/dist/ui/MessageBox.d.ts +26 -0
- package/dist/ui/MessageBox.d.ts.map +1 -1
- package/dist/ui/MessageBox.js +62 -13
- package/dist/ui/MessageBox.js.map +1 -1
- package/dist/ui/RebindScreen.d.ts +55 -0
- package/dist/ui/RebindScreen.d.ts.map +1 -0
- package/dist/ui/RebindScreen.js +114 -0
- package/dist/ui/RebindScreen.js.map +1 -0
- package/dist/ui/Toast.d.ts +44 -0
- package/dist/ui/Toast.d.ts.map +1 -0
- package/dist/ui/Toast.js +89 -0
- package/dist/ui/Toast.js.map +1 -0
- package/dist/ui/VerticalLabel.d.ts +5 -0
- package/dist/ui/VerticalLabel.d.ts.map +1 -1
- package/dist/ui/VerticalLabel.js +18 -7
- package/dist/ui/VerticalLabel.js.map +1 -1
- package/dist/ui/Window.d.ts +6 -0
- package/dist/ui/Window.d.ts.map +1 -1
- package/dist/ui/Window.js +16 -1
- package/dist/ui/Window.js.map +1 -1
- package/dist/ui/WindowStack.d.ts +1 -0
- package/dist/ui/WindowStack.d.ts.map +1 -1
- package/dist/ui/WindowStack.js +4 -1
- package/dist/ui/WindowStack.js.map +1 -1
- package/dist/ui/index.d.ts +17 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +9 -1
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/theme.d.ts +21 -0
- package/dist/ui/theme.d.ts.map +1 -1
- package/dist/ui/theme.js +42 -0
- package/dist/ui/theme.js.map +1 -1
- package/dist/version.d.ts +13 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +13 -0
- package/dist/version.js.map +1 -0
- package/dist/world/Environment.d.ts +35 -0
- package/dist/world/Environment.d.ts.map +1 -0
- package/dist/world/Environment.js +55 -0
- package/dist/world/Environment.js.map +1 -0
- package/dist/world/index.d.ts +2 -0
- package/dist/world/index.d.ts.map +1 -1
- package/dist/world/index.js +1 -0
- package/dist/world/index.js.map +1 -1
- package/package.json +40 -4
package/dist/render/Camera.d.ts
CHANGED
|
@@ -19,6 +19,19 @@ export interface CameraOptions {
|
|
|
19
19
|
* grid-based game where movement is in whole tiles.
|
|
20
20
|
*/
|
|
21
21
|
deadzone?: number;
|
|
22
|
+
/**
|
|
23
|
+
* When set, `zoom` snaps to the nearest value at which one world unit of this size lands
|
|
24
|
+
* on a whole number of screen pixels - a tile's own width or height, typically.
|
|
25
|
+
*
|
|
26
|
+
* `apply()` already rounds the whole camera's screen offset to a whole pixel, which stops
|
|
27
|
+
* pixel art shimmering as the camera moves, but at a fractional zoom each tile's *own*
|
|
28
|
+
* edge still lands on a different sub-pixel offset depending on its position, so
|
|
29
|
+
* nearest-neighbour sampling rounds one tile's edge column one way and its neighbour's
|
|
30
|
+
* the other - a thin seam between tiles that camera-level rounding alone cannot fix.
|
|
31
|
+
* Snapping zoom itself so tile-size × zoom is always a whole number closes the gap at
|
|
32
|
+
* its source, without a per-tile sampling flag.
|
|
33
|
+
*/
|
|
34
|
+
pixelPerfectTileSize?: number;
|
|
22
35
|
}
|
|
23
36
|
export declare class Camera {
|
|
24
37
|
/** put the map and everything in it here */
|
|
@@ -28,8 +41,11 @@ export declare class Camera {
|
|
|
28
41
|
y: number;
|
|
29
42
|
private _zoom;
|
|
30
43
|
private deadzone;
|
|
44
|
+
private readonly pixelPerfectTileSize?;
|
|
31
45
|
private viewWidth;
|
|
32
46
|
private viewHeight;
|
|
47
|
+
private screenX;
|
|
48
|
+
private screenY;
|
|
33
49
|
private followTarget;
|
|
34
50
|
private followIntensity;
|
|
35
51
|
private shakeMagnitude;
|
|
@@ -42,8 +58,13 @@ export declare class Camera {
|
|
|
42
58
|
constructor(options?: CameraOptions);
|
|
43
59
|
get zoom(): number;
|
|
44
60
|
set zoom(value: number);
|
|
45
|
-
/**
|
|
46
|
-
|
|
61
|
+
/**
|
|
62
|
+
* The framework calls this on resize; sizes are in screen pixels. `screenX`/`screenY`
|
|
63
|
+
* default to 0 (an ordinary camera starting at the corner of the canvas); a `Viewport`
|
|
64
|
+
* gives its camera a nonzero one so this camera's own rectangle starts partway across
|
|
65
|
+
* the screen instead, for a split-screen layout.
|
|
66
|
+
*/
|
|
67
|
+
setViewport(width: number, height: number, screenX?: number, screenY?: number): void;
|
|
47
68
|
/** the visible rectangle, in world units: use it to cull */
|
|
48
69
|
get view(): {
|
|
49
70
|
x: number;
|
|
@@ -84,6 +105,12 @@ export declare class Camera {
|
|
|
84
105
|
private clampedCentre;
|
|
85
106
|
private apply;
|
|
86
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* The nearest zoom to `zoom` at which `tileSize * zoom` is a whole number of screen pixels -
|
|
110
|
+
* the pure math behind `CameraOptions.pixelPerfectTileSize`, exported so a game can snap a
|
|
111
|
+
* zoom value (from a slider, say) before ever handing it to a `Camera`.
|
|
112
|
+
*/
|
|
113
|
+
export declare function snapZoom(zoom: number, tileSize: number): number;
|
|
87
114
|
/** a camera sized to the running game's viewport, updated on every frame */
|
|
88
115
|
export declare function createCamera(options?: CameraOptions): Camera;
|
|
89
116
|
//# sourceMappingURL=Camera.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Camera.d.ts","sourceRoot":"","sources":["../../src/render/Camera.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAIpC;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC7B,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"Camera.d.ts","sourceRoot":"","sources":["../../src/render/Camera.ts"],"names":[],"mappings":"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"}
|
package/dist/render/Camera.js
CHANGED
|
@@ -10,6 +10,10 @@ export class Camera {
|
|
|
10
10
|
this.y = 0;
|
|
11
11
|
this.viewWidth = 0;
|
|
12
12
|
this.viewHeight = 0;
|
|
13
|
+
//where this camera's own rectangle starts on screen; 0,0 for an ordinary full-screen
|
|
14
|
+
//camera, nonzero for one player's share of a split-screen layout (see render.Viewport)
|
|
15
|
+
this.screenX = 0;
|
|
16
|
+
this.screenY = 0;
|
|
13
17
|
this.followTarget = null;
|
|
14
18
|
//how fast the camera closes on its target: it covers `intensity` of the remaining
|
|
15
19
|
//distance each second, so it eases in without ever quite arriving
|
|
@@ -21,19 +25,29 @@ export class Camera {
|
|
|
21
25
|
this.shakeY = 0;
|
|
22
26
|
/** clamps the view to these world bounds when set, so the map's edge is never crossed */
|
|
23
27
|
this.bounds = null;
|
|
24
|
-
this._zoom = options.zoom ?? 1;
|
|
25
28
|
this.deadzone = options.deadzone ?? 0;
|
|
29
|
+
this.pixelPerfectTileSize = options.pixelPerfectTileSize;
|
|
30
|
+
this._zoom = 1;
|
|
31
|
+
this.zoom = options.zoom ?? 1;
|
|
26
32
|
}
|
|
27
33
|
get zoom() {
|
|
28
34
|
return this._zoom;
|
|
29
35
|
}
|
|
30
36
|
set zoom(value) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
37
|
+
const clamped = Math.max(0.01, value);
|
|
38
|
+
this._zoom = this.pixelPerfectTileSize ? snapZoom(clamped, this.pixelPerfectTileSize) : clamped;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The framework calls this on resize; sizes are in screen pixels. `screenX`/`screenY`
|
|
42
|
+
* default to 0 (an ordinary camera starting at the corner of the canvas); a `Viewport`
|
|
43
|
+
* gives its camera a nonzero one so this camera's own rectangle starts partway across
|
|
44
|
+
* the screen instead, for a split-screen layout.
|
|
45
|
+
*/
|
|
46
|
+
setViewport(width, height, screenX = 0, screenY = 0) {
|
|
35
47
|
this.viewWidth = width;
|
|
36
48
|
this.viewHeight = height;
|
|
49
|
+
this.screenX = screenX;
|
|
50
|
+
this.screenY = screenY;
|
|
37
51
|
}
|
|
38
52
|
/** the visible rectangle, in world units: use it to cull */
|
|
39
53
|
get view() {
|
|
@@ -102,16 +116,22 @@ export class Camera {
|
|
|
102
116
|
}
|
|
103
117
|
/** world point to screen pixels */
|
|
104
118
|
toScreen(x, y) {
|
|
119
|
+
//must agree with apply()'s clamped centre (shake included), or a point converted
|
|
120
|
+
//with this and placed on screen lands somewhere other than where the camera
|
|
121
|
+
//actually drew it - exactly what happens near a bound, or on an axis the map is
|
|
122
|
+
//narrower than the view
|
|
123
|
+
const { x: centreX, y: centreY } = this.clampedCentre(this.x + this.shakeX, this.y + this.shakeY);
|
|
105
124
|
return {
|
|
106
|
-
x: (x -
|
|
107
|
-
y: (y -
|
|
125
|
+
x: (x - centreX) * this._zoom + this.screenX + this.viewWidth / 2,
|
|
126
|
+
y: (y - centreY) * this._zoom + this.screenY + this.viewHeight / 2,
|
|
108
127
|
};
|
|
109
128
|
}
|
|
110
129
|
/** screen pixels to world point, for turning a click into a tile */
|
|
111
130
|
toWorld(x, y) {
|
|
131
|
+
const { x: centreX, y: centreY } = this.clampedCentre(this.x + this.shakeX, this.y + this.shakeY);
|
|
112
132
|
return {
|
|
113
|
-
x: (x - this.viewWidth / 2) / this._zoom +
|
|
114
|
-
y: (y - this.viewHeight / 2) / this._zoom +
|
|
133
|
+
x: (x - this.screenX - this.viewWidth / 2) / this._zoom + centreX,
|
|
134
|
+
y: (y - this.screenY - this.viewHeight / 2) / this._zoom + centreY,
|
|
115
135
|
};
|
|
116
136
|
}
|
|
117
137
|
//the bounds-clamped centre `apply()` renders at, also what `view` reports for
|
|
@@ -133,13 +153,22 @@ export class Camera {
|
|
|
133
153
|
const { x: centreX, y: centreY } = this.clampedCentre(this.x + this.shakeX, this.y + this.shakeY);
|
|
134
154
|
this.world.scale.set(this._zoom);
|
|
135
155
|
//rounding to whole screen pixels stops pixel art shimmering as the camera moves
|
|
136
|
-
this.world.x = Math.round(this.viewWidth / 2 - centreX * this._zoom);
|
|
137
|
-
this.world.y = Math.round(this.viewHeight / 2 - centreY * this._zoom);
|
|
156
|
+
this.world.x = Math.round(this.screenX + this.viewWidth / 2 - centreX * this._zoom);
|
|
157
|
+
this.world.y = Math.round(this.screenY + this.viewHeight / 2 - centreY * this._zoom);
|
|
138
158
|
}
|
|
139
159
|
}
|
|
140
160
|
function clamp(value, min, max) {
|
|
141
161
|
return value < min ? min : value > max ? max : value;
|
|
142
162
|
}
|
|
163
|
+
/**
|
|
164
|
+
* The nearest zoom to `zoom` at which `tileSize * zoom` is a whole number of screen pixels -
|
|
165
|
+
* the pure math behind `CameraOptions.pixelPerfectTileSize`, exported so a game can snap a
|
|
166
|
+
* zoom value (from a slider, say) before ever handing it to a `Camera`.
|
|
167
|
+
*/
|
|
168
|
+
export function snapZoom(zoom, tileSize) {
|
|
169
|
+
const pixels = Math.max(1, Math.round(zoom * tileSize));
|
|
170
|
+
return pixels / tileSize;
|
|
171
|
+
}
|
|
143
172
|
/** a camera sized to the running game's viewport, updated on every frame */
|
|
144
173
|
export function createCamera(options = {}) {
|
|
145
174
|
const camera = new Camera(options);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Camera.js","sourceRoot":"","sources":["../../src/render/Camera.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"Camera.js","sourceRoot":"","sources":["../../src/render/Camera.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export type GraphicsWorkload = 'sprites' | 'ui' | 'custom-shaders' | 'particles' | 'instanced-terrain' | 'voxels' | 'animated-models' | 'large-3d-worlds';
|
|
2
|
+
export interface GraphicsCapabilities {
|
|
3
|
+
webgl1: boolean;
|
|
4
|
+
webgl2: boolean;
|
|
5
|
+
webgpu: boolean;
|
|
6
|
+
/** WGSL is usable only through a WebGPU-capable browser runtime. */
|
|
7
|
+
wgsl: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface GraphicsProbe {
|
|
10
|
+
createCanvas?(): {
|
|
11
|
+
getContext(kind: string): unknown;
|
|
12
|
+
} | null;
|
|
13
|
+
webgpu?: boolean;
|
|
14
|
+
/** whether a real WGSL shader actually compiled; see `detectWebGpu` for how to get one */
|
|
15
|
+
wgsl?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface RenderingDecision {
|
|
18
|
+
workload: GraphicsWorkload;
|
|
19
|
+
preferred: string;
|
|
20
|
+
fallback: string;
|
|
21
|
+
reason: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The framework's rendering choices by workload. This is data, not a global renderer switch:
|
|
25
|
+
* each game imports only the module it uses and keeps 2D Pixi and optional 3D Babylon paths
|
|
26
|
+
* independent.
|
|
27
|
+
*/
|
|
28
|
+
export declare const RENDERING_DECISIONS: readonly RenderingDecision[];
|
|
29
|
+
/**
|
|
30
|
+
* Reports browser graphics APIs without creating a renderer or selecting a fallback.
|
|
31
|
+
* Pass a probe in tests or host integrations; omitting it reads the current browser safely.
|
|
32
|
+
*
|
|
33
|
+
* `wgsl` cannot be checked synchronously - the only way to genuinely know a WGSL shader
|
|
34
|
+
* compiles is `detectWebGpu`, which requests a real device and compiles one, and every step
|
|
35
|
+
* of that is asynchronous. Rather than assume WGSL works just because `navigator.gpu`
|
|
36
|
+
* exists (a browser can expose WebGPU behind a still-broken or disabled implementation),
|
|
37
|
+
* this stays `false` unless a caller supplies a real result through `probe.wgsl`.
|
|
38
|
+
*/
|
|
39
|
+
export declare function inspectGraphicsCapabilities(probe?: GraphicsProbe): GraphicsCapabilities;
|
|
40
|
+
export interface WebGpuDetection {
|
|
41
|
+
webgpu: boolean;
|
|
42
|
+
wgsl: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The real, asynchronous WebGPU/WGSL check `inspectGraphicsCapabilities` cannot do
|
|
46
|
+
* synchronously: requests an actual adapter and device, then compiles an actual shader
|
|
47
|
+
* module and reads back its compilation diagnostics. Feed the result to
|
|
48
|
+
* `inspectGraphicsCapabilities` via `probe.webgpu`/`probe.wgsl` once resolved.
|
|
49
|
+
*/
|
|
50
|
+
export declare function detectWebGpu(): Promise<WebGpuDetection>;
|
|
51
|
+
//# sourceMappingURL=Capabilities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Capabilities.d.ts","sourceRoot":"","sources":["../../src/render/Capabilities.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GACzB,SAAS,GACT,IAAI,GACJ,gBAAgB,GAChB,WAAW,GACX,mBAAmB,GACnB,QAAQ,GACR,iBAAiB,GACjB,iBAAiB,CAAC;AAErB,MAAM,WAAW,oBAAoB;IACpC,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,oEAAoE;IACpE,IAAI,EAAE,OAAO,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC7B,YAAY,CAAC,IAAI;QAAE,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAC9D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0FAA0F;IAC1F,IAAI,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IACjC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,iBAAiB,EAS3D,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,GAAE,aAAkB,GAAG,oBAAoB,CAM3F;AAED,MAAM,WAAW,eAAe;IAC/B,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;CACd;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,eAAe,CAAC,CAe7D"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The framework's rendering choices by workload. This is data, not a global renderer switch:
|
|
3
|
+
* each game imports only the module it uses and keeps 2D Pixi and optional 3D Babylon paths
|
|
4
|
+
* independent.
|
|
5
|
+
*/
|
|
6
|
+
export const RENDERING_DECISIONS = [
|
|
7
|
+
{ workload: 'sprites', preferred: 'PixiJS WebGL/WebGPU batcher', fallback: 'PixiJS WebGL', reason: 'high-volume textured 2D batches' },
|
|
8
|
+
{ workload: 'ui', preferred: 'PixiJS display tree', fallback: 'PixiJS display tree', reason: 'themeable 2D layout and text' },
|
|
9
|
+
{ workload: 'custom-shaders', preferred: 'backend-specific GLSL/WGSL only when profiled', fallback: 'PixiJS filters', reason: 'avoid maintaining paired shader sources without a measured gain' },
|
|
10
|
+
{ workload: 'particles', preferred: 'PixiJS for 2D, Babylon.js for 3D', fallback: 'instanced sprites/meshes', reason: 'match simulation and depth to the scene' },
|
|
11
|
+
{ workload: 'instanced-terrain', preferred: 'Babylon.js thin instances', fallback: 'PixiJS TileMap for 2D', reason: 'depth-tested repeated 3D geometry' },
|
|
12
|
+
{ workload: 'voxels', preferred: 'Babylon.js thin instances', fallback: 'batched meshes', reason: 'color-grouped 3D voxels' },
|
|
13
|
+
{ workload: 'animated-models', preferred: 'Babylon.js glTF animation groups', fallback: 'billboard sprites', reason: 'standard 3D interchange and animation support' },
|
|
14
|
+
{ workload: 'large-3d-worlds', preferred: 'Babylon.js with streaming/culling', fallback: 'partitioned scenes', reason: 'scene graph, depth, and instancing' },
|
|
15
|
+
];
|
|
16
|
+
/**
|
|
17
|
+
* Reports browser graphics APIs without creating a renderer or selecting a fallback.
|
|
18
|
+
* Pass a probe in tests or host integrations; omitting it reads the current browser safely.
|
|
19
|
+
*
|
|
20
|
+
* `wgsl` cannot be checked synchronously - the only way to genuinely know a WGSL shader
|
|
21
|
+
* compiles is `detectWebGpu`, which requests a real device and compiles one, and every step
|
|
22
|
+
* of that is asynchronous. Rather than assume WGSL works just because `navigator.gpu`
|
|
23
|
+
* exists (a browser can expose WebGPU behind a still-broken or disabled implementation),
|
|
24
|
+
* this stays `false` unless a caller supplies a real result through `probe.wgsl`.
|
|
25
|
+
*/
|
|
26
|
+
export function inspectGraphicsCapabilities(probe = {}) {
|
|
27
|
+
const canvas = probe.createCanvas?.() ?? (typeof document === 'undefined' ? null : document.createElement('canvas'));
|
|
28
|
+
const webgl2 = Boolean(canvas?.getContext('webgl2'));
|
|
29
|
+
const webgl1 = webgl2 || Boolean(canvas?.getContext('webgl') ?? canvas?.getContext('experimental-webgl'));
|
|
30
|
+
const webgpu = probe.webgpu ?? Boolean(globalThis.navigator?.gpu);
|
|
31
|
+
return { webgl1, webgl2, webgpu, wgsl: probe.wgsl ?? false };
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The real, asynchronous WebGPU/WGSL check `inspectGraphicsCapabilities` cannot do
|
|
35
|
+
* synchronously: requests an actual adapter and device, then compiles an actual shader
|
|
36
|
+
* module and reads back its compilation diagnostics. Feed the result to
|
|
37
|
+
* `inspectGraphicsCapabilities` via `probe.webgpu`/`probe.wgsl` once resolved.
|
|
38
|
+
*/
|
|
39
|
+
export async function detectWebGpu() {
|
|
40
|
+
const gpu = globalThis.navigator?.gpu;
|
|
41
|
+
if (!gpu)
|
|
42
|
+
return { webgpu: false, wgsl: false };
|
|
43
|
+
try {
|
|
44
|
+
const adapter = await gpu.requestAdapter();
|
|
45
|
+
const device = await adapter?.requestDevice();
|
|
46
|
+
if (!device)
|
|
47
|
+
return { webgpu: false, wgsl: false };
|
|
48
|
+
const shader = device.createShaderModule({ code: '@compute @workgroup_size(1) fn main() {}' });
|
|
49
|
+
const info = await shader.getCompilationInfo();
|
|
50
|
+
return { webgpu: true, wgsl: info.messages.length === 0 };
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return { webgpu: false, wgsl: false };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=Capabilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Capabilities.js","sourceRoot":"","sources":["../../src/render/Capabilities.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ColorMatrixFilter } from 'pixi.js';
|
|
2
|
+
import type { ColorMatrix } from 'pixi.js';
|
|
3
|
+
export type ColorBlindnessType = 'protanopia' | 'deuteranopia' | 'tritanopia';
|
|
4
|
+
export declare const COLOR_BLINDNESS_MATRICES: Record<ColorBlindnessType, ColorMatrix>;
|
|
5
|
+
/**
|
|
6
|
+
* A whole-scene filter simulating one of the three common types of colour vision deficiency.
|
|
7
|
+
* Assign the result to a container's `.filters` (typically a game's whole stage), the same
|
|
8
|
+
* way any Pixi filter is applied - nothing here is `mwg`-specific beyond the named matrices.
|
|
9
|
+
*
|
|
10
|
+
* This simulates, showing a sighted developer what a colourblind player sees - the standard
|
|
11
|
+
* first step toward choosing a palette that reads clearly for them. It does not correct an
|
|
12
|
+
* existing palette automatically; that would need the source colours' own intent (which one
|
|
13
|
+
* is the "danger" colour, say), not just their RGB values.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createColorBlindnessFilter(type: ColorBlindnessType): ColorMatrixFilter;
|
|
16
|
+
//# sourceMappingURL=ColorBlindness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ColorBlindness.d.ts","sourceRoot":"","sources":["../../src/render/ColorBlindness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,MAAM,MAAM,kBAAkB,GAAG,YAAY,GAAG,cAAc,GAAG,YAAY,CAAC;AAM9E,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,kBAAkB,EAAE,WAAW,CAmB5E,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,kBAAkB,GAAG,iBAAiB,CAItF"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ColorMatrixFilter } from 'pixi.js';
|
|
2
|
+
//Brettel/Viénot-derived simulation matrices, the same values widely used by colourblindness
|
|
3
|
+
//simulators - a 5x4 (20-value) row-major RGBA matrix, Pixi's own `ColorMatrixFilter` format.
|
|
4
|
+
//Exported so the matrix data itself can be tested without constructing a `ColorMatrixFilter`,
|
|
5
|
+
//which (like `BitmapText`) needs a real WebGL context even to construct.
|
|
6
|
+
export const COLOR_BLINDNESS_MATRICES = {
|
|
7
|
+
protanopia: [
|
|
8
|
+
0.567, 0.433, 0, 0, 0,
|
|
9
|
+
0.558, 0.442, 0, 0, 0,
|
|
10
|
+
0, 0.242, 0.758, 0, 0,
|
|
11
|
+
0, 0, 0, 1, 0,
|
|
12
|
+
],
|
|
13
|
+
deuteranopia: [
|
|
14
|
+
0.625, 0.375, 0, 0, 0,
|
|
15
|
+
0.7, 0.3, 0, 0, 0,
|
|
16
|
+
0, 0.3, 0.7, 0, 0,
|
|
17
|
+
0, 0, 0, 1, 0,
|
|
18
|
+
],
|
|
19
|
+
tritanopia: [
|
|
20
|
+
0.95, 0.05, 0, 0, 0,
|
|
21
|
+
0, 0.433, 0.567, 0, 0,
|
|
22
|
+
0, 0.475, 0.525, 0, 0,
|
|
23
|
+
0, 0, 0, 1, 0,
|
|
24
|
+
],
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* A whole-scene filter simulating one of the three common types of colour vision deficiency.
|
|
28
|
+
* Assign the result to a container's `.filters` (typically a game's whole stage), the same
|
|
29
|
+
* way any Pixi filter is applied - nothing here is `mwg`-specific beyond the named matrices.
|
|
30
|
+
*
|
|
31
|
+
* This simulates, showing a sighted developer what a colourblind player sees - the standard
|
|
32
|
+
* first step toward choosing a palette that reads clearly for them. It does not correct an
|
|
33
|
+
* existing palette automatically; that would need the source colours' own intent (which one
|
|
34
|
+
* is the "danger" colour, say), not just their RGB values.
|
|
35
|
+
*/
|
|
36
|
+
export function createColorBlindnessFilter(type) {
|
|
37
|
+
const filter = new ColorMatrixFilter();
|
|
38
|
+
filter.matrix = COLOR_BLINDNESS_MATRICES[type];
|
|
39
|
+
return filter;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=ColorBlindness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ColorBlindness.js","sourceRoot":"","sources":["../../src/render/ColorBlindness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAK5C,4FAA4F;AAC5F,6FAA6F;AAC7F,8FAA8F;AAC9F,yEAAyE;AACzE,MAAM,CAAC,MAAM,wBAAwB,GAA4C;IAChF,UAAU,EAAE;QACX,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QACrB,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QACrB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QACrB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;KACb;IACD,YAAY,EAAE;QACb,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QACrB,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QACjB,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;QACjB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;KACb;IACD,UAAU,EAAE;QACX,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QACnB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QACrB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QACrB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;KACb;CACD,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,UAAU,0BAA0B,CAAC,IAAwB;IAClE,MAAM,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;IACvC,MAAM,CAAC,MAAM,GAAG,wBAAwB,CAAC,IAAI,CAAC,CAAC;IAC/C,OAAO,MAAM,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Container } from 'pixi.js';
|
|
2
|
+
/** the cell indices in `explored` not yet baked into a minimap's texture - pure, so it can
|
|
3
|
+
* be tested without a renderer */
|
|
4
|
+
export declare function newlyRevealed(explored: ReadonlySet<number>, alreadyDrawn: ReadonlySet<number>): number[];
|
|
5
|
+
export interface MinimapOptions {
|
|
6
|
+
/** the level's own width, in cells - needed to turn a cell index back into x/y */
|
|
7
|
+
widthInCells: number;
|
|
8
|
+
heightInCells: number;
|
|
9
|
+
/** screen pixels per cell; defaults to 2, small enough for an always-on-screen corner HUD */
|
|
10
|
+
cellSize?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A downscaled picture of a level, built from exactly the data `roguelike.FieldOfView`
|
|
14
|
+
* already tracks - `explored`, distinct from `visible` - plus a per-cell colour a game
|
|
15
|
+
* supplies, since `mwg` has no opinion on what a wall or a floor should look like.
|
|
16
|
+
*
|
|
17
|
+
* The same widget serves both sizes a map screen comes in: a small corner HUD element at a
|
|
18
|
+
* coarse `cellSize`, or a full, `Window`-sized pause-and-look screen at a larger one -
|
|
19
|
+
* nothing here is specific to either. Quest markers or a tracked-quest location (see
|
|
20
|
+
* `rpg.QuestLog.markerFor`/`trackedLocation`) are a game's own overlay on top of `world`,
|
|
21
|
+
* same as they would be over any other rendered view.
|
|
22
|
+
*
|
|
23
|
+
* Revealed cells are painted once into a persistent `RenderTexture` and never revisited -
|
|
24
|
+
* `sync` only rasterises what `newlyRevealed` reports as new, rather than redrawing the
|
|
25
|
+
* whole map from scratch on every call, which is the one open engineering question this
|
|
26
|
+
* item named: how an explored-cell set becomes a small texture without becoming a
|
|
27
|
+
* per-frame cost that grows with how much of the level has been seen.
|
|
28
|
+
*/
|
|
29
|
+
export declare class Minimap extends Container {
|
|
30
|
+
private readonly widthInCells;
|
|
31
|
+
private readonly cellSize;
|
|
32
|
+
private renderTexture;
|
|
33
|
+
private sprite;
|
|
34
|
+
private drawn;
|
|
35
|
+
private marker;
|
|
36
|
+
constructor(options: MinimapOptions);
|
|
37
|
+
/** cells revealed since the last call, by width/height already given to the constructor */
|
|
38
|
+
get exploredCount(): number;
|
|
39
|
+
/**
|
|
40
|
+
* Bakes every cell in `explored` that has not been drawn yet, at whatever colour
|
|
41
|
+
* `colorFor` reports for it. A cell already baked is never revisited even if `colorFor`
|
|
42
|
+
* would now answer differently - explored terrain does not usually change colour, and a
|
|
43
|
+
* game that wants it to can `reset()` and resync from a clean texture.
|
|
44
|
+
*/
|
|
45
|
+
sync(explored: ReadonlySet<number>, colorFor: (x: number, y: number) => number): void;
|
|
46
|
+
/** positions a marker at a cell, optionally pointing it in a facing direction (radians) */
|
|
47
|
+
setMarker(x: number, y: number, facing?: number, color?: number): void;
|
|
48
|
+
/** forgets everything baked, so the next `sync` repaints from a clean texture - a fresh floor */
|
|
49
|
+
reset(): void;
|
|
50
|
+
destroy(options?: Parameters<Container['destroy']>[0]): void;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=Minimap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Minimap.d.ts","sourceRoot":"","sources":["../../src/render/Minimap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAmC,MAAM,SAAS,CAAC;AAGrE;kCACkC;AAClC,wBAAgB,aAAa,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAMxG;AAED,MAAM,WAAW,cAAc;IAC9B,kFAAkF;IAClF,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IAEtB,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,OAAQ,SAAQ,SAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAElC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAqB;IAElC,OAAO,CAAC,MAAM,CAAkB;IAEhC,YAAY,OAAO,EAAE,cAAc,EAalC;IAED,2FAA2F;IAC3F,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED;;;;;OAKG;IACH,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAgBpF;IAED,2FAA2F;IAC3F,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,SAAW,GAAG,IAAI,CAcvE;IAED,iGAAiG;IACjG,KAAK,IAAI,IAAI,CAGZ;IAEQ,OAAO,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAGpE;CACD"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Container, Graphics, RenderTexture, Sprite } from 'pixi.js';
|
|
2
|
+
import { Game } from '../core/Game.js';
|
|
3
|
+
/** the cell indices in `explored` not yet baked into a minimap's texture - pure, so it can
|
|
4
|
+
* be tested without a renderer */
|
|
5
|
+
export function newlyRevealed(explored, alreadyDrawn) {
|
|
6
|
+
const result = [];
|
|
7
|
+
for (const index of explored) {
|
|
8
|
+
if (!alreadyDrawn.has(index))
|
|
9
|
+
result.push(index);
|
|
10
|
+
}
|
|
11
|
+
return result;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A downscaled picture of a level, built from exactly the data `roguelike.FieldOfView`
|
|
15
|
+
* already tracks - `explored`, distinct from `visible` - plus a per-cell colour a game
|
|
16
|
+
* supplies, since `mwg` has no opinion on what a wall or a floor should look like.
|
|
17
|
+
*
|
|
18
|
+
* The same widget serves both sizes a map screen comes in: a small corner HUD element at a
|
|
19
|
+
* coarse `cellSize`, or a full, `Window`-sized pause-and-look screen at a larger one -
|
|
20
|
+
* nothing here is specific to either. Quest markers or a tracked-quest location (see
|
|
21
|
+
* `rpg.QuestLog.markerFor`/`trackedLocation`) are a game's own overlay on top of `world`,
|
|
22
|
+
* same as they would be over any other rendered view.
|
|
23
|
+
*
|
|
24
|
+
* Revealed cells are painted once into a persistent `RenderTexture` and never revisited -
|
|
25
|
+
* `sync` only rasterises what `newlyRevealed` reports as new, rather than redrawing the
|
|
26
|
+
* whole map from scratch on every call, which is the one open engineering question this
|
|
27
|
+
* item named: how an explored-cell set becomes a small texture without becoming a
|
|
28
|
+
* per-frame cost that grows with how much of the level has been seen.
|
|
29
|
+
*/
|
|
30
|
+
export class Minimap extends Container {
|
|
31
|
+
constructor(options) {
|
|
32
|
+
super();
|
|
33
|
+
this.drawn = new Set();
|
|
34
|
+
this.marker = new Graphics();
|
|
35
|
+
this.widthInCells = options.widthInCells;
|
|
36
|
+
this.cellSize = options.cellSize ?? 2;
|
|
37
|
+
this.renderTexture = RenderTexture.create({
|
|
38
|
+
width: options.widthInCells * this.cellSize,
|
|
39
|
+
height: options.heightInCells * this.cellSize,
|
|
40
|
+
});
|
|
41
|
+
this.sprite = new Sprite(this.renderTexture);
|
|
42
|
+
this.addChild(this.sprite);
|
|
43
|
+
this.addChild(this.marker);
|
|
44
|
+
}
|
|
45
|
+
/** cells revealed since the last call, by width/height already given to the constructor */
|
|
46
|
+
get exploredCount() {
|
|
47
|
+
return this.drawn.size;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Bakes every cell in `explored` that has not been drawn yet, at whatever colour
|
|
51
|
+
* `colorFor` reports for it. A cell already baked is never revisited even if `colorFor`
|
|
52
|
+
* would now answer differently - explored terrain does not usually change colour, and a
|
|
53
|
+
* game that wants it to can `reset()` and resync from a clean texture.
|
|
54
|
+
*/
|
|
55
|
+
sync(explored, colorFor) {
|
|
56
|
+
const cells = newlyRevealed(explored, this.drawn);
|
|
57
|
+
if (cells.length === 0)
|
|
58
|
+
return;
|
|
59
|
+
const patch = new Graphics();
|
|
60
|
+
for (const index of cells) {
|
|
61
|
+
this.drawn.add(index);
|
|
62
|
+
const x = index % this.widthInCells;
|
|
63
|
+
const y = Math.floor(index / this.widthInCells);
|
|
64
|
+
patch
|
|
65
|
+
.rect(x * this.cellSize, y * this.cellSize, this.cellSize, this.cellSize)
|
|
66
|
+
.fill({ color: colorFor(x, y) });
|
|
67
|
+
}
|
|
68
|
+
Game.current.app.renderer.render({ container: patch, target: this.renderTexture, clear: false });
|
|
69
|
+
patch.destroy();
|
|
70
|
+
}
|
|
71
|
+
/** positions a marker at a cell, optionally pointing it in a facing direction (radians) */
|
|
72
|
+
setMarker(x, y, facing, color = 0xffffff) {
|
|
73
|
+
this.marker.clear();
|
|
74
|
+
this.marker.circle(0, 0, Math.max(1, this.cellSize)).fill({ color });
|
|
75
|
+
if (facing !== undefined) {
|
|
76
|
+
const length = this.cellSize * 2;
|
|
77
|
+
this.marker
|
|
78
|
+
.moveTo(0, 0)
|
|
79
|
+
.lineTo(Math.cos(facing) * length, Math.sin(facing) * length)
|
|
80
|
+
.stroke({ color, width: 1 });
|
|
81
|
+
}
|
|
82
|
+
this.marker.x = (x + 0.5) * this.cellSize;
|
|
83
|
+
this.marker.y = (y + 0.5) * this.cellSize;
|
|
84
|
+
}
|
|
85
|
+
/** forgets everything baked, so the next `sync` repaints from a clean texture - a fresh floor */
|
|
86
|
+
reset() {
|
|
87
|
+
this.drawn.clear();
|
|
88
|
+
Game.current.app.renderer.render({ container: new Container(), target: this.renderTexture, clear: true });
|
|
89
|
+
}
|
|
90
|
+
destroy(options) {
|
|
91
|
+
this.renderTexture.destroy(true);
|
|
92
|
+
super.destroy(options);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=Minimap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Minimap.js","sourceRoot":"","sources":["../../src/render/Minimap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Container } from 'pixi.js';
|
|
2
|
+
import { Camera, type CameraOptions } from './Camera.ts';
|
|
3
|
+
export interface ViewportOptions extends CameraOptions {
|
|
4
|
+
/** this viewport's own rectangle of the screen, in pixels */
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* One player's own rectangle of the screen, for a same-screen local multiplayer layout: a
|
|
12
|
+
* `Camera` whose world is offset to start at `x`/`y` instead of the corner of the canvas,
|
|
13
|
+
* and clipped to `width`/`height` so it never bleeds into a neighbouring player's share of
|
|
14
|
+
* the screen. A game with a single `Viewport` covering the whole canvas behaves exactly like
|
|
15
|
+
* a game using a bare `Camera` directly - this adds a screen region and a mask around it,
|
|
16
|
+
* nothing else.
|
|
17
|
+
*/
|
|
18
|
+
export declare class Viewport {
|
|
19
|
+
readonly camera: Camera;
|
|
20
|
+
/** add this to `Game.current.stage`, the way a single-camera game already adds `camera.world` */
|
|
21
|
+
readonly container: Container<import("pixi.js").ContainerChild>;
|
|
22
|
+
private readonly clip;
|
|
23
|
+
constructor(options: ViewportOptions);
|
|
24
|
+
/** moves and/or resizes this viewport's own rectangle of the screen */
|
|
25
|
+
resize(x: number, y: number, width: number, height: number): void;
|
|
26
|
+
update(dt: number): void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The two even halves of `width`×`height` a two-player split screen typically wants -
|
|
30
|
+
* side by side for a landscape screen, stacked for a portrait one - as plain rectangles a
|
|
31
|
+
* game hands straight to two `Viewport`s (or to `resize` on a resize event). Not the only
|
|
32
|
+
* reasonable split, so not baked into `Viewport` itself: a game wanting an L-shaped, uneven,
|
|
33
|
+
* or three/four-player layout lays out its own rectangles the same way.
|
|
34
|
+
*/
|
|
35
|
+
export declare function splitScreenHalves(width: number, height: number): [{
|
|
36
|
+
x: number;
|
|
37
|
+
y: number;
|
|
38
|
+
width: number;
|
|
39
|
+
height: number;
|
|
40
|
+
}, {
|
|
41
|
+
x: number;
|
|
42
|
+
y: number;
|
|
43
|
+
width: number;
|
|
44
|
+
height: number;
|
|
45
|
+
}];
|
|
46
|
+
//# sourceMappingURL=Viewport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Viewport.d.ts","sourceRoot":"","sources":["../../src/render/Viewport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAY,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAEzD,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACrD,6DAA6D;IAC7D,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;GAOG;AACH,qBAAa,QAAQ;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,iGAAiG;IACjG,QAAQ,CAAC,SAAS,8CAAmB;IAErC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAkB;IAEvC,YAAY,OAAO,EAAE,eAAe,EAMnC;IAED,uEAAuE;IACvE,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAGhE;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAEvB;CACD;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAChC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACZ,CAAC;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAapH"}
|