@oidoid/void 0.1.0-3 → 0.1.0-6
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/dist/meta.json +1 -0
- package/dist/package.json +66 -0
- package/dist/public/favicon/favicon16.png +0 -0
- package/dist/public/favicon/favicon192.png +0 -0
- package/dist/public/favicon/favicon32.png +0 -0
- package/dist/public/favicon/favicon48.png +0 -0
- package/dist/public/favicon/favicon512.png +0 -0
- package/dist/public/favicon/favicon64.png +0 -0
- package/dist/public/index.html +23 -0
- package/dist/public/index.js +3844 -0
- package/dist/public/index.js.map +7 -0
- package/dist/public/manifest.json +1 -0
- package/dist/public/preload-atlas.png +0 -0
- package/dist/public/void-v0.1.0-4.html +111 -0
- package/dist/public/void-v0.1.0-5.html +111 -0
- package/dist/public/void-v0.1.0-6.html +111 -0
- package/dist/schema/config-file.d.ts +32 -0
- package/dist/schema/config-file.js +41 -0
- package/dist/schema/config-file.js.map +1 -0
- package/dist/schema/config-file.v0.json +68 -0
- package/dist/src/audio.d.ts +7 -0
- package/dist/src/audio.js +25 -0
- package/dist/src/audio.js.map +1 -0
- package/dist/src/demo/assets/manifest.json +46 -0
- package/dist/src/demo/assets/preload-atlas.json +193 -0
- package/dist/src/demo/ents/clock-ent.d.ts +10 -0
- package/dist/src/demo/ents/clock-ent.js +26 -0
- package/dist/src/demo/ents/clock-ent.js.map +1 -0
- package/dist/src/demo/ents/render-toggle-ent.d.ts +10 -0
- package/dist/src/demo/ents/render-toggle-ent.js +38 -0
- package/dist/src/demo/ents/render-toggle-ent.js.map +1 -0
- package/dist/src/demo/ents/work-counter-ent.d.ts +10 -0
- package/dist/src/demo/ents/work-counter-ent.js +24 -0
- package/dist/src/demo/ents/work-counter-ent.js.map +1 -0
- package/dist/src/demo/game.d.ts +13 -0
- package/dist/src/demo/game.js +155 -0
- package/dist/src/demo/game.js.map +1 -0
- package/dist/src/demo/index.d.ts +1 -0
- package/dist/src/demo/index.js +8 -0
- package/dist/src/demo/index.js.map +1 -0
- package/dist/src/demo/tsconfig.json +15 -0
- package/dist/src/demo/types/tag.d.ts +2 -0
- package/dist/src/demo/types/tag.js +2 -0
- package/dist/src/demo/types/tag.js.map +1 -0
- package/dist/src/demo/void.json +11 -0
- package/dist/src/ents/button-ent.d.ts +38 -0
- package/dist/src/ents/button-ent.js +124 -0
- package/dist/src/ents/button-ent.js.map +1 -0
- package/dist/src/ents/cursor-ent.d.ts +18 -0
- package/dist/src/ents/cursor-ent.js +58 -0
- package/dist/src/ents/cursor-ent.js.map +1 -0
- package/dist/src/ents/ent.d.ts +7 -0
- package/dist/src/ents/ent.js +2 -0
- package/dist/src/ents/ent.js.map +1 -0
- package/dist/src/ents/follow-cam-ent.d.ts +25 -0
- package/dist/src/ents/follow-cam-ent.js +87 -0
- package/dist/src/ents/follow-cam-ent.js.map +1 -0
- package/dist/src/ents/nine-patch-ent.d.ts +43 -0
- package/dist/src/ents/nine-patch-ent.js +143 -0
- package/dist/src/ents/nine-patch-ent.js.map +1 -0
- package/dist/src/ents/text-ent.d.ts +23 -0
- package/dist/src/ents/text-ent.js +109 -0
- package/dist/src/ents/text-ent.js.map +1 -0
- package/dist/src/ents/zoo.d.ts +16 -0
- package/dist/src/ents/zoo.js +38 -0
- package/dist/src/ents/zoo.js.map +1 -0
- package/dist/src/graphics/atlas-parser.d.ts +4 -0
- package/dist/src/graphics/atlas-parser.js +27 -0
- package/dist/src/graphics/atlas-parser.js.map +1 -0
- package/dist/src/graphics/atlas.d.ts +49 -0
- package/dist/src/graphics/atlas.js +7 -0
- package/dist/src/graphics/atlas.js.map +1 -0
- package/dist/src/graphics/cam.d.ts +89 -0
- package/dist/src/graphics/cam.js +211 -0
- package/dist/src/graphics/cam.js.map +1 -0
- package/dist/src/graphics/gl.d.ts +24 -0
- package/dist/src/graphics/gl.js +70 -0
- package/dist/src/graphics/gl.js.map +1 -0
- package/dist/src/graphics/layer.d.ts +21 -0
- package/dist/src/graphics/layer.js +23 -0
- package/dist/src/graphics/layer.js.map +1 -0
- package/dist/src/graphics/renderer.d.ts +22 -0
- package/dist/src/graphics/renderer.js +168 -0
- package/dist/src/graphics/renderer.js.map +1 -0
- package/dist/src/graphics/sprite-frag.glsl.d.ts +1 -0
- package/dist/src/graphics/sprite-frag.glsl.js +35 -0
- package/dist/src/graphics/sprite-frag.glsl.js.map +1 -0
- package/dist/src/graphics/sprite-vert.glsl.d.ts +1 -0
- package/dist/src/graphics/sprite-vert.glsl.js +68 -0
- package/dist/src/graphics/sprite-vert.glsl.js.map +1 -0
- package/dist/src/graphics/sprite.d.ts +108 -0
- package/dist/src/graphics/sprite.js +301 -0
- package/dist/src/graphics/sprite.js.map +1 -0
- package/dist/src/index.d.ts +30 -0
- package/dist/src/index.js +33 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/input/context-menu.d.ts +8 -0
- package/dist/src/input/context-menu.js +25 -0
- package/dist/src/input/context-menu.js.map +1 -0
- package/dist/src/input/gamepad.d.ts +18 -0
- package/dist/src/input/gamepad.js +49 -0
- package/dist/src/input/gamepad.js.map +1 -0
- package/dist/src/input/input.d.ts +148 -0
- package/dist/src/input/input.js +383 -0
- package/dist/src/input/input.js.map +1 -0
- package/dist/src/input/keyboard.d.ts +17 -0
- package/dist/src/input/keyboard.js +46 -0
- package/dist/src/input/keyboard.js.map +1 -0
- package/dist/src/input/pointer.d.ts +53 -0
- package/dist/src/input/pointer.js +162 -0
- package/dist/src/input/pointer.js.map +1 -0
- package/dist/src/input/wheel.d.ts +12 -0
- package/dist/src/input/wheel.js +30 -0
- package/dist/src/input/wheel.js.map +1 -0
- package/dist/src/looper.d.ts +15 -0
- package/dist/src/looper.js +48 -0
- package/dist/src/looper.js.map +1 -0
- package/dist/src/mem/pool.d.ts +31 -0
- package/dist/src/mem/pool.js +98 -0
- package/dist/src/mem/pool.js.map +1 -0
- package/dist/src/pixel-ratio-observer.d.ts +10 -0
- package/dist/src/pixel-ratio-observer.js +26 -0
- package/dist/src/pixel-ratio-observer.js.map +1 -0
- package/dist/src/random/random.d.ts +8 -0
- package/dist/src/random/random.js +23 -0
- package/dist/src/random/random.js.map +1 -0
- package/dist/src/storage/local-storage.d.ts +3 -0
- package/dist/src/storage/local-storage.js +11 -0
- package/dist/src/storage/local-storage.js.map +1 -0
- package/dist/src/text/font.d.ts +6 -0
- package/dist/src/text/font.js +20 -0
- package/dist/src/text/font.js.map +1 -0
- package/dist/src/text/mem-prop-5x6.json +573 -0
- package/dist/src/text/text-layout.d.ts +19 -0
- package/dist/src/text/text-layout.js +85 -0
- package/dist/src/text/text-layout.js.map +1 -0
- package/dist/src/tsconfig.json +15 -0
- package/dist/src/types/geo.d.ts +38 -0
- package/dist/src/types/geo.js +61 -0
- package/dist/src/types/geo.js.map +1 -0
- package/dist/src/types/json.d.ts +31 -0
- package/dist/src/types/json.js +2 -0
- package/dist/src/types/json.js.map +1 -0
- package/dist/src/types/time.d.ts +19 -0
- package/dist/src/types/time.js +10 -0
- package/dist/src/types/time.js.map +1 -0
- package/dist/src/types/void-version.d.ts +9 -0
- package/dist/src/types/void-version.js +2 -0
- package/dist/src/types/void-version.js.map +1 -0
- package/dist/src/utils/async-util.d.ts +11 -0
- package/dist/src/utils/async-util.js +36 -0
- package/dist/src/utils/async-util.js.map +1 -0
- package/dist/src/utils/canvas-util.d.ts +7 -0
- package/dist/src/utils/canvas-util.js +128 -0
- package/dist/src/utils/canvas-util.js.map +1 -0
- package/dist/src/utils/color-util.d.ts +1 -0
- package/dist/src/utils/color-util.js +4 -0
- package/dist/src/utils/color-util.js.map +1 -0
- package/dist/src/utils/debug.d.ts +17 -0
- package/dist/src/utils/debug.js +34 -0
- package/dist/src/utils/debug.js.map +1 -0
- package/dist/src/utils/dom-util.d.ts +3 -0
- package/dist/src/utils/dom-util.js +29 -0
- package/dist/src/utils/dom-util.js.map +1 -0
- package/dist/src/utils/fetch-util.d.ts +3 -0
- package/dist/src/utils/fetch-util.js +24 -0
- package/dist/src/utils/fetch-util.js.map +1 -0
- package/dist/src/utils/math.d.ts +6 -0
- package/dist/src/utils/math.js +18 -0
- package/dist/src/utils/math.js.map +1 -0
- package/dist/src/utils/vibrate.d.ts +1 -0
- package/dist/src/utils/vibrate.js +4 -0
- package/dist/src/utils/vibrate.js.map +1 -0
- package/dist/src/void.d.ts +43 -0
- package/dist/src/void.js +95 -0
- package/dist/src/void.js.map +1 -0
- package/dist/tools/atlas-pack/aseprite.d.ts +58 -0
- package/dist/tools/atlas-pack/aseprite.js +16 -0
- package/dist/tools/atlas-pack/aseprite.js.map +1 -0
- package/dist/tools/atlas-pack/atlas-json-parser.d.ts +21 -0
- package/dist/tools/atlas-pack/atlas-json-parser.js +116 -0
- package/dist/tools/atlas-pack/atlas-json-parser.js.map +1 -0
- package/dist/tools/atlas-pack/atlas-pack.d.ts +2 -0
- package/dist/tools/atlas-pack/atlas-pack.js +17 -0
- package/dist/tools/atlas-pack/atlas-pack.js.map +1 -0
- package/dist/tools/bundle/bundle.d.ts +3 -0
- package/dist/tools/bundle/bundle.js +48 -0
- package/dist/tools/bundle/bundle.js.map +1 -0
- package/dist/tools/bundle/html-plugin.d.ts +3 -0
- package/dist/tools/bundle/html-plugin.js +88 -0
- package/dist/tools/bundle/html-plugin.js.map +1 -0
- package/dist/tools/tsconfig-base.json +45 -0
- package/dist/tools/tsconfig.json +21 -0
- package/dist/tools/types/config.d.ts +20 -0
- package/dist/tools/types/config.js +22 -0
- package/dist/tools/types/config.js.map +1 -0
- package/dist/tools/utils/argv.d.ts +12 -0
- package/dist/tools/utils/argv.js +19 -0
- package/dist/tools/utils/argv.js.map +1 -0
- package/dist/tools/utils/exec.d.ts +3 -0
- package/dist/tools/utils/exec.js +15 -0
- package/dist/tools/utils/exec.js.map +1 -0
- package/dist/tools/utils/file-util.d.ts +1 -0
- package/dist/tools/utils/file-util.js +13 -0
- package/dist/tools/utils/file-util.js.map +1 -0
- package/dist/tools/utils/html-parser.d.ts +1 -0
- package/dist/tools/utils/html-parser.js +10 -0
- package/dist/tools/utils/html-parser.js.map +1 -0
- package/dist/tools/void.d.ts +17 -0
- package/dist/tools/void.js +30 -0
- package/dist/tools/void.js.map +1 -0
- package/package.json +33 -39
- package/readme.md +1 -1
- package/schema/config-file.test.ts +55 -0
- package/schema/config-file.ts +69 -0
- package/schema/config-file.v0.json +68 -0
- package/tools/atlas-pack/aseprite.ts +60 -0
- package/tools/atlas-pack/atlas-json-parser.test.ts +780 -0
- package/tools/atlas-pack/atlas-json-parser.ts +159 -0
- package/tools/atlas-pack/atlas-pack.ts +38 -0
- package/tools/bundle/bundle.ts +65 -0
- package/tools/bundle/html-plugin.ts +135 -0
- package/tools/types/config.ts +43 -0
- package/tools/utils/argv.test.ts +41 -0
- package/tools/utils/argv.ts +29 -0
- package/tools/utils/exec.ts +22 -0
- package/tools/utils/file-util.ts +11 -0
- package/tools/utils/html-parser.ts +9 -0
- package/tools/void.ts +54 -0
- package/dist/atlas/aseprite.d.ts +0 -37
- package/dist/atlas/aseprite.js +0 -2
- package/dist/atlas/aseprite.js.map +0 -1
- package/dist/atlas/atlas-parser.d.ts +0 -52
- package/dist/atlas/atlas-parser.js +0 -109
- package/dist/atlas/atlas-parser.js.map +0 -1
- package/dist/atlas/atlas.d.ts +0 -12
- package/dist/atlas/atlas.js +0 -2
- package/dist/atlas/atlas.js.map +0 -1
- package/dist/audio/synth.d.ts +0 -4
- package/dist/audio/synth.js +0 -21
- package/dist/audio/synth.js.map +0 -1
- package/dist/graphics/bitmap.d.ts +0 -14
- package/dist/graphics/bitmap.js +0 -14
- package/dist/graphics/bitmap.js.map +0 -1
- package/dist/graphics/cam.d.ts +0 -16
- package/dist/graphics/cam.js +0 -42
- package/dist/graphics/cam.js.map +0 -1
- package/dist/graphics/frag.glsl.d.ts +0 -1
- package/dist/graphics/frag.glsl.js +0 -15
- package/dist/graphics/frag.glsl.js.map +0 -1
- package/dist/graphics/frame-listener.d.ts +0 -16
- package/dist/graphics/frame-listener.js +0 -83
- package/dist/graphics/frame-listener.js.map +0 -1
- package/dist/graphics/renderer.d.ts +0 -12
- package/dist/graphics/renderer.js +0 -185
- package/dist/graphics/renderer.js.map +0 -1
- package/dist/graphics/vert.glsl.d.ts +0 -1
- package/dist/graphics/vert.glsl.js +0 -46
- package/dist/graphics/vert.glsl.js.map +0 -1
- package/dist/index.d.ts +0 -31
- package/dist/index.js +0 -79
- package/dist/index.js.map +0 -1
- package/dist/input/gamepad-poller.d.ts +0 -8
- package/dist/input/gamepad-poller.js +0 -38
- package/dist/input/gamepad-poller.js.map +0 -1
- package/dist/input/input.d.ts +0 -44
- package/dist/input/input.js +0 -175
- package/dist/input/input.js.map +0 -1
- package/dist/input/keyboard-poller.d.ts +0 -7
- package/dist/input/keyboard-poller.js +0 -30
- package/dist/input/keyboard-poller.js.map +0 -1
- package/dist/input/pointer-poller.d.ts +0 -12
- package/dist/input/pointer-poller.js +0 -67
- package/dist/input/pointer-poller.js.map +0 -1
- package/dist/sprite/sprite.d.ts +0 -51
- package/dist/sprite/sprite.js +0 -161
- package/dist/sprite/sprite.js.map +0 -1
- package/dist/storage/json-storage.d.ts +0 -4
- package/dist/storage/json-storage.js +0 -13
- package/dist/storage/json-storage.js.map +0 -1
- package/dist/test/tsconfig.json +0 -14
- package/dist/text/font.d.ts +0 -6
- package/dist/text/font.js +0 -18
- package/dist/text/font.js.map +0 -1
- package/dist/text/text-layout.d.ts +0 -11
- package/dist/text/text-layout.js +0 -73
- package/dist/text/text-layout.js.map +0 -1
- package/dist/tsconfig.json +0 -13
- package/dist/types/2d.d.ts +0 -9
- package/dist/types/2d.js +0 -2
- package/dist/types/2d.js.map +0 -1
- package/dist/void.js +0 -60
- package/dist/void.js.map +0 -7
- package/dist/void.meta.json +0 -299
- package/tools/void.js +0 -143
|
@@ -0,0 +1,3844 @@
|
|
|
1
|
+
new EventSource('/esbuild').addEventListener('change', () => location.reload());
|
|
2
|
+
|
|
3
|
+
// <define:globalThis.voidVersion>
|
|
4
|
+
var define_globalThis_voidVersion_default = { hash: "2eb97a3", published: "20250824", version: "0.1.0-4" };
|
|
5
|
+
|
|
6
|
+
// src/types/void-version.ts
|
|
7
|
+
var voidVersion = define_globalThis_voidVersion_default;
|
|
8
|
+
|
|
9
|
+
// node_modules/mem-font/dist/mem-prop-5x6.json
|
|
10
|
+
var mem_prop_5x6_default = {
|
|
11
|
+
id: "mem-prop-5x6",
|
|
12
|
+
name: "mem 5x6",
|
|
13
|
+
cellWidth: 5,
|
|
14
|
+
cellHeight: 6,
|
|
15
|
+
leading: 1,
|
|
16
|
+
lineHeight: 7,
|
|
17
|
+
baseline: 1,
|
|
18
|
+
kerning: {
|
|
19
|
+
" 0": 0,
|
|
20
|
+
" 1": 0,
|
|
21
|
+
" 2": 0,
|
|
22
|
+
" 3": 0,
|
|
23
|
+
" 4": 0,
|
|
24
|
+
" 5": 0,
|
|
25
|
+
" 6": 0,
|
|
26
|
+
" 7": 0,
|
|
27
|
+
" 8": 0,
|
|
28
|
+
" 9": 0,
|
|
29
|
+
"##": -1,
|
|
30
|
+
"#_": 0,
|
|
31
|
+
"',": 0,
|
|
32
|
+
"'.": 0,
|
|
33
|
+
"'/": 0,
|
|
34
|
+
"'J": 0,
|
|
35
|
+
"'S": 0,
|
|
36
|
+
"'_": 0,
|
|
37
|
+
"'j": 0,
|
|
38
|
+
"'s": 0,
|
|
39
|
+
"(+": 0,
|
|
40
|
+
"(-": 0,
|
|
41
|
+
"(<": 0,
|
|
42
|
+
"(f": 0,
|
|
43
|
+
"({": 0,
|
|
44
|
+
"(~": 0,
|
|
45
|
+
")_": 0,
|
|
46
|
+
"*,": 0,
|
|
47
|
+
"*.": 0,
|
|
48
|
+
"*/": 0,
|
|
49
|
+
"*S": 0,
|
|
50
|
+
"*_": 0,
|
|
51
|
+
"*j": 0,
|
|
52
|
+
"*s": 0,
|
|
53
|
+
"+)": 0,
|
|
54
|
+
"+,": 0,
|
|
55
|
+
"+.": 0,
|
|
56
|
+
"+/": 0,
|
|
57
|
+
"+>": 0,
|
|
58
|
+
"+?": 0,
|
|
59
|
+
"+I": 0,
|
|
60
|
+
"+S": 0,
|
|
61
|
+
"+T": 0,
|
|
62
|
+
"+Z": 0,
|
|
63
|
+
"+]": 0,
|
|
64
|
+
"+_": 0,
|
|
65
|
+
"+`": 0,
|
|
66
|
+
"+j": 0,
|
|
67
|
+
"+s": 0,
|
|
68
|
+
"+}": 0,
|
|
69
|
+
",'": 0,
|
|
70
|
+
",*": 0,
|
|
71
|
+
",+": 0,
|
|
72
|
+
",-": 0,
|
|
73
|
+
",<": 0,
|
|
74
|
+
",?": 0,
|
|
75
|
+
",T": 0,
|
|
76
|
+
",Y": 0,
|
|
77
|
+
",Z": 0,
|
|
78
|
+
',"': 0,
|
|
79
|
+
",\\": 0,
|
|
80
|
+
",^": 0,
|
|
81
|
+
",`": 0,
|
|
82
|
+
",f": 0,
|
|
83
|
+
",t": 0,
|
|
84
|
+
",z": 0,
|
|
85
|
+
",{": 0,
|
|
86
|
+
",~": 0,
|
|
87
|
+
"-)": 0,
|
|
88
|
+
"-,": 0,
|
|
89
|
+
"--": 0,
|
|
90
|
+
"-.": 0,
|
|
91
|
+
"-/": 0,
|
|
92
|
+
"->": 0,
|
|
93
|
+
"-?": 0,
|
|
94
|
+
"-I": 0,
|
|
95
|
+
"-S": 0,
|
|
96
|
+
"-T": 0,
|
|
97
|
+
"-Z": 0,
|
|
98
|
+
"-]": 0,
|
|
99
|
+
"-_": 0,
|
|
100
|
+
"-`": 0,
|
|
101
|
+
"-j": 0,
|
|
102
|
+
"-s": 0,
|
|
103
|
+
"-}": 0,
|
|
104
|
+
".'": 0,
|
|
105
|
+
".*": 0,
|
|
106
|
+
".+": 0,
|
|
107
|
+
".-": 0,
|
|
108
|
+
".<": 0,
|
|
109
|
+
".?": 0,
|
|
110
|
+
".T": 0,
|
|
111
|
+
".Y": 0,
|
|
112
|
+
".Z": 0,
|
|
113
|
+
'."': 0,
|
|
114
|
+
".\\": 0,
|
|
115
|
+
".^": 0,
|
|
116
|
+
".`": 0,
|
|
117
|
+
".f": 0,
|
|
118
|
+
".t": 0,
|
|
119
|
+
".z": 0,
|
|
120
|
+
".{": 0,
|
|
121
|
+
".~": 0,
|
|
122
|
+
"/,": 0,
|
|
123
|
+
"/.": 0,
|
|
124
|
+
"//": 0,
|
|
125
|
+
"/J": 0,
|
|
126
|
+
"/S": 0,
|
|
127
|
+
"/_": 0,
|
|
128
|
+
"/j": 0,
|
|
129
|
+
"/s": 0,
|
|
130
|
+
"0 ": 0,
|
|
131
|
+
"1 ": 0,
|
|
132
|
+
"1T": 0,
|
|
133
|
+
"1Y": 0,
|
|
134
|
+
"1Z": 0,
|
|
135
|
+
"1f": 0,
|
|
136
|
+
"1t": 0,
|
|
137
|
+
"1z": 0,
|
|
138
|
+
"2 ": 0,
|
|
139
|
+
"3 ": 0,
|
|
140
|
+
"4 ": 0,
|
|
141
|
+
"5 ": 0,
|
|
142
|
+
"6 ": 0,
|
|
143
|
+
"7 ": 0,
|
|
144
|
+
"8 ": 0,
|
|
145
|
+
"9 ": 0,
|
|
146
|
+
":?": 0,
|
|
147
|
+
":T": 0,
|
|
148
|
+
":Z": 0,
|
|
149
|
+
":`": 0,
|
|
150
|
+
";?": 0,
|
|
151
|
+
";T": 0,
|
|
152
|
+
";Z": 0,
|
|
153
|
+
"<+": 0,
|
|
154
|
+
"<-": 0,
|
|
155
|
+
"<<": 0,
|
|
156
|
+
"<f": 0,
|
|
157
|
+
"<{": 0,
|
|
158
|
+
"<~": 0,
|
|
159
|
+
"==": 0,
|
|
160
|
+
"=_": 0,
|
|
161
|
+
">)": 0,
|
|
162
|
+
">,": 0,
|
|
163
|
+
">.": 0,
|
|
164
|
+
">/": 0,
|
|
165
|
+
">>": 0,
|
|
166
|
+
">?": 0,
|
|
167
|
+
">I": 0,
|
|
168
|
+
">S": 0,
|
|
169
|
+
">T": 0,
|
|
170
|
+
">Z": 0,
|
|
171
|
+
">]": 0,
|
|
172
|
+
">_": 0,
|
|
173
|
+
">`": 0,
|
|
174
|
+
">j": 0,
|
|
175
|
+
">s": 0,
|
|
176
|
+
">}": 0,
|
|
177
|
+
"?,": 0,
|
|
178
|
+
"?.": 0,
|
|
179
|
+
"?/": 0,
|
|
180
|
+
"?S": 0,
|
|
181
|
+
"?_": 0,
|
|
182
|
+
"?j": 0,
|
|
183
|
+
"?s": 0,
|
|
184
|
+
"@_": 0,
|
|
185
|
+
"C+": 0,
|
|
186
|
+
"C-": 0,
|
|
187
|
+
"C<": 0,
|
|
188
|
+
Cf: 0,
|
|
189
|
+
"C{": 0,
|
|
190
|
+
"C~": 0,
|
|
191
|
+
D_: 0,
|
|
192
|
+
"E+": 0,
|
|
193
|
+
"E-": 0,
|
|
194
|
+
"E<": 0,
|
|
195
|
+
Ef: 0,
|
|
196
|
+
"E{": 0,
|
|
197
|
+
"E~": 0,
|
|
198
|
+
"F&": 0,
|
|
199
|
+
"F+": 0,
|
|
200
|
+
"F,": 0,
|
|
201
|
+
"F-": 0,
|
|
202
|
+
"F.": 0,
|
|
203
|
+
"F/": 0,
|
|
204
|
+
"F:": 0,
|
|
205
|
+
"F;": 0,
|
|
206
|
+
"F<": 0,
|
|
207
|
+
FJ: 0,
|
|
208
|
+
FS: 0,
|
|
209
|
+
F_: 0,
|
|
210
|
+
Fa: 0,
|
|
211
|
+
Fe: 0,
|
|
212
|
+
Ff: 0,
|
|
213
|
+
Fg: 0,
|
|
214
|
+
Fj: 0,
|
|
215
|
+
Fq: 0,
|
|
216
|
+
Fs: 0,
|
|
217
|
+
"F{": 0,
|
|
218
|
+
"F~": 0,
|
|
219
|
+
"I+": 0,
|
|
220
|
+
"I-": 0,
|
|
221
|
+
"I<": 0,
|
|
222
|
+
If: 0,
|
|
223
|
+
"I{": 0,
|
|
224
|
+
"I~": 0,
|
|
225
|
+
"L'": 0,
|
|
226
|
+
"L*": 0,
|
|
227
|
+
"L+": 0,
|
|
228
|
+
"L-": 0,
|
|
229
|
+
L4: 0,
|
|
230
|
+
L7: 0,
|
|
231
|
+
"L<": 0,
|
|
232
|
+
"L?": 0,
|
|
233
|
+
LT: 0,
|
|
234
|
+
LY: 0,
|
|
235
|
+
LZ: 0,
|
|
236
|
+
'L"': 0,
|
|
237
|
+
"L\\": 0,
|
|
238
|
+
"L^": 0,
|
|
239
|
+
"L`": 0,
|
|
240
|
+
Lf: 0,
|
|
241
|
+
Lt: 0,
|
|
242
|
+
Lz: 0,
|
|
243
|
+
"L{": 0,
|
|
244
|
+
"L~": 0,
|
|
245
|
+
"P,": 0,
|
|
246
|
+
"P.": 0,
|
|
247
|
+
"P/": 0,
|
|
248
|
+
PS: 0,
|
|
249
|
+
P_: 0,
|
|
250
|
+
Pj: 0,
|
|
251
|
+
Ps: 0,
|
|
252
|
+
"S&": 0,
|
|
253
|
+
"S+": 0,
|
|
254
|
+
"S,": 0,
|
|
255
|
+
"S-": 0,
|
|
256
|
+
"S.": 0,
|
|
257
|
+
"S/": 0,
|
|
258
|
+
"S:": 0,
|
|
259
|
+
"S;": 0,
|
|
260
|
+
"S<": 0,
|
|
261
|
+
SJ: 0,
|
|
262
|
+
SS: 0,
|
|
263
|
+
S_: 0,
|
|
264
|
+
Sa: 0,
|
|
265
|
+
Se: 0,
|
|
266
|
+
Sf: 0,
|
|
267
|
+
Sg: 0,
|
|
268
|
+
Sj: 0,
|
|
269
|
+
Sq: 0,
|
|
270
|
+
Ss: 0,
|
|
271
|
+
"S{": 0,
|
|
272
|
+
"S~": 0,
|
|
273
|
+
"T&": 0,
|
|
274
|
+
"T+": 0,
|
|
275
|
+
"T,": 0,
|
|
276
|
+
"T-": 0,
|
|
277
|
+
"T.": 0,
|
|
278
|
+
"T/": 0,
|
|
279
|
+
"T:": 0,
|
|
280
|
+
"T;": 0,
|
|
281
|
+
"T<": 0,
|
|
282
|
+
TJ: 0,
|
|
283
|
+
TS: 0,
|
|
284
|
+
T_: 0,
|
|
285
|
+
Ta: 0,
|
|
286
|
+
Te: 0,
|
|
287
|
+
Tf: 0,
|
|
288
|
+
Tg: 0,
|
|
289
|
+
Tj: 0,
|
|
290
|
+
Tq: 0,
|
|
291
|
+
Ts: 0,
|
|
292
|
+
"T{": 0,
|
|
293
|
+
"T~": 0,
|
|
294
|
+
V_: 0,
|
|
295
|
+
"Y,": 0,
|
|
296
|
+
"Y.": 0,
|
|
297
|
+
"Y/": 0,
|
|
298
|
+
YS: 0,
|
|
299
|
+
Y_: 0,
|
|
300
|
+
Yj: 0,
|
|
301
|
+
Ys: 0,
|
|
302
|
+
"Z'": 0,
|
|
303
|
+
"Z*": 0,
|
|
304
|
+
"Z+": 0,
|
|
305
|
+
"Z-": 0,
|
|
306
|
+
Z4: 0,
|
|
307
|
+
Z7: 0,
|
|
308
|
+
"Z<": 0,
|
|
309
|
+
"Z?": 0,
|
|
310
|
+
ZT: 0,
|
|
311
|
+
ZY: 0,
|
|
312
|
+
ZZ: 0,
|
|
313
|
+
'Z"': 0,
|
|
314
|
+
"Z\\": 0,
|
|
315
|
+
"Z^": 0,
|
|
316
|
+
"Z`": 0,
|
|
317
|
+
Zf: 0,
|
|
318
|
+
Zt: 0,
|
|
319
|
+
Zz: 0,
|
|
320
|
+
"Z{": 0,
|
|
321
|
+
"Z~": 0,
|
|
322
|
+
"[+": 0,
|
|
323
|
+
"[-": 0,
|
|
324
|
+
"[<": 0,
|
|
325
|
+
"[f": 0,
|
|
326
|
+
"[{": 0,
|
|
327
|
+
"[~": 0,
|
|
328
|
+
'",': 0,
|
|
329
|
+
'".': 0,
|
|
330
|
+
'"/': 0,
|
|
331
|
+
'"J': 0,
|
|
332
|
+
'"S': 0,
|
|
333
|
+
'"_': 0,
|
|
334
|
+
'"j': 0,
|
|
335
|
+
'"s': 0,
|
|
336
|
+
"\\'": 0,
|
|
337
|
+
"\\*": 0,
|
|
338
|
+
"\\+": 0,
|
|
339
|
+
"\\-": 0,
|
|
340
|
+
"\\<": 0,
|
|
341
|
+
"\\?": 0,
|
|
342
|
+
"\\T": 0,
|
|
343
|
+
"\\Y": 0,
|
|
344
|
+
"\\Z": 0,
|
|
345
|
+
'\\"': 0,
|
|
346
|
+
"\\\\": 0,
|
|
347
|
+
"\\^": 0,
|
|
348
|
+
"\\`": 0,
|
|
349
|
+
"\\f": 0,
|
|
350
|
+
"\\t": 0,
|
|
351
|
+
"\\z": 0,
|
|
352
|
+
"\\{": 0,
|
|
353
|
+
"\\~": 0,
|
|
354
|
+
"^,": 0,
|
|
355
|
+
"^.": 0,
|
|
356
|
+
"^/": 0,
|
|
357
|
+
"^J": 0,
|
|
358
|
+
"^S": 0,
|
|
359
|
+
"^_": 0,
|
|
360
|
+
"^j": 0,
|
|
361
|
+
"^s": 0,
|
|
362
|
+
"_#": 0,
|
|
363
|
+
"_%": 0,
|
|
364
|
+
"_'": 0,
|
|
365
|
+
"_(": 0,
|
|
366
|
+
"_*": 0,
|
|
367
|
+
"_+": 0,
|
|
368
|
+
"_-": 0,
|
|
369
|
+
"_<": 0,
|
|
370
|
+
"_=": 0,
|
|
371
|
+
"_?": 0,
|
|
372
|
+
"_@": 0,
|
|
373
|
+
_T: 0,
|
|
374
|
+
_V: 0,
|
|
375
|
+
_Y: 0,
|
|
376
|
+
_Z: 0,
|
|
377
|
+
'_"': 0,
|
|
378
|
+
"_\\": 0,
|
|
379
|
+
"_^": 0,
|
|
380
|
+
__: 0,
|
|
381
|
+
"_`": 0,
|
|
382
|
+
_a: 0,
|
|
383
|
+
_e: 0,
|
|
384
|
+
_f: 0,
|
|
385
|
+
_t: 0,
|
|
386
|
+
_v: 0,
|
|
387
|
+
_z: 0,
|
|
388
|
+
"_{": 0,
|
|
389
|
+
"_~": 0,
|
|
390
|
+
"`,": 0,
|
|
391
|
+
"`.": 0,
|
|
392
|
+
"`/": 0,
|
|
393
|
+
"`J": 0,
|
|
394
|
+
"`S": 0,
|
|
395
|
+
"`_": 0,
|
|
396
|
+
"`j": 0,
|
|
397
|
+
"`s": 0,
|
|
398
|
+
"f,": 0,
|
|
399
|
+
"f.": 0,
|
|
400
|
+
"f/": 0,
|
|
401
|
+
fS: 0,
|
|
402
|
+
f_: 0,
|
|
403
|
+
fj: 0,
|
|
404
|
+
fs: 0,
|
|
405
|
+
"q#": 0,
|
|
406
|
+
q$: 0,
|
|
407
|
+
"q%": 0,
|
|
408
|
+
"q&": 0,
|
|
409
|
+
"q'": 0,
|
|
410
|
+
"q(": 0,
|
|
411
|
+
"q*": 0,
|
|
412
|
+
"q+": 0,
|
|
413
|
+
"q-": 0,
|
|
414
|
+
q0: 0,
|
|
415
|
+
q1: 0,
|
|
416
|
+
q2: 0,
|
|
417
|
+
q3: 0,
|
|
418
|
+
q4: 0,
|
|
419
|
+
q5: 0,
|
|
420
|
+
q6: 0,
|
|
421
|
+
q7: 0,
|
|
422
|
+
q8: 0,
|
|
423
|
+
q9: 0,
|
|
424
|
+
"q<": 0,
|
|
425
|
+
"q=": 0,
|
|
426
|
+
"q?": 0,
|
|
427
|
+
"q@": 0,
|
|
428
|
+
qA: 0,
|
|
429
|
+
qB: 0,
|
|
430
|
+
qC: 0,
|
|
431
|
+
qD: 0,
|
|
432
|
+
qE: 0,
|
|
433
|
+
qF: 0,
|
|
434
|
+
qG: 0,
|
|
435
|
+
qH: 0,
|
|
436
|
+
qI: 0,
|
|
437
|
+
qJ: 0,
|
|
438
|
+
qK: 0,
|
|
439
|
+
qL: 0,
|
|
440
|
+
qM: 0,
|
|
441
|
+
qN: 0,
|
|
442
|
+
qO: 0,
|
|
443
|
+
qP: 0,
|
|
444
|
+
qQ: 0,
|
|
445
|
+
qR: 0,
|
|
446
|
+
qS: 0,
|
|
447
|
+
qT: 0,
|
|
448
|
+
qU: 0,
|
|
449
|
+
qV: 0,
|
|
450
|
+
qW: 0,
|
|
451
|
+
qX: 0,
|
|
452
|
+
qY: 0,
|
|
453
|
+
qZ: 0,
|
|
454
|
+
"q[": 0,
|
|
455
|
+
'q"': 0,
|
|
456
|
+
"q\\": 0,
|
|
457
|
+
"q]": 0,
|
|
458
|
+
"q^": 0,
|
|
459
|
+
"q`": 0,
|
|
460
|
+
qa: 0,
|
|
461
|
+
qb: 0,
|
|
462
|
+
qc: 0,
|
|
463
|
+
qd: 0,
|
|
464
|
+
qe: 0,
|
|
465
|
+
qf: 0,
|
|
466
|
+
qh: 0,
|
|
467
|
+
qk: 0,
|
|
468
|
+
qm: 0,
|
|
469
|
+
qn: 0,
|
|
470
|
+
qo: 0,
|
|
471
|
+
qq: 0,
|
|
472
|
+
qr: 0,
|
|
473
|
+
qs: 0,
|
|
474
|
+
qt: 0,
|
|
475
|
+
qu: 0,
|
|
476
|
+
qv: 0,
|
|
477
|
+
qw: 0,
|
|
478
|
+
qx: 0,
|
|
479
|
+
qz: 0,
|
|
480
|
+
"q{": 0,
|
|
481
|
+
"q}": 0,
|
|
482
|
+
"q~": 0,
|
|
483
|
+
"r,": 0,
|
|
484
|
+
"r.": 0,
|
|
485
|
+
"r/": 0,
|
|
486
|
+
rS: 0,
|
|
487
|
+
r_: 0,
|
|
488
|
+
rj: -1,
|
|
489
|
+
rs: 0,
|
|
490
|
+
"s,": 0,
|
|
491
|
+
"s.": 0,
|
|
492
|
+
"s/": 0,
|
|
493
|
+
sJ: 0,
|
|
494
|
+
sS: 0,
|
|
495
|
+
s_: 0,
|
|
496
|
+
sj: 0,
|
|
497
|
+
ss: 0,
|
|
498
|
+
"z'": 0,
|
|
499
|
+
"z*": 0,
|
|
500
|
+
"z+": 0,
|
|
501
|
+
"z-": 0,
|
|
502
|
+
z4: 0,
|
|
503
|
+
z7: 0,
|
|
504
|
+
"z<": 0,
|
|
505
|
+
"z?": 0,
|
|
506
|
+
zT: 0,
|
|
507
|
+
zY: 0,
|
|
508
|
+
zZ: 0,
|
|
509
|
+
'z"': 0,
|
|
510
|
+
"z\\": 0,
|
|
511
|
+
"z^": 0,
|
|
512
|
+
"z`": 0,
|
|
513
|
+
zf: 0,
|
|
514
|
+
zt: 0,
|
|
515
|
+
zz: 0,
|
|
516
|
+
"z{": 0,
|
|
517
|
+
"z~": 0,
|
|
518
|
+
"{+": 0,
|
|
519
|
+
"{-": 0,
|
|
520
|
+
"{<": 0,
|
|
521
|
+
"{f": 0,
|
|
522
|
+
"{{": 0,
|
|
523
|
+
"{~": 0,
|
|
524
|
+
"})": 0,
|
|
525
|
+
"},": 0,
|
|
526
|
+
"}.": 0,
|
|
527
|
+
"}/": 0,
|
|
528
|
+
"}>": 0,
|
|
529
|
+
"}?": 0,
|
|
530
|
+
"}I": 0,
|
|
531
|
+
"}S": 0,
|
|
532
|
+
"}T": 0,
|
|
533
|
+
"}Z": 0,
|
|
534
|
+
"}]": 0,
|
|
535
|
+
"}_": 0,
|
|
536
|
+
"}`": 0,
|
|
537
|
+
"}j": 0,
|
|
538
|
+
"}s": 0,
|
|
539
|
+
"}}": 0,
|
|
540
|
+
"~'": 0,
|
|
541
|
+
"~?": 0,
|
|
542
|
+
"~T": 0,
|
|
543
|
+
"~Z": 0,
|
|
544
|
+
'~"': 0,
|
|
545
|
+
"~\\": 0,
|
|
546
|
+
"~^": 0,
|
|
547
|
+
"~_": 0,
|
|
548
|
+
"~`": 0,
|
|
549
|
+
"~t": 0,
|
|
550
|
+
"~z": 0
|
|
551
|
+
},
|
|
552
|
+
defaultKerning: 1,
|
|
553
|
+
defaultWhitespaceKerning: -1,
|
|
554
|
+
endOfLineKerning: 0,
|
|
555
|
+
charWidth: {
|
|
556
|
+
" ": 4,
|
|
557
|
+
"!": 1,
|
|
558
|
+
"#": 5,
|
|
559
|
+
"&": 4,
|
|
560
|
+
"'": 1,
|
|
561
|
+
"(": 2,
|
|
562
|
+
")": 2,
|
|
563
|
+
",": 1,
|
|
564
|
+
".": 1,
|
|
565
|
+
":": 1,
|
|
566
|
+
";": 1,
|
|
567
|
+
"@": 5,
|
|
568
|
+
M: 5,
|
|
569
|
+
W: 5,
|
|
570
|
+
"[": 2,
|
|
571
|
+
"\n": 0,
|
|
572
|
+
"]": 2,
|
|
573
|
+
"`": 2,
|
|
574
|
+
i: 1,
|
|
575
|
+
l: 1,
|
|
576
|
+
m: 5,
|
|
577
|
+
q: 4,
|
|
578
|
+
w: 5,
|
|
579
|
+
"|": 1
|
|
580
|
+
},
|
|
581
|
+
defaultCharWidth: 3
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
// node_modules/mem-font/dist/index.js
|
|
585
|
+
var memProp5x6 = mem_prop_5x6_default;
|
|
586
|
+
|
|
587
|
+
// src/graphics/layer.ts
|
|
588
|
+
var Layer = {
|
|
589
|
+
Top: 0,
|
|
590
|
+
UIA: 1,
|
|
591
|
+
UIB: 2,
|
|
592
|
+
UIC: 3,
|
|
593
|
+
UID: 4,
|
|
594
|
+
UIE: 5,
|
|
595
|
+
UIF: 6,
|
|
596
|
+
UIG: 7,
|
|
597
|
+
A: 8,
|
|
598
|
+
B: 9,
|
|
599
|
+
C: 10,
|
|
600
|
+
D: 11,
|
|
601
|
+
E: 12,
|
|
602
|
+
F: 13,
|
|
603
|
+
Bottom: 14,
|
|
604
|
+
Hidden: 15
|
|
605
|
+
};
|
|
606
|
+
function layerOffset(layer, offset) {
|
|
607
|
+
return Math.max(Layer.Top, Math.min(Layer.Bottom, layer + offset));
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// src/types/geo.ts
|
|
611
|
+
function boxHits(l, r) {
|
|
612
|
+
const rWH = { w: r.w ?? 1, h: r.h ?? 1 };
|
|
613
|
+
if (!l.w || !l.h || !rWH.w || !rWH.h) return false;
|
|
614
|
+
const lXY = { x: l.x ?? 0, y: l.y ?? 0 };
|
|
615
|
+
return lXY.x < r.x + rWH.w && lXY.x + l.w > r.x && lXY.y < r.y + rWH.h && lXY.y + l.h > r.y;
|
|
616
|
+
}
|
|
617
|
+
function whAssign(l, r) {
|
|
618
|
+
l.w = r.w;
|
|
619
|
+
l.h = r.h;
|
|
620
|
+
}
|
|
621
|
+
function whEq(l, r) {
|
|
622
|
+
return l.w === r.w && l.h === r.h;
|
|
623
|
+
}
|
|
624
|
+
function xyAdd(l, r) {
|
|
625
|
+
return { x: l.x + r.x, y: l.y + r.y };
|
|
626
|
+
}
|
|
627
|
+
function xyAssign(l, r) {
|
|
628
|
+
l.x = r.x;
|
|
629
|
+
l.y = r.y;
|
|
630
|
+
}
|
|
631
|
+
function xyDistance(from, to) {
|
|
632
|
+
return xyMagnitude(xySub(from, to));
|
|
633
|
+
}
|
|
634
|
+
function xyEq(l, r) {
|
|
635
|
+
return l.x === r.x && l.y === r.y;
|
|
636
|
+
}
|
|
637
|
+
function xyMagnitude(xy) {
|
|
638
|
+
return Math.hypot(xy.x, xy.y);
|
|
639
|
+
}
|
|
640
|
+
function xyMax(l, r) {
|
|
641
|
+
return { x: Math.max(l.x, r.x), y: Math.max(l.y, r.y) };
|
|
642
|
+
}
|
|
643
|
+
function xyMin(l, r) {
|
|
644
|
+
return { x: Math.min(l.x, r.x), y: Math.min(l.y, r.y) };
|
|
645
|
+
}
|
|
646
|
+
function xySub(l, r) {
|
|
647
|
+
return { x: l.x - r.x, y: l.y - r.y };
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// src/ents/nine-patch-ent.ts
|
|
651
|
+
var NinePatchEnt = class {
|
|
652
|
+
#dir;
|
|
653
|
+
#margin;
|
|
654
|
+
#invalid = true;
|
|
655
|
+
constructor(v2, opts) {
|
|
656
|
+
this.#dir = {
|
|
657
|
+
w: v2.sprites.alloc(),
|
|
658
|
+
nw: v2.sprites.alloc(),
|
|
659
|
+
n: v2.sprites.alloc(),
|
|
660
|
+
ne: v2.sprites.alloc(),
|
|
661
|
+
e: v2.sprites.alloc(),
|
|
662
|
+
se: v2.sprites.alloc(),
|
|
663
|
+
s: v2.sprites.alloc(),
|
|
664
|
+
sw: v2.sprites.alloc(),
|
|
665
|
+
origin: v2.sprites.alloc()
|
|
666
|
+
};
|
|
667
|
+
this.#dir.w.tag = opts.w?.tag ?? opts.e?.tag ?? opts.n.tag;
|
|
668
|
+
this.#dir.n.tag = opts.n.tag;
|
|
669
|
+
this.#dir.e.tag = opts.e?.tag ?? this.#dir.w.tag;
|
|
670
|
+
this.#dir.s.tag = opts.s?.tag ?? this.#dir.n.tag;
|
|
671
|
+
this.#dir.nw.tag = opts.nw?.tag ?? opts.se?.tag ?? opts.n.tag;
|
|
672
|
+
this.#dir.ne.tag = opts.ne?.tag ?? opts.sw?.tag ?? opts.nw?.tag ?? opts.n.tag;
|
|
673
|
+
this.#dir.se.tag = opts.se?.tag ?? this.#dir.nw.tag;
|
|
674
|
+
this.#dir.sw.tag = opts.sw?.tag ?? this.#dir.ne.tag;
|
|
675
|
+
this.#dir.origin.tag = opts.origin.tag;
|
|
676
|
+
this.#dir.w.z = this.#dir.nw.z = this.#dir.n.z = this.#dir.ne.z = this.#dir.e.z = this.#dir.se.z = this.#dir.s.z = this.#dir.sw.z = this.#dir.origin.z = opts.z ?? 0;
|
|
677
|
+
this.#dir.w.stretch = opts.w?.stretch ?? opts.e?.stretch ?? false;
|
|
678
|
+
this.#dir.n.stretch = opts.n.stretch ?? opts.s?.stretch ?? false;
|
|
679
|
+
this.#dir.e.stretch = opts.e?.stretch ?? this.#dir.w.stretch;
|
|
680
|
+
this.#dir.s.stretch = opts.s?.stretch ?? this.#dir.n.stretch;
|
|
681
|
+
this.#dir.nw.stretch = opts.nw?.stretch ?? opts.se?.stretch ?? false;
|
|
682
|
+
this.#dir.ne.stretch = opts.ne?.stretch ?? opts.sw?.stretch ?? false;
|
|
683
|
+
this.#dir.se.stretch = opts.se?.stretch ?? this.#dir.nw.stretch;
|
|
684
|
+
this.#dir.sw.stretch = opts.sw?.stretch ?? this.#dir.ne.stretch;
|
|
685
|
+
this.#dir.origin.stretch = opts.origin.stretch ?? false;
|
|
686
|
+
this.#dir.w.flipX = opts.w?.flip?.x ?? !opts.e?.flip?.x;
|
|
687
|
+
this.#dir.w.flipY = opts.w?.flip?.y ?? !!opts.e?.flip?.y;
|
|
688
|
+
this.#dir.n.flipX = opts.n.flip?.x ?? !!opts.s?.flip?.x;
|
|
689
|
+
this.#dir.n.flipY = opts.n.flip?.y ?? !opts.s?.flip?.y;
|
|
690
|
+
this.#dir.e.flipX = opts.e?.flip?.x ?? !this.#dir.w.flipX;
|
|
691
|
+
this.#dir.e.flipY = opts.e?.flip?.y ?? this.#dir.w.flipY;
|
|
692
|
+
this.#dir.s.flipX = opts.s?.flip?.x ?? this.#dir.n.flipX;
|
|
693
|
+
this.#dir.s.flipY = opts.s?.flip?.y ?? !this.#dir.n.flipY;
|
|
694
|
+
this.#dir.origin.flipX = !!opts.origin.flip?.x;
|
|
695
|
+
this.#dir.origin.flipY = !!opts.origin.flip?.y;
|
|
696
|
+
this.#dir.n.h = opts.border?.n ?? opts.border?.s ?? this.#dir.n.h;
|
|
697
|
+
this.#dir.w.w = opts.border?.w ?? opts.border?.e ?? this.#dir.n.h;
|
|
698
|
+
this.#dir.e.w = opts.border?.e ?? this.#dir.w.w;
|
|
699
|
+
this.#dir.s.h = opts.border?.s ?? this.#dir.n.h;
|
|
700
|
+
this.#dir.nw.w = this.#dir.w.w;
|
|
701
|
+
this.#dir.nw.h = this.#dir.n.h;
|
|
702
|
+
this.#dir.ne.w = this.#dir.e.w;
|
|
703
|
+
this.#dir.ne.h = this.#dir.n.h;
|
|
704
|
+
this.#dir.se.w = this.#dir.e.w;
|
|
705
|
+
this.#dir.se.h = this.#dir.s.h;
|
|
706
|
+
this.#dir.sw.w = this.#dir.w.w;
|
|
707
|
+
this.#dir.sw.h = this.#dir.s.h;
|
|
708
|
+
this.#margin = { w: opts.margin?.w ?? 0, h: opts.margin?.h ?? 0 };
|
|
709
|
+
const w = opts.wh?.w == null ? this.#dir.w.w + this.#dir.n.w + this.#dir.e.w : opts.wh.w;
|
|
710
|
+
this.#dir.n.w = w - 1;
|
|
711
|
+
this.wh = {
|
|
712
|
+
w,
|
|
713
|
+
h: opts.wh?.h == null ? this.#dir.n.h + this.#dir.e.h + this.#dir.s.h : opts.wh.h
|
|
714
|
+
};
|
|
715
|
+
this.#dir.nw.x = (opts.x ?? 0) - 1;
|
|
716
|
+
this.xy = { x: opts.x ?? 0, y: opts.y ?? 0 };
|
|
717
|
+
}
|
|
718
|
+
free(v2) {
|
|
719
|
+
v2.sprites.free(
|
|
720
|
+
this.#dir.w,
|
|
721
|
+
this.#dir.nw,
|
|
722
|
+
this.#dir.n,
|
|
723
|
+
this.#dir.ne,
|
|
724
|
+
this.#dir.e,
|
|
725
|
+
this.#dir.se,
|
|
726
|
+
this.#dir.s,
|
|
727
|
+
this.#dir.sw,
|
|
728
|
+
this.#dir.origin
|
|
729
|
+
);
|
|
730
|
+
}
|
|
731
|
+
update() {
|
|
732
|
+
if (!this.#invalid) return;
|
|
733
|
+
this.#invalid = false;
|
|
734
|
+
return true;
|
|
735
|
+
}
|
|
736
|
+
get wh() {
|
|
737
|
+
return {
|
|
738
|
+
w: this.#dir.w.w + this.#dir.n.w + this.#dir.e.w + this.#margin.w,
|
|
739
|
+
h: this.#dir.n.h + this.#dir.w.h + this.#dir.s.h + this.#margin.h
|
|
740
|
+
};
|
|
741
|
+
}
|
|
742
|
+
set wh(wh) {
|
|
743
|
+
if (whEq(wh, this.wh)) return;
|
|
744
|
+
this.#dir.w.h = wh.h - this.#dir.n.h - this.#dir.s.h - this.#margin.h;
|
|
745
|
+
this.#dir.n.w = wh.w - this.#dir.w.w - this.#dir.e.w - this.#margin.w;
|
|
746
|
+
this.#dir.s.w = this.#dir.n.w;
|
|
747
|
+
this.#dir.e.h = this.#dir.w.h;
|
|
748
|
+
this.#dir.origin.w = this.#dir.n.w;
|
|
749
|
+
this.#dir.origin.h = this.#dir.e.h;
|
|
750
|
+
this.#setXYRight();
|
|
751
|
+
this.#invalid = true;
|
|
752
|
+
}
|
|
753
|
+
get xy() {
|
|
754
|
+
return {
|
|
755
|
+
x: this.#dir.nw.x - this.#margin.w / 2,
|
|
756
|
+
y: this.#dir.nw.y - this.#margin.h / 2
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
set xy(xy) {
|
|
760
|
+
if (xyEq(xy, this.xy)) return;
|
|
761
|
+
this.#dir.nw.x = xy.x + this.#margin.w / 2;
|
|
762
|
+
this.#dir.nw.y = xy.y + this.#margin.h / 2;
|
|
763
|
+
this.#dir.w.x = this.#dir.nw.x;
|
|
764
|
+
this.#dir.w.y = this.#dir.nw.y + this.#dir.nw.h;
|
|
765
|
+
this.#dir.n.x = this.#dir.nw.x + this.#dir.nw.w;
|
|
766
|
+
this.#dir.n.y = this.#dir.nw.y;
|
|
767
|
+
this.#dir.origin.x = this.#dir.n.x;
|
|
768
|
+
this.#dir.origin.y = this.#dir.nw.y + this.#dir.ne.h;
|
|
769
|
+
this.#setXYRight();
|
|
770
|
+
this.#invalid = true;
|
|
771
|
+
}
|
|
772
|
+
#setXYRight() {
|
|
773
|
+
this.#dir.ne.x = this.#dir.n.x + this.#dir.n.w;
|
|
774
|
+
this.#dir.ne.y = this.#dir.nw.y;
|
|
775
|
+
this.#dir.e.x = this.#dir.ne.x;
|
|
776
|
+
this.#dir.e.y = this.#dir.nw.y + this.#dir.ne.h;
|
|
777
|
+
this.#dir.se.x = this.#dir.e.x;
|
|
778
|
+
this.#dir.se.y = this.#dir.e.y + this.#dir.e.h;
|
|
779
|
+
this.#dir.s.x = this.#dir.n.x;
|
|
780
|
+
this.#dir.s.y = this.#dir.se.y;
|
|
781
|
+
this.#dir.sw.x = this.#dir.nw.x;
|
|
782
|
+
this.#dir.sw.y = this.#dir.se.y;
|
|
783
|
+
}
|
|
784
|
+
};
|
|
785
|
+
|
|
786
|
+
// src/text/font.ts
|
|
787
|
+
function fontCharToTag(font, char) {
|
|
788
|
+
let pt = char.codePointAt(0);
|
|
789
|
+
if (pt == null || pt > 255) pt = 63;
|
|
790
|
+
return `${font.id}--${pt.toString(16).padStart(2, "0")}`;
|
|
791
|
+
}
|
|
792
|
+
function fontKerning(font, l, r) {
|
|
793
|
+
if (r == null) return font.endOfLineKerning;
|
|
794
|
+
if (font.kerning[l + r] != null) return font.kerning[l + r];
|
|
795
|
+
if (/^\s?$/.test(l) || /^\s?$/.test(r)) return font.defaultWhitespaceKerning;
|
|
796
|
+
return font.defaultKerning;
|
|
797
|
+
}
|
|
798
|
+
function fontCharWidth(font, letter) {
|
|
799
|
+
return font.charWidth[letter] ?? font.defaultCharWidth;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
// src/text/text-layout.ts
|
|
803
|
+
function layoutText(opts) {
|
|
804
|
+
const chars = [];
|
|
805
|
+
const scale = opts.scale ?? 1;
|
|
806
|
+
const start = opts.start ?? { x: 0, y: 0 };
|
|
807
|
+
const maxW = opts.maxW ?? Infinity;
|
|
808
|
+
let cursor = { x: start.x, y: start.y };
|
|
809
|
+
let w = 0;
|
|
810
|
+
while (chars.length < opts.str.length) {
|
|
811
|
+
const i = chars.length;
|
|
812
|
+
const char = opts.str[i];
|
|
813
|
+
let layout;
|
|
814
|
+
if (char === "\n") layout = layoutNewline(opts.font, cursor, start.x, scale);
|
|
815
|
+
else if (/^\s*$/.test(char)) {
|
|
816
|
+
layout = layoutSpace(
|
|
817
|
+
opts.font,
|
|
818
|
+
cursor,
|
|
819
|
+
maxW,
|
|
820
|
+
tracking(opts.font, char, opts.str[i + 1], scale),
|
|
821
|
+
start.x,
|
|
822
|
+
scale
|
|
823
|
+
);
|
|
824
|
+
} else {
|
|
825
|
+
layout = layoutWord(opts.font, cursor, maxW, opts.str, i, start.x, scale);
|
|
826
|
+
if (cursor.x > 0 && layout.cursor.y === nextLine(opts.font, start.x, cursor.y, scale).y) {
|
|
827
|
+
const wordW = maxW - cursor.x + layout.cursor.x;
|
|
828
|
+
if (wordW <= maxW) {
|
|
829
|
+
cursor = nextLine(opts.font, start.x, cursor.y, scale);
|
|
830
|
+
layout = layoutWord(
|
|
831
|
+
opts.font,
|
|
832
|
+
cursor,
|
|
833
|
+
maxW,
|
|
834
|
+
opts.str,
|
|
835
|
+
i,
|
|
836
|
+
start.x,
|
|
837
|
+
scale
|
|
838
|
+
);
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
chars.push(...layout.chars);
|
|
843
|
+
cursor.x = layout.cursor.x;
|
|
844
|
+
cursor.y = layout.cursor.y;
|
|
845
|
+
w = Math.max(w, layout.cursor.x - start.x);
|
|
846
|
+
}
|
|
847
|
+
return {
|
|
848
|
+
chars,
|
|
849
|
+
cursor,
|
|
850
|
+
wh: { w, h: nextLine(opts.font, start.x, cursor.y, scale).y - start.y }
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
function layoutWord(font, cursor, maxW, word, index, startX, scale) {
|
|
854
|
+
const chars = [];
|
|
855
|
+
let { x, y } = cursor;
|
|
856
|
+
for (; ; index++) {
|
|
857
|
+
const char = word[index];
|
|
858
|
+
if (!char || /^\s*$/.test(char)) break;
|
|
859
|
+
const span = tracking(font, char, word[index + 1], scale);
|
|
860
|
+
if (x > startX && x + span > startX + maxW)
|
|
861
|
+
({ x, y } = nextLine(font, startX, y, scale));
|
|
862
|
+
chars.push({ x, y, w: fontCharWidth(font, char), h: font.cellHeight });
|
|
863
|
+
x += span;
|
|
864
|
+
}
|
|
865
|
+
return { chars, cursor: { x, y } };
|
|
866
|
+
}
|
|
867
|
+
function nextLine(font, startX, curY, scale) {
|
|
868
|
+
return { x: startX, y: curY + font.lineHeight * scale };
|
|
869
|
+
}
|
|
870
|
+
function layoutNewline(font, cursor, startX, scale) {
|
|
871
|
+
return { chars: [void 0], cursor: nextLine(font, startX, cursor.y, scale) };
|
|
872
|
+
}
|
|
873
|
+
function layoutSpace(font, cursor, w, span, startX, scale) {
|
|
874
|
+
const nextCursor = cursor.x > 0 && cursor.x + span >= w ? nextLine(font, startX, cursor.y, scale) : { x: cursor.x + span, y: cursor.y };
|
|
875
|
+
return { chars: [void 0], cursor: nextCursor };
|
|
876
|
+
}
|
|
877
|
+
function tracking(font, l, r, scale) {
|
|
878
|
+
return scale * (fontCharWidth(font, l) + fontKerning(font, l, r));
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
// src/ents/text-ent.ts
|
|
882
|
+
var TextEnt = class {
|
|
883
|
+
#maxW = Infinity;
|
|
884
|
+
#layout = "Outdated";
|
|
885
|
+
#z = Layer.UIA;
|
|
886
|
+
#scale = 1;
|
|
887
|
+
#sprites = [];
|
|
888
|
+
#str = "";
|
|
889
|
+
#wh = { w: 0, h: 0 };
|
|
890
|
+
#xy = { x: 0, y: 0 };
|
|
891
|
+
free(v2) {
|
|
892
|
+
v2.sprites.free(...this.#sprites);
|
|
893
|
+
}
|
|
894
|
+
layout(v2) {
|
|
895
|
+
if (this.#layout !== "Outdated") return false;
|
|
896
|
+
let len = 0;
|
|
897
|
+
const layout = layoutText({
|
|
898
|
+
font: memProp5x6,
|
|
899
|
+
maxW: this.#maxW,
|
|
900
|
+
scale: this.#scale,
|
|
901
|
+
start: this.#xy,
|
|
902
|
+
str: this.#str
|
|
903
|
+
});
|
|
904
|
+
this.#wh = { w: layout.wh.w, h: layout.wh.h };
|
|
905
|
+
for (const [i, char] of layout.chars.entries()) {
|
|
906
|
+
if (char == null) continue;
|
|
907
|
+
const sprite = this.#sprites[len] ??= v2.sprites.alloc();
|
|
908
|
+
sprite.x = char.x;
|
|
909
|
+
sprite.y = char.y;
|
|
910
|
+
sprite.tag = fontCharToTag(memProp5x6, this.#str[i]);
|
|
911
|
+
sprite.stretch = true;
|
|
912
|
+
sprite.w *= this.#scale;
|
|
913
|
+
sprite.h *= this.#scale;
|
|
914
|
+
sprite.z = this.#z;
|
|
915
|
+
len++;
|
|
916
|
+
}
|
|
917
|
+
while (this.#sprites.length > len) v2.sprites.free(this.#sprites.pop());
|
|
918
|
+
this.#layout = "Updated";
|
|
919
|
+
return true;
|
|
920
|
+
}
|
|
921
|
+
get maxW() {
|
|
922
|
+
return this.#maxW;
|
|
923
|
+
}
|
|
924
|
+
set maxW(w) {
|
|
925
|
+
if (w === this.#maxW) return;
|
|
926
|
+
this.#maxW = w;
|
|
927
|
+
this.#layout = "Outdated";
|
|
928
|
+
}
|
|
929
|
+
get scale() {
|
|
930
|
+
return this.#scale;
|
|
931
|
+
}
|
|
932
|
+
set scale(scale) {
|
|
933
|
+
if (scale === this.#scale) return;
|
|
934
|
+
this.#scale = scale;
|
|
935
|
+
this.#layout = "Outdated";
|
|
936
|
+
}
|
|
937
|
+
get text() {
|
|
938
|
+
return this.#str;
|
|
939
|
+
}
|
|
940
|
+
set text(str) {
|
|
941
|
+
if (str === this.#str) return;
|
|
942
|
+
this.#str = str;
|
|
943
|
+
this.#layout = "Outdated";
|
|
944
|
+
}
|
|
945
|
+
update(v2) {
|
|
946
|
+
if (this.#layout === "Rendered") return;
|
|
947
|
+
if (this.#layout === "Outdated") this.layout(v2);
|
|
948
|
+
this.#layout = "Rendered";
|
|
949
|
+
return true;
|
|
950
|
+
}
|
|
951
|
+
get scaledLeading() {
|
|
952
|
+
return memProp5x6.leading * this.#scale;
|
|
953
|
+
}
|
|
954
|
+
get wh() {
|
|
955
|
+
return this.#wh;
|
|
956
|
+
}
|
|
957
|
+
get xy() {
|
|
958
|
+
return this.#xy;
|
|
959
|
+
}
|
|
960
|
+
set xy(xy) {
|
|
961
|
+
if (xyEq(xy, this.#xy)) return;
|
|
962
|
+
this.#xy.x = xy.x;
|
|
963
|
+
this.#xy.y = xy.y;
|
|
964
|
+
this.#layout = "Outdated";
|
|
965
|
+
}
|
|
966
|
+
get z() {
|
|
967
|
+
return this.#z;
|
|
968
|
+
}
|
|
969
|
+
set z(layer) {
|
|
970
|
+
if (layer === this.#z) return;
|
|
971
|
+
this.#z = layer;
|
|
972
|
+
this.#layout = "Outdated";
|
|
973
|
+
}
|
|
974
|
+
};
|
|
975
|
+
|
|
976
|
+
// src/ents/button-ent.ts
|
|
977
|
+
var ButtonEnt = class {
|
|
978
|
+
#button;
|
|
979
|
+
#invalid = true;
|
|
980
|
+
#pressed;
|
|
981
|
+
#selected;
|
|
982
|
+
#started = false;
|
|
983
|
+
#toggle = false;
|
|
984
|
+
#text = new TextEnt();
|
|
985
|
+
#xy = { x: 0, y: 0 };
|
|
986
|
+
constructor(v2, opts) {
|
|
987
|
+
const buttonZ = opts.button.z ?? Layer.UID;
|
|
988
|
+
this.#button = new NinePatchEnt(v2, {
|
|
989
|
+
...opts.button,
|
|
990
|
+
x: opts.x,
|
|
991
|
+
y: opts.y,
|
|
992
|
+
z: buttonZ,
|
|
993
|
+
wh: { w: opts.w, h: opts.h }
|
|
994
|
+
});
|
|
995
|
+
this.#pressed = {
|
|
996
|
+
sprite: v2.sprites.alloc(),
|
|
997
|
+
z: opts.pressed.z ?? layerOffset(buttonZ, 2)
|
|
998
|
+
};
|
|
999
|
+
this.#selected = {
|
|
1000
|
+
sprite: v2.sprites.alloc(),
|
|
1001
|
+
z: opts.selected.z ?? layerOffset(this.#pressed.z, -1)
|
|
1002
|
+
};
|
|
1003
|
+
this.#pressed.sprite.tag = opts.pressed.tag;
|
|
1004
|
+
this.#pressed.sprite.x = opts.x ?? 0;
|
|
1005
|
+
this.#pressed.sprite.y = opts.y ?? 0;
|
|
1006
|
+
this.#pressed.sprite.w = opts.w ?? this.#button.wh.w;
|
|
1007
|
+
this.#pressed.sprite.h = opts.h ?? this.#button.wh.h;
|
|
1008
|
+
this.#pressed.sprite.z = Layer.Hidden;
|
|
1009
|
+
this.#selected.sprite.tag = opts.selected.tag;
|
|
1010
|
+
this.#selected.sprite.x = opts.x ?? 0;
|
|
1011
|
+
this.#selected.sprite.y = opts.y ?? 0;
|
|
1012
|
+
this.#selected.sprite.w = opts.w ?? this.#button.wh.w;
|
|
1013
|
+
this.#selected.sprite.h = opts.h ?? this.#button.wh.h;
|
|
1014
|
+
this.#selected.sprite.z = Layer.Hidden;
|
|
1015
|
+
this.#text.text = opts.text?.text ?? "";
|
|
1016
|
+
this.#text.scale = opts.text?.scale ?? 1;
|
|
1017
|
+
this.#text.layout(v2);
|
|
1018
|
+
this.#moveText(v2);
|
|
1019
|
+
this.#text.maxW = opts.w ?? this.#button.wh.w;
|
|
1020
|
+
this.#text.z = opts.text?.z ?? layerOffset(buttonZ, -1);
|
|
1021
|
+
this.#toggle = opts.toggle ?? false;
|
|
1022
|
+
}
|
|
1023
|
+
get selected() {
|
|
1024
|
+
return this.#selected.z !== Layer.Hidden;
|
|
1025
|
+
}
|
|
1026
|
+
free(v2) {
|
|
1027
|
+
this.#button.free(v2);
|
|
1028
|
+
this.#text.free(v2);
|
|
1029
|
+
v2.sprites.free(this.#selected.sprite, this.#pressed.sprite);
|
|
1030
|
+
}
|
|
1031
|
+
get on() {
|
|
1032
|
+
return this.#pressed.sprite.z !== Layer.Hidden;
|
|
1033
|
+
}
|
|
1034
|
+
// to-do: offStart() for pointer up listen? would need a boundary check too.
|
|
1035
|
+
get onStart() {
|
|
1036
|
+
return this.on && this.#started;
|
|
1037
|
+
}
|
|
1038
|
+
set text(str) {
|
|
1039
|
+
this.#text.text = str;
|
|
1040
|
+
}
|
|
1041
|
+
update(v2) {
|
|
1042
|
+
let invalid = this.#invalid;
|
|
1043
|
+
if (this.#button.update()) invalid = true;
|
|
1044
|
+
if (this.#text.update(v2)) invalid = true;
|
|
1045
|
+
const hitsCursor = !v2.input.handled && !!v2.zoo.cursor?.hits(v2, this.#selected.sprite, "UI");
|
|
1046
|
+
const clickStarted = hitsCursor && v2.input.isOnStart("Click") || v2.zoo.cursor?.keyboard && v2.input.isOnStart("A");
|
|
1047
|
+
const on = clickStarted ? this.#toggle ? !this.on : true : this.#toggle ? this.on : v2.input.isOn("Click") || v2.zoo.cursor?.keyboard && v2.input.isOn("A");
|
|
1048
|
+
this.#started = this.on !== on;
|
|
1049
|
+
if (this.#started) {
|
|
1050
|
+
this.#pressed.sprite.z = on ? this.#pressed.z : Layer.Hidden;
|
|
1051
|
+
invalid = true;
|
|
1052
|
+
}
|
|
1053
|
+
if (hitsCursor && (v2.input.point?.click || v2.input.point?.type === "Mouse")) {
|
|
1054
|
+
invalid ||= this.#selected.sprite.z !== this.#selected.z;
|
|
1055
|
+
this.#selected.sprite.z = this.#selected.z;
|
|
1056
|
+
} else {
|
|
1057
|
+
invalid ||= this.#selected.z !== Layer.Hidden;
|
|
1058
|
+
this.#selected.sprite.z = Layer.Hidden;
|
|
1059
|
+
}
|
|
1060
|
+
v2.input.handled ||= hitsCursor;
|
|
1061
|
+
this.#invalid = false;
|
|
1062
|
+
return invalid;
|
|
1063
|
+
}
|
|
1064
|
+
setXY(v2, xy) {
|
|
1065
|
+
if (xyEq(xy, this.#xy)) return;
|
|
1066
|
+
this.#xy.x = xy.x;
|
|
1067
|
+
this.#xy.y = xy.y;
|
|
1068
|
+
this.#button.xy = xy;
|
|
1069
|
+
this.#moveText(v2);
|
|
1070
|
+
this.#pressed.sprite.xy = xy;
|
|
1071
|
+
this.#selected.sprite.xy = xy;
|
|
1072
|
+
this.#invalid = true;
|
|
1073
|
+
}
|
|
1074
|
+
#moveText(v2) {
|
|
1075
|
+
this.#text.layout(v2);
|
|
1076
|
+
this.#text.xy = {
|
|
1077
|
+
x: this.#button.xy.x + this.#button.wh.w / 2 - this.#text.wh.w / 2,
|
|
1078
|
+
y: this.#button.xy.y + this.#button.wh.h / 2 - (this.#text.wh.h - this.#text.scaledLeading) / 2
|
|
1079
|
+
};
|
|
1080
|
+
}
|
|
1081
|
+
};
|
|
1082
|
+
|
|
1083
|
+
// src/ents/cursor-ent.ts
|
|
1084
|
+
var CursorEnt = class {
|
|
1085
|
+
keyboard = false;
|
|
1086
|
+
#sprite;
|
|
1087
|
+
constructor(v2, tag) {
|
|
1088
|
+
this.#sprite = v2.sprites.alloc();
|
|
1089
|
+
this.#sprite.tag = tag;
|
|
1090
|
+
this.#sprite.z = Layer.Hidden;
|
|
1091
|
+
}
|
|
1092
|
+
free(v2) {
|
|
1093
|
+
v2.sprites.free(this.#sprite);
|
|
1094
|
+
}
|
|
1095
|
+
hitbox(v2, coords) {
|
|
1096
|
+
const lvl = coords === "Level";
|
|
1097
|
+
const hitbox = this.#sprite.hitbox;
|
|
1098
|
+
if (!hitbox) throw Error("cursor has no hitbox");
|
|
1099
|
+
return {
|
|
1100
|
+
x: (lvl ? v2.cam.x : 0) + hitbox.x,
|
|
1101
|
+
y: (lvl ? v2.cam.y : 0) + hitbox.y,
|
|
1102
|
+
w: hitbox.w,
|
|
1103
|
+
h: hitbox.h
|
|
1104
|
+
};
|
|
1105
|
+
}
|
|
1106
|
+
hits(v2, box, coords) {
|
|
1107
|
+
return this.visible && boxHits(this.hitbox(v2, coords), box);
|
|
1108
|
+
}
|
|
1109
|
+
update(v2) {
|
|
1110
|
+
if (v2.input.point?.invalid) {
|
|
1111
|
+
this.#sprite.xy = v2.input.point.local;
|
|
1112
|
+
this.#sprite.z = v2.input.point?.type === "Mouse" ? Layer.Top : Layer.Hidden;
|
|
1113
|
+
return true;
|
|
1114
|
+
}
|
|
1115
|
+
if (this.keyboard && v2.input.isAnyOn("L", "R", "U", "D")) {
|
|
1116
|
+
const epsilon = 1;
|
|
1117
|
+
if (v2.input.isOn("L")) this.#sprite.x -= epsilon;
|
|
1118
|
+
if (v2.input.isOn("R")) this.#sprite.x += epsilon;
|
|
1119
|
+
if (v2.input.isOn("U")) this.#sprite.y -= epsilon;
|
|
1120
|
+
if (v2.input.isOn("D")) this.#sprite.y += epsilon;
|
|
1121
|
+
this.#sprite.z = Layer.Top;
|
|
1122
|
+
return true;
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
get visible() {
|
|
1126
|
+
return this.#sprite.z !== Layer.Hidden;
|
|
1127
|
+
}
|
|
1128
|
+
};
|
|
1129
|
+
|
|
1130
|
+
// src/ents/follow-cam-ent.ts
|
|
1131
|
+
var FollowCamEnt = class {
|
|
1132
|
+
#fill;
|
|
1133
|
+
#invalid = true;
|
|
1134
|
+
#margin = { w: 0, h: 0 };
|
|
1135
|
+
#modulo = { x: 0, y: 0 };
|
|
1136
|
+
#pivot;
|
|
1137
|
+
#sprite;
|
|
1138
|
+
constructor(v2, tag, pivot) {
|
|
1139
|
+
this.#sprite = v2.sprites.alloc();
|
|
1140
|
+
this.#sprite.tag = tag;
|
|
1141
|
+
this.#pivot = pivot;
|
|
1142
|
+
}
|
|
1143
|
+
get fill() {
|
|
1144
|
+
return this.#fill;
|
|
1145
|
+
}
|
|
1146
|
+
set fill(fill) {
|
|
1147
|
+
if (this.#fill === fill) return;
|
|
1148
|
+
this.#fill = fill;
|
|
1149
|
+
this.#invalid = true;
|
|
1150
|
+
}
|
|
1151
|
+
free(v2) {
|
|
1152
|
+
v2.sprites.free(this.#sprite);
|
|
1153
|
+
}
|
|
1154
|
+
get h() {
|
|
1155
|
+
return this.#sprite.h;
|
|
1156
|
+
}
|
|
1157
|
+
set h(h) {
|
|
1158
|
+
if (this.#sprite.h === h) return;
|
|
1159
|
+
this.#sprite.h = h;
|
|
1160
|
+
this.#invalid = true;
|
|
1161
|
+
}
|
|
1162
|
+
get margin() {
|
|
1163
|
+
return this.#margin;
|
|
1164
|
+
}
|
|
1165
|
+
set margin(margin) {
|
|
1166
|
+
if (whEq(margin, this.#margin)) return;
|
|
1167
|
+
whAssign(this.#margin, margin);
|
|
1168
|
+
this.#invalid = true;
|
|
1169
|
+
}
|
|
1170
|
+
get modulo() {
|
|
1171
|
+
return this.#modulo;
|
|
1172
|
+
}
|
|
1173
|
+
set modulo(modulo) {
|
|
1174
|
+
if (xyEq(modulo, this.#modulo)) return;
|
|
1175
|
+
xyAssign(this.#modulo, modulo);
|
|
1176
|
+
this.#invalid = true;
|
|
1177
|
+
}
|
|
1178
|
+
get pivot() {
|
|
1179
|
+
return this.#pivot;
|
|
1180
|
+
}
|
|
1181
|
+
set pivot(pivot) {
|
|
1182
|
+
if (this.#pivot === pivot) return;
|
|
1183
|
+
this.#pivot = pivot;
|
|
1184
|
+
this.#invalid = true;
|
|
1185
|
+
}
|
|
1186
|
+
update(v2) {
|
|
1187
|
+
if (!this.#invalid && !v2.cam.invalid) return;
|
|
1188
|
+
const follow = v2.cam.follow(
|
|
1189
|
+
{ w: this.#sprite.w, h: this.#sprite.h },
|
|
1190
|
+
this.#sprite.z,
|
|
1191
|
+
this.#pivot,
|
|
1192
|
+
{ fill: this.#fill, modulo: this.#modulo, margin: this.#margin }
|
|
1193
|
+
);
|
|
1194
|
+
this.#sprite.x = follow.x;
|
|
1195
|
+
this.#sprite.y = follow.y;
|
|
1196
|
+
this.#invalid = false;
|
|
1197
|
+
return true;
|
|
1198
|
+
}
|
|
1199
|
+
get w() {
|
|
1200
|
+
return this.#sprite.w;
|
|
1201
|
+
}
|
|
1202
|
+
set w(w) {
|
|
1203
|
+
if (this.#sprite.w === w) return;
|
|
1204
|
+
this.#sprite.w = w;
|
|
1205
|
+
this.#invalid = true;
|
|
1206
|
+
}
|
|
1207
|
+
get z() {
|
|
1208
|
+
return this.#sprite.z;
|
|
1209
|
+
}
|
|
1210
|
+
set z(z) {
|
|
1211
|
+
this.#sprite.z = z;
|
|
1212
|
+
}
|
|
1213
|
+
};
|
|
1214
|
+
|
|
1215
|
+
// src/ents/zoo.ts
|
|
1216
|
+
var Zoo = class {
|
|
1217
|
+
#cursor;
|
|
1218
|
+
#ents = /* @__PURE__ */ new Set();
|
|
1219
|
+
add(...ents) {
|
|
1220
|
+
for (const ent of ents) {
|
|
1221
|
+
this.#ents.add(ent);
|
|
1222
|
+
if (ent instanceof CursorEnt) this.#cursor = ent;
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
clear() {
|
|
1226
|
+
this.#cursor = void 0;
|
|
1227
|
+
this.#ents.clear();
|
|
1228
|
+
}
|
|
1229
|
+
get cursor() {
|
|
1230
|
+
return this.#cursor;
|
|
1231
|
+
}
|
|
1232
|
+
remove(...ents) {
|
|
1233
|
+
for (const ent of ents) {
|
|
1234
|
+
this.#ents.delete(ent);
|
|
1235
|
+
if (ent === this.#cursor) this.#cursor = void 0;
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
update(v2) {
|
|
1239
|
+
let invalid = false;
|
|
1240
|
+
for (const ent of this.#ents) if (ent.update?.(v2)) invalid = true;
|
|
1241
|
+
return invalid;
|
|
1242
|
+
}
|
|
1243
|
+
};
|
|
1244
|
+
|
|
1245
|
+
// src/graphics/atlas.ts
|
|
1246
|
+
var animCels = 16;
|
|
1247
|
+
var animMillis = 1e3;
|
|
1248
|
+
var celMillis = animMillis / animCels;
|
|
1249
|
+
|
|
1250
|
+
// src/graphics/atlas-parser.ts
|
|
1251
|
+
function parseAtlas(json) {
|
|
1252
|
+
return {
|
|
1253
|
+
anim: json.anim,
|
|
1254
|
+
celXYWH: parseCelXYWH(json),
|
|
1255
|
+
tags: Object.keys(json.anim)
|
|
1256
|
+
};
|
|
1257
|
+
}
|
|
1258
|
+
function parseCelXYWH(json) {
|
|
1259
|
+
const cels = [];
|
|
1260
|
+
let i = 0;
|
|
1261
|
+
for (const anim of Object.values(json.anim)) {
|
|
1262
|
+
cels.push(...parseXYWH(anim, json.celXY, i));
|
|
1263
|
+
i += anim.cels * 2;
|
|
1264
|
+
}
|
|
1265
|
+
return cels;
|
|
1266
|
+
}
|
|
1267
|
+
function parseXYWH(anim, celXY, i) {
|
|
1268
|
+
const xywh = [];
|
|
1269
|
+
for (let ii = 0; ii < animCels; ii++) {
|
|
1270
|
+
const iii = i + 2 * (ii % anim.cels);
|
|
1271
|
+
xywh.push(celXY[iii], celXY[iii + 1], anim.w, anim.h);
|
|
1272
|
+
}
|
|
1273
|
+
return xywh;
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
// src/graphics/cam.ts
|
|
1277
|
+
var Cam = class {
|
|
1278
|
+
#h = 1;
|
|
1279
|
+
#invalid = true;
|
|
1280
|
+
#minScale = 1;
|
|
1281
|
+
#minWH = { w: Infinity, h: Infinity };
|
|
1282
|
+
#mode = "Int";
|
|
1283
|
+
#scale = 1;
|
|
1284
|
+
#w = 1;
|
|
1285
|
+
#whClient = { w: 1, h: 1 };
|
|
1286
|
+
#x = 0;
|
|
1287
|
+
#y = 0;
|
|
1288
|
+
#zoomOut = 0;
|
|
1289
|
+
center(xy) {
|
|
1290
|
+
this.x = Math.floor(xy.x - this.w / 2);
|
|
1291
|
+
this.y = Math.floor(xy.y - this.h / 2);
|
|
1292
|
+
}
|
|
1293
|
+
/** position in fractional level coordinates. */
|
|
1294
|
+
clientToXY(client) {
|
|
1295
|
+
const local = this.clientToXYLocal(client);
|
|
1296
|
+
return { x: this.#x + local.x, y: this.#y + local.y };
|
|
1297
|
+
}
|
|
1298
|
+
/**
|
|
1299
|
+
* position relative canvas top-left in level scale (like level xy but no cam
|
|
1300
|
+
* offset). often used for UI that is fixed within the cam.
|
|
1301
|
+
*/
|
|
1302
|
+
clientToXYLocal(client) {
|
|
1303
|
+
return {
|
|
1304
|
+
x: client.x / this.#whClient.w * this.#w,
|
|
1305
|
+
y: client.y / this.#whClient.h * this.#h
|
|
1306
|
+
};
|
|
1307
|
+
}
|
|
1308
|
+
follow(wh, z, pivot, opts) {
|
|
1309
|
+
const marginW = opts?.margin?.w ?? 0;
|
|
1310
|
+
let x = z > Layer.UIG ? Math.trunc(this.x) : 0;
|
|
1311
|
+
switch (pivot) {
|
|
1312
|
+
case "SW":
|
|
1313
|
+
case "W":
|
|
1314
|
+
case "NW":
|
|
1315
|
+
x += marginW;
|
|
1316
|
+
break;
|
|
1317
|
+
case "SE":
|
|
1318
|
+
case "E":
|
|
1319
|
+
case "NE":
|
|
1320
|
+
x += this.w - (wh.w + marginW);
|
|
1321
|
+
break;
|
|
1322
|
+
case "N":
|
|
1323
|
+
case "S":
|
|
1324
|
+
case "Origin":
|
|
1325
|
+
x += Math.trunc(this.w / 2) - Math.trunc(wh.w / 2);
|
|
1326
|
+
break;
|
|
1327
|
+
}
|
|
1328
|
+
x -= x % ((opts?.modulo?.x ?? x) || 1);
|
|
1329
|
+
const marginH = opts?.margin?.h ?? 0;
|
|
1330
|
+
let y = z > Layer.UIG ? Math.trunc(this.y) : 0;
|
|
1331
|
+
switch (pivot) {
|
|
1332
|
+
case "N":
|
|
1333
|
+
case "NE":
|
|
1334
|
+
case "NW":
|
|
1335
|
+
y += marginH;
|
|
1336
|
+
break;
|
|
1337
|
+
case "SE":
|
|
1338
|
+
case "S":
|
|
1339
|
+
case "SW":
|
|
1340
|
+
y += this.h - (wh.h + marginH);
|
|
1341
|
+
break;
|
|
1342
|
+
case "E":
|
|
1343
|
+
case "W":
|
|
1344
|
+
case "Origin":
|
|
1345
|
+
y += Math.trunc(this.h / 2) - Math.trunc(wh.h / 2);
|
|
1346
|
+
break;
|
|
1347
|
+
}
|
|
1348
|
+
y -= y % ((opts?.modulo?.y ?? y) || 1);
|
|
1349
|
+
const w = opts?.fill === "X" || opts?.fill === "XY" ? this.w - 2 * marginW : wh.w;
|
|
1350
|
+
const h = opts?.fill === "Y" || opts?.fill === "XY" ? this.h - 2 * marginH : wh.h;
|
|
1351
|
+
return { x, y, w, h };
|
|
1352
|
+
}
|
|
1353
|
+
/** positive int in level px. */
|
|
1354
|
+
get h() {
|
|
1355
|
+
return this.#h;
|
|
1356
|
+
}
|
|
1357
|
+
isVisible(box) {
|
|
1358
|
+
return boxHits(this, box);
|
|
1359
|
+
}
|
|
1360
|
+
/** true if cam moved or resized since last update. */
|
|
1361
|
+
get invalid() {
|
|
1362
|
+
return this.#invalid;
|
|
1363
|
+
}
|
|
1364
|
+
/** positive int or fraction depending on mode. */
|
|
1365
|
+
get minScale() {
|
|
1366
|
+
return this.#minScale;
|
|
1367
|
+
}
|
|
1368
|
+
set minScale(scale) {
|
|
1369
|
+
if (this.#scale === scale) return;
|
|
1370
|
+
this.#scale = scale;
|
|
1371
|
+
this.#invalidateWH();
|
|
1372
|
+
}
|
|
1373
|
+
/**
|
|
1374
|
+
* positive int or infinite min dimensions. set to
|
|
1375
|
+
* `{w: Infinity, h: Infinity}` to always use min scale.
|
|
1376
|
+
*/
|
|
1377
|
+
get minWH() {
|
|
1378
|
+
return this.#minWH;
|
|
1379
|
+
}
|
|
1380
|
+
set minWH(wh) {
|
|
1381
|
+
if (this.#minWH.w === wh.w && this.#minWH.h === wh.h) return;
|
|
1382
|
+
this.#minWH.w = wh.w;
|
|
1383
|
+
this.#minWH.h = wh.h;
|
|
1384
|
+
this.#invalidateWH();
|
|
1385
|
+
}
|
|
1386
|
+
get mode() {
|
|
1387
|
+
return this.#mode;
|
|
1388
|
+
}
|
|
1389
|
+
set mode(mode) {
|
|
1390
|
+
if (this.#mode === mode) return;
|
|
1391
|
+
this.#mode = mode;
|
|
1392
|
+
this.#invalidateWH();
|
|
1393
|
+
}
|
|
1394
|
+
get portrait() {
|
|
1395
|
+
return this.h > this.w;
|
|
1396
|
+
}
|
|
1397
|
+
postupdate() {
|
|
1398
|
+
this.#invalid = false;
|
|
1399
|
+
}
|
|
1400
|
+
/** positive int or fraction depending on mode. */
|
|
1401
|
+
get scale() {
|
|
1402
|
+
return this.#scale;
|
|
1403
|
+
}
|
|
1404
|
+
toString() {
|
|
1405
|
+
return `Cam{(${this.x} ${this.y}) ${this.w}\xD7${this.h}}`;
|
|
1406
|
+
}
|
|
1407
|
+
/**
|
|
1408
|
+
* call after input processing but before ent processing. ents that move the
|
|
1409
|
+
* camera should be called immediately after update so that the invalid state
|
|
1410
|
+
* can be considered.
|
|
1411
|
+
*/
|
|
1412
|
+
update(canvas) {
|
|
1413
|
+
if (!canvas.parentElement) throw Error("canvas has no parent");
|
|
1414
|
+
const { clientWidth, clientHeight } = canvas.parentElement;
|
|
1415
|
+
this.#invalid ||= this.#whClient.w !== clientWidth || this.#whClient.h !== clientHeight;
|
|
1416
|
+
if (!this.#invalid) return;
|
|
1417
|
+
this.#whClient.w = clientWidth;
|
|
1418
|
+
this.#whClient.h = clientHeight;
|
|
1419
|
+
this.#invalidateWH();
|
|
1420
|
+
canvas.width = this.#w;
|
|
1421
|
+
canvas.height = this.#h;
|
|
1422
|
+
canvas.style.width = `${this.#w * this.#scale / devicePixelRatio}px`;
|
|
1423
|
+
canvas.style.height = `${this.#h * this.#scale / devicePixelRatio}px`;
|
|
1424
|
+
}
|
|
1425
|
+
/** positive int in level px. */
|
|
1426
|
+
get w() {
|
|
1427
|
+
return this.#w;
|
|
1428
|
+
}
|
|
1429
|
+
/**
|
|
1430
|
+
* positive int dimensions in client px of canvas (often
|
|
1431
|
+
* `canvas.parentElement.clientWidth/Height` since the canvas is resized)
|
|
1432
|
+
* which is assumed to be max WH.
|
|
1433
|
+
*/
|
|
1434
|
+
get whClient() {
|
|
1435
|
+
return this.#whClient;
|
|
1436
|
+
}
|
|
1437
|
+
/** fractional. */
|
|
1438
|
+
get x() {
|
|
1439
|
+
return this.#x;
|
|
1440
|
+
}
|
|
1441
|
+
set x(x) {
|
|
1442
|
+
this.#invalid ||= this.x !== x;
|
|
1443
|
+
this.#x = x;
|
|
1444
|
+
}
|
|
1445
|
+
/** fractional. */
|
|
1446
|
+
get y() {
|
|
1447
|
+
return this.#y;
|
|
1448
|
+
}
|
|
1449
|
+
set y(y) {
|
|
1450
|
+
this.#invalid ||= this.y !== y;
|
|
1451
|
+
this.#y = y;
|
|
1452
|
+
}
|
|
1453
|
+
/** nonnegative int or fraction depending on mode. */
|
|
1454
|
+
get zoomOut() {
|
|
1455
|
+
return this.#zoomOut;
|
|
1456
|
+
}
|
|
1457
|
+
set zoomOut(out) {
|
|
1458
|
+
out = Math.max(0, out);
|
|
1459
|
+
if (this.#zoomOut === out) return;
|
|
1460
|
+
this.#zoomOut = out;
|
|
1461
|
+
this.#invalidateWH();
|
|
1462
|
+
}
|
|
1463
|
+
#invalidateWH() {
|
|
1464
|
+
this.#invalid = true;
|
|
1465
|
+
const phy = {
|
|
1466
|
+
w: this.#whClient.w * devicePixelRatio,
|
|
1467
|
+
h: this.#whClient.h * devicePixelRatio
|
|
1468
|
+
};
|
|
1469
|
+
const scale = Math.max(
|
|
1470
|
+
this.#minScale,
|
|
1471
|
+
Math.min(phy.w / this.#minWH.w, phy.h / this.#minWH.h) - (this.#mode === "Int" ? Math.trunc(this.#zoomOut) : this.#zoomOut)
|
|
1472
|
+
);
|
|
1473
|
+
this.#scale = this.#mode === "Int" ? Math.trunc(scale) : scale;
|
|
1474
|
+
this.#w = Math.ceil(phy.w / this.#scale);
|
|
1475
|
+
this.#h = Math.ceil(phy.h / this.#scale);
|
|
1476
|
+
}
|
|
1477
|
+
};
|
|
1478
|
+
|
|
1479
|
+
// src/utils/math.ts
|
|
1480
|
+
function mod(dividend, divisor) {
|
|
1481
|
+
return (dividend % divisor + divisor) % divisor;
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
// src/graphics/sprite.ts
|
|
1485
|
+
var drawableBytes = 12;
|
|
1486
|
+
var drawableEpsilon = 1 / 64;
|
|
1487
|
+
var drawableMaxWH = { w: 4095, h: 4095 };
|
|
1488
|
+
var Drawable = class {
|
|
1489
|
+
i;
|
|
1490
|
+
#pool;
|
|
1491
|
+
constructor(pool, i) {
|
|
1492
|
+
this.#pool = pool;
|
|
1493
|
+
this.i = i;
|
|
1494
|
+
}
|
|
1495
|
+
above(draw) {
|
|
1496
|
+
const compare = this.z === draw.z ? (draw.zend ? draw.y + draw.h : draw.y) - (this.zend ? this.y + this.h : this.y) : this.z - draw.z;
|
|
1497
|
+
return compare < 0;
|
|
1498
|
+
}
|
|
1499
|
+
get cel() {
|
|
1500
|
+
const iiic_cccc = this.#pool.view.getUint8(this.i + 10);
|
|
1501
|
+
return iiic_cccc & 31;
|
|
1502
|
+
}
|
|
1503
|
+
/**
|
|
1504
|
+
* [0, 31]. rendered cel offset. call reset() to play animation from start.
|
|
1505
|
+
*/
|
|
1506
|
+
set cel(cel) {
|
|
1507
|
+
const iiic_cccc = this.#pool.view.getUint8(this.i + 10);
|
|
1508
|
+
this.#pool.view.setUint8(this.i + 10, iiic_cccc & ~31 | cel & 31);
|
|
1509
|
+
}
|
|
1510
|
+
/** test if render area overlaps box or sprite render area. */
|
|
1511
|
+
clips(box) {
|
|
1512
|
+
return boxHits(this, box);
|
|
1513
|
+
}
|
|
1514
|
+
get flipX() {
|
|
1515
|
+
const sxyz_llll = this.#pool.view.getUint8(this.i + 6);
|
|
1516
|
+
return !!(sxyz_llll & 64);
|
|
1517
|
+
}
|
|
1518
|
+
set flipX(flip) {
|
|
1519
|
+
const sxyz_llll = this.#pool.view.getUint8(this.i + 6);
|
|
1520
|
+
this.#pool.view.setUint8(this.i + 6, sxyz_llll & ~64 | -flip & 64);
|
|
1521
|
+
}
|
|
1522
|
+
get flipY() {
|
|
1523
|
+
const sxyz_llll = this.#pool.view.getUint8(this.i + 6);
|
|
1524
|
+
return !!(sxyz_llll & 32);
|
|
1525
|
+
}
|
|
1526
|
+
set flipY(flip) {
|
|
1527
|
+
const sxyz_llll = this.#pool.view.getUint8(this.i + 6);
|
|
1528
|
+
this.#pool.view.setUint8(this.i + 6, sxyz_llll & ~32 | -flip & 32);
|
|
1529
|
+
}
|
|
1530
|
+
get h() {
|
|
1531
|
+
const h12_wwww = this.#pool.view.getUint16(this.i + 8, true);
|
|
1532
|
+
return h12_wwww >>> 4;
|
|
1533
|
+
}
|
|
1534
|
+
/** [0, 4095]. */
|
|
1535
|
+
set h(h) {
|
|
1536
|
+
const h12_wwww = this.#pool.view.getUint16(this.i + 8, true);
|
|
1537
|
+
this.#pool.view.setUint16(
|
|
1538
|
+
this.i + 8,
|
|
1539
|
+
h12_wwww & ~(4095 << 4) | (h & 4095) << 4,
|
|
1540
|
+
true
|
|
1541
|
+
);
|
|
1542
|
+
}
|
|
1543
|
+
get id() {
|
|
1544
|
+
const i11_c5 = this.#pool.view.getUint16(this.i + 10, true);
|
|
1545
|
+
return i11_c5 >>> 5 & 2047;
|
|
1546
|
+
}
|
|
1547
|
+
/** [0, 2047]. */
|
|
1548
|
+
set id(id) {
|
|
1549
|
+
const i11_c5 = this.#pool.view.getUint16(this.i + 10, true);
|
|
1550
|
+
this.#pool.view.setUint16(
|
|
1551
|
+
this.i + 10,
|
|
1552
|
+
i11_c5 & ~(2047 << 5) | (id & 2047) << 5,
|
|
1553
|
+
true
|
|
1554
|
+
);
|
|
1555
|
+
}
|
|
1556
|
+
get stretch() {
|
|
1557
|
+
const sxyz_llll = this.#pool.view.getUint8(this.i + 6);
|
|
1558
|
+
return !!(sxyz_llll & 128);
|
|
1559
|
+
}
|
|
1560
|
+
/** wrap texture (default) or stretch to width and height. */
|
|
1561
|
+
set stretch(stretch) {
|
|
1562
|
+
const sxyz_llll = this.#pool.view.getUint8(this.i + 6);
|
|
1563
|
+
this.#pool.view.setUint8(
|
|
1564
|
+
this.i + 6,
|
|
1565
|
+
sxyz_llll & ~128 | -stretch & 128
|
|
1566
|
+
);
|
|
1567
|
+
}
|
|
1568
|
+
get w() {
|
|
1569
|
+
const hhhh_w12 = this.#pool.view.getUint16(this.i + 7, true);
|
|
1570
|
+
return hhhh_w12 & 4095;
|
|
1571
|
+
}
|
|
1572
|
+
/** [0, 4095]. */
|
|
1573
|
+
set w(w) {
|
|
1574
|
+
const hhhh_w12 = this.#pool.view.getUint16(this.i + 7, true);
|
|
1575
|
+
this.#pool.view.setUint16(
|
|
1576
|
+
this.i + 7,
|
|
1577
|
+
hhhh_w12 & ~4095 | w & 4095,
|
|
1578
|
+
true
|
|
1579
|
+
);
|
|
1580
|
+
}
|
|
1581
|
+
get x() {
|
|
1582
|
+
const y8_x24 = this.#pool.view.getUint32(this.i + 0, true);
|
|
1583
|
+
return (y8_x24 << 8 >> 8) / 64;
|
|
1584
|
+
}
|
|
1585
|
+
/** [-131072, 131071.984375] with 1/64th (0.015625) granularity. */
|
|
1586
|
+
set x(x) {
|
|
1587
|
+
const y8_x24 = this.#pool.view.getUint32(this.i + 0, true);
|
|
1588
|
+
this.#pool.view.setUint32(
|
|
1589
|
+
this.i + 0,
|
|
1590
|
+
y8_x24 & ~16777215 | x * 64 & 16777215,
|
|
1591
|
+
true
|
|
1592
|
+
);
|
|
1593
|
+
}
|
|
1594
|
+
get xy() {
|
|
1595
|
+
return { x: this.x, y: this.y };
|
|
1596
|
+
}
|
|
1597
|
+
set xy(xy) {
|
|
1598
|
+
this.x = xy.x;
|
|
1599
|
+
this.y = xy.y;
|
|
1600
|
+
}
|
|
1601
|
+
get y() {
|
|
1602
|
+
const sxyz_llll_y24 = this.#pool.view.getUint32(this.i + 3, true);
|
|
1603
|
+
return (sxyz_llll_y24 << 8 >> 8) / 64;
|
|
1604
|
+
}
|
|
1605
|
+
/** [-131072, 131071.984375] with 1/64th (0.015625) granularity. */
|
|
1606
|
+
set y(y) {
|
|
1607
|
+
const sxyz_llll_y24 = this.#pool.view.getUint32(this.i + 3, true);
|
|
1608
|
+
this.#pool.view.setUint32(
|
|
1609
|
+
this.i + 3,
|
|
1610
|
+
sxyz_llll_y24 & ~16777215 | y * 64 & 16777215,
|
|
1611
|
+
true
|
|
1612
|
+
);
|
|
1613
|
+
}
|
|
1614
|
+
get z() {
|
|
1615
|
+
const sxyz_llll = this.#pool.view.getUint8(this.i + 6);
|
|
1616
|
+
return sxyz_llll & 15;
|
|
1617
|
+
}
|
|
1618
|
+
/** layer [0 (closest), 14 (furthest)]; 15 is hidden. */
|
|
1619
|
+
set z(z) {
|
|
1620
|
+
const sxyz_llll = this.#pool.view.getUint8(this.i + 6);
|
|
1621
|
+
this.#pool.view.setUint8(this.i + 6, sxyz_llll & ~15 | z & 15);
|
|
1622
|
+
}
|
|
1623
|
+
get zend() {
|
|
1624
|
+
const sxyz_llll = this.#pool.view.getUint8(this.i + 6);
|
|
1625
|
+
return !!(sxyz_llll & 16);
|
|
1626
|
+
}
|
|
1627
|
+
/** z-order by top (default) or bottom of box. */
|
|
1628
|
+
set zend(end) {
|
|
1629
|
+
const sxyz_llll = this.#pool.view.getUint8(this.i + 6);
|
|
1630
|
+
this.#pool.view.setUint8(this.i + 6, sxyz_llll & ~16 | -end & 16);
|
|
1631
|
+
}
|
|
1632
|
+
};
|
|
1633
|
+
var Sprite = class _Sprite extends Drawable {
|
|
1634
|
+
#atlas;
|
|
1635
|
+
#framer;
|
|
1636
|
+
#hitbox;
|
|
1637
|
+
#hurtbox;
|
|
1638
|
+
constructor(pool, i, atlas, framer) {
|
|
1639
|
+
super(pool, i);
|
|
1640
|
+
this.#atlas = atlas;
|
|
1641
|
+
this.#framer = framer;
|
|
1642
|
+
}
|
|
1643
|
+
get anim() {
|
|
1644
|
+
return this.#atlas.anim[this.tag];
|
|
1645
|
+
}
|
|
1646
|
+
get flipX() {
|
|
1647
|
+
return super.flipX;
|
|
1648
|
+
}
|
|
1649
|
+
set flipX(flip) {
|
|
1650
|
+
if (this.flipX === flip) return;
|
|
1651
|
+
super.flipX = flip;
|
|
1652
|
+
this.#hitbox = void 0;
|
|
1653
|
+
this.#hurtbox = void 0;
|
|
1654
|
+
}
|
|
1655
|
+
get flipY() {
|
|
1656
|
+
return super.flipY;
|
|
1657
|
+
}
|
|
1658
|
+
set flipY(flip) {
|
|
1659
|
+
if (this.flipY === flip) return;
|
|
1660
|
+
super.flipY = flip;
|
|
1661
|
+
this.#hitbox = void 0;
|
|
1662
|
+
this.#hurtbox = void 0;
|
|
1663
|
+
}
|
|
1664
|
+
get h() {
|
|
1665
|
+
return super.h;
|
|
1666
|
+
}
|
|
1667
|
+
set h(h) {
|
|
1668
|
+
if (this.h === h) return;
|
|
1669
|
+
super.h = h;
|
|
1670
|
+
this.#hitbox = void 0;
|
|
1671
|
+
this.#hurtbox = void 0;
|
|
1672
|
+
}
|
|
1673
|
+
get hitbox() {
|
|
1674
|
+
if (this.#hitbox) return this.#hitbox;
|
|
1675
|
+
const { hitbox } = this.anim;
|
|
1676
|
+
if (!hitbox) return;
|
|
1677
|
+
return this.#hitbox ??= {
|
|
1678
|
+
x: this.x + (this.flipX ? this.w - hitbox.w - hitbox.x : hitbox.x),
|
|
1679
|
+
y: this.y + (this.flipY ? this.h - hitbox.h - hitbox.y : hitbox.y),
|
|
1680
|
+
w: hitbox.w,
|
|
1681
|
+
h: hitbox.h
|
|
1682
|
+
};
|
|
1683
|
+
}
|
|
1684
|
+
hits(box) {
|
|
1685
|
+
const hitbox = this.hitbox;
|
|
1686
|
+
if (!hitbox) return false;
|
|
1687
|
+
const hurtbox = box instanceof _Sprite ? box.hurtbox : box;
|
|
1688
|
+
return !!hurtbox && boxHits(hitbox, hurtbox);
|
|
1689
|
+
}
|
|
1690
|
+
get hurtbox() {
|
|
1691
|
+
if (this.#hurtbox) return this.#hurtbox;
|
|
1692
|
+
const { hurtbox } = this.anim;
|
|
1693
|
+
if (!hurtbox) return;
|
|
1694
|
+
return this.#hurtbox ??= {
|
|
1695
|
+
x: this.x + (this.flipX ? this.w - hurtbox.w - hurtbox.x : hurtbox.x),
|
|
1696
|
+
y: this.y + (this.flipY ? this.h - hurtbox.h - hurtbox.y : hurtbox.y),
|
|
1697
|
+
w: hurtbox.w,
|
|
1698
|
+
h: hurtbox.h
|
|
1699
|
+
};
|
|
1700
|
+
}
|
|
1701
|
+
get id() {
|
|
1702
|
+
return super.id;
|
|
1703
|
+
}
|
|
1704
|
+
set id(id) {
|
|
1705
|
+
if (this.id === id) return;
|
|
1706
|
+
super.id = id;
|
|
1707
|
+
this.#hitbox = void 0;
|
|
1708
|
+
this.#hurtbox = void 0;
|
|
1709
|
+
}
|
|
1710
|
+
/** true if animation has played once. */
|
|
1711
|
+
get looped() {
|
|
1712
|
+
return mod(this.#currentCel - this.cel, animCels * 2) >= this.anim.cels;
|
|
1713
|
+
}
|
|
1714
|
+
/** sets cel to animation start. */
|
|
1715
|
+
reset() {
|
|
1716
|
+
this.cel = this.#currentCel;
|
|
1717
|
+
}
|
|
1718
|
+
// to-do: unit test and catch up on unit tests elsewhere.
|
|
1719
|
+
get tag() {
|
|
1720
|
+
return this.#atlas.tags[this.id];
|
|
1721
|
+
}
|
|
1722
|
+
/** sets animation, resets cel, dimensions, hitbox, and hurtbox. */
|
|
1723
|
+
set tag(tag) {
|
|
1724
|
+
const anim = this.#atlas.anim[tag];
|
|
1725
|
+
this.w = anim.w;
|
|
1726
|
+
this.h = anim.h;
|
|
1727
|
+
this.id = anim.id;
|
|
1728
|
+
this.reset();
|
|
1729
|
+
}
|
|
1730
|
+
toString() {
|
|
1731
|
+
return `Sprite{${this.tag} (${this.x} ${this.y} ${this.z}) ${this.w}\xD7${this.h}}`;
|
|
1732
|
+
}
|
|
1733
|
+
get w() {
|
|
1734
|
+
return super.w;
|
|
1735
|
+
}
|
|
1736
|
+
set w(w) {
|
|
1737
|
+
if (this.w === w) return;
|
|
1738
|
+
super.w = w;
|
|
1739
|
+
this.#hitbox = void 0;
|
|
1740
|
+
this.#hurtbox = void 0;
|
|
1741
|
+
}
|
|
1742
|
+
get x() {
|
|
1743
|
+
return super.x;
|
|
1744
|
+
}
|
|
1745
|
+
set x(x) {
|
|
1746
|
+
if (this.x === x) return;
|
|
1747
|
+
super.x = x;
|
|
1748
|
+
this.#hitbox = void 0;
|
|
1749
|
+
this.#hurtbox = void 0;
|
|
1750
|
+
}
|
|
1751
|
+
get y() {
|
|
1752
|
+
return super.y;
|
|
1753
|
+
}
|
|
1754
|
+
set y(y) {
|
|
1755
|
+
if (this.y === y) return;
|
|
1756
|
+
super.y = y;
|
|
1757
|
+
this.#hitbox = void 0;
|
|
1758
|
+
this.#hurtbox = void 0;
|
|
1759
|
+
}
|
|
1760
|
+
/** current fractional cel in [0, 2 * anim.cels). */
|
|
1761
|
+
get #currentCel() {
|
|
1762
|
+
const cel = this.#framer.age / celMillis;
|
|
1763
|
+
return cel % (this.anim.cels * 2);
|
|
1764
|
+
}
|
|
1765
|
+
};
|
|
1766
|
+
|
|
1767
|
+
// src/input/context-menu.ts
|
|
1768
|
+
var ContextMenu = class {
|
|
1769
|
+
enable = false;
|
|
1770
|
+
#target;
|
|
1771
|
+
constructor(target) {
|
|
1772
|
+
this.#target = target;
|
|
1773
|
+
}
|
|
1774
|
+
register(op) {
|
|
1775
|
+
const fn = this.#target[`${op}EventListener`].bind(this.#target);
|
|
1776
|
+
fn("contextmenu", this.#onContextMenu);
|
|
1777
|
+
fn("touchstart", this.#onContextMenu, { passive: false });
|
|
1778
|
+
return this;
|
|
1779
|
+
}
|
|
1780
|
+
[Symbol.dispose]() {
|
|
1781
|
+
this.register("remove");
|
|
1782
|
+
}
|
|
1783
|
+
#onContextMenu = (ev) => {
|
|
1784
|
+
if (!ev.isTrusted || ev.metaKey || ev.altKey || ev.ctrlKey) return;
|
|
1785
|
+
if (!this.enable) ev.preventDefault();
|
|
1786
|
+
};
|
|
1787
|
+
};
|
|
1788
|
+
|
|
1789
|
+
// src/input/gamepad.ts
|
|
1790
|
+
var Gamepad = class {
|
|
1791
|
+
bits = 0;
|
|
1792
|
+
// to-do: support analog button values, expose connected status and vibration,
|
|
1793
|
+
// and distinct devices. would be nice if vibration could merge with
|
|
1794
|
+
// navigator.vibrate().
|
|
1795
|
+
bitByAxis = {};
|
|
1796
|
+
bitByButton = {};
|
|
1797
|
+
onEvent = () => {
|
|
1798
|
+
};
|
|
1799
|
+
#target;
|
|
1800
|
+
constructor(target) {
|
|
1801
|
+
this.#target = target;
|
|
1802
|
+
}
|
|
1803
|
+
get connected() {
|
|
1804
|
+
return isSecureContext && navigator.getGamepads().filter(Boolean).length > 0;
|
|
1805
|
+
}
|
|
1806
|
+
register(op) {
|
|
1807
|
+
const fn = this.#target[`${op}EventListener`].bind(this.#target);
|
|
1808
|
+
fn("gamepadconnected", this.onEvent);
|
|
1809
|
+
fn("gamepaddisconnected", this.onEvent);
|
|
1810
|
+
return this;
|
|
1811
|
+
}
|
|
1812
|
+
reset() {
|
|
1813
|
+
this.bits = 0;
|
|
1814
|
+
}
|
|
1815
|
+
[Symbol.dispose]() {
|
|
1816
|
+
this.register("remove");
|
|
1817
|
+
}
|
|
1818
|
+
update() {
|
|
1819
|
+
if (!isSecureContext) return;
|
|
1820
|
+
for (const pad of navigator.getGamepads()) {
|
|
1821
|
+
for (const [index, axis] of pad?.axes.entries() ?? []) {
|
|
1822
|
+
const lessMore = this.bitByAxis[index];
|
|
1823
|
+
if (!lessMore) continue;
|
|
1824
|
+
const bit = axis < 0 ? lessMore[0] : axis === 0 ? 0 : lessMore[1];
|
|
1825
|
+
this.bits |= Math.abs(axis) >= 0.5 ? bit : 0;
|
|
1826
|
+
}
|
|
1827
|
+
for (const [index, btn] of pad?.buttons.entries() ?? []) {
|
|
1828
|
+
const bit = this.bitByButton[index];
|
|
1829
|
+
if (bit == null) continue;
|
|
1830
|
+
this.bits |= btn.pressed ? bit : 0;
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
};
|
|
1835
|
+
|
|
1836
|
+
// src/input/keyboard.ts
|
|
1837
|
+
var Keyboard = class {
|
|
1838
|
+
/** KeyboardEvent.code to bit. */
|
|
1839
|
+
bitByCode = {};
|
|
1840
|
+
invalid = false;
|
|
1841
|
+
/** KeyboardEvent.code to state. Multiple keys may map to the same bit. */
|
|
1842
|
+
onEvent = () => {
|
|
1843
|
+
};
|
|
1844
|
+
#on = {};
|
|
1845
|
+
#target;
|
|
1846
|
+
constructor(target) {
|
|
1847
|
+
this.#target = target;
|
|
1848
|
+
}
|
|
1849
|
+
get bits() {
|
|
1850
|
+
let bits = 0;
|
|
1851
|
+
for (const k in this.bitByCode) bits |= this.#on[k] ? this.bitByCode[k] : 0;
|
|
1852
|
+
return bits;
|
|
1853
|
+
}
|
|
1854
|
+
postupdate() {
|
|
1855
|
+
this.invalid = false;
|
|
1856
|
+
}
|
|
1857
|
+
register(op) {
|
|
1858
|
+
const fn = this.#target[`${op}EventListener`].bind(this.#target);
|
|
1859
|
+
for (const ev of ["keydown", "keyup"]) fn(ev, this.#onKey);
|
|
1860
|
+
return this;
|
|
1861
|
+
}
|
|
1862
|
+
reset() {
|
|
1863
|
+
this.invalid = false;
|
|
1864
|
+
this.#on = {};
|
|
1865
|
+
}
|
|
1866
|
+
[Symbol.dispose]() {
|
|
1867
|
+
this.register("remove");
|
|
1868
|
+
}
|
|
1869
|
+
#onKey = (ev) => {
|
|
1870
|
+
if (!ev.isTrusted || this.bitByCode[ev.code] == null) return;
|
|
1871
|
+
if (ev.type === "keydown" && (ev.metaKey || ev.altKey || ev.ctrlKey)) return;
|
|
1872
|
+
this.invalid = true;
|
|
1873
|
+
this.#on[ev.code] = ev.type === "keydown";
|
|
1874
|
+
ev.preventDefault();
|
|
1875
|
+
this.onEvent();
|
|
1876
|
+
};
|
|
1877
|
+
};
|
|
1878
|
+
|
|
1879
|
+
// src/input/pointer.ts
|
|
1880
|
+
var pointTypeByPointerType = {
|
|
1881
|
+
mouse: "Mouse",
|
|
1882
|
+
pen: "Pen",
|
|
1883
|
+
touch: "Touch"
|
|
1884
|
+
};
|
|
1885
|
+
var pointEvents = [
|
|
1886
|
+
"pointercancel",
|
|
1887
|
+
"pointerdown",
|
|
1888
|
+
"pointermove",
|
|
1889
|
+
"pointerup"
|
|
1890
|
+
];
|
|
1891
|
+
var Pointer = class {
|
|
1892
|
+
bitByButton = {};
|
|
1893
|
+
dragMinClient = 5;
|
|
1894
|
+
invalid = false;
|
|
1895
|
+
onEvent = () => {
|
|
1896
|
+
};
|
|
1897
|
+
/** primary may be on or off. */
|
|
1898
|
+
primary;
|
|
1899
|
+
/**
|
|
1900
|
+
* secondaries are deleted when buttons are off. secondaries are only present
|
|
1901
|
+
* when primary is defined.
|
|
1902
|
+
*/
|
|
1903
|
+
secondary = {};
|
|
1904
|
+
/** nonnegative. */
|
|
1905
|
+
#pinchStartClient;
|
|
1906
|
+
#target;
|
|
1907
|
+
constructor(target) {
|
|
1908
|
+
this.#target = target;
|
|
1909
|
+
}
|
|
1910
|
+
get boundsClient() {
|
|
1911
|
+
if (!this.primary?.bits && !Object.keys(this.secondary).length) return;
|
|
1912
|
+
let min = { x: Infinity, y: Infinity };
|
|
1913
|
+
let max = { x: -Infinity, y: -Infinity };
|
|
1914
|
+
for (const pt of [this.primary, ...Object.values(this.secondary)]) {
|
|
1915
|
+
if (!pt?.bits) continue;
|
|
1916
|
+
min = xyMin(min, pt.xyClient);
|
|
1917
|
+
max = xyMax(max, pt.xyClient);
|
|
1918
|
+
}
|
|
1919
|
+
return { x: min.x, y: min.y, w: max.x - min.x, h: max.y - min.y };
|
|
1920
|
+
}
|
|
1921
|
+
get centerClient() {
|
|
1922
|
+
const bounds = this.boundsClient;
|
|
1923
|
+
if (!bounds) return this.primary?.xyClient;
|
|
1924
|
+
return xyAdd(bounds, { x: bounds.w / 2, y: bounds.h / 2 });
|
|
1925
|
+
}
|
|
1926
|
+
get locked() {
|
|
1927
|
+
return this.#target.ownerDocument.pointerLockElement === this.#target;
|
|
1928
|
+
}
|
|
1929
|
+
get pinchClient() {
|
|
1930
|
+
if (!this.#pinchStartClient) return;
|
|
1931
|
+
const end = this.#newPinchClient;
|
|
1932
|
+
return end ? xySub(end, this.#pinchStartClient) : void 0;
|
|
1933
|
+
}
|
|
1934
|
+
postupdate() {
|
|
1935
|
+
this.invalid = false;
|
|
1936
|
+
}
|
|
1937
|
+
register(op) {
|
|
1938
|
+
const fn = this.#target[`${op}EventListener`].bind(this.#target);
|
|
1939
|
+
for (const ev of pointEvents) fn(ev, this.#onInput);
|
|
1940
|
+
return this;
|
|
1941
|
+
}
|
|
1942
|
+
reset() {
|
|
1943
|
+
this.invalid = false;
|
|
1944
|
+
this.primary = void 0;
|
|
1945
|
+
for (const pt in this.secondary) delete this.secondary[pt];
|
|
1946
|
+
this.#pinchStartClient = void 0;
|
|
1947
|
+
}
|
|
1948
|
+
update() {
|
|
1949
|
+
const on = (this.primary?.bits ? 1 : 0) + Object.values(this.secondary).length;
|
|
1950
|
+
if (on < 2 || !this.#pinchStartClient)
|
|
1951
|
+
this.#pinchStartClient = this.#newPinchClient;
|
|
1952
|
+
}
|
|
1953
|
+
[Symbol.dispose]() {
|
|
1954
|
+
this.register("remove");
|
|
1955
|
+
}
|
|
1956
|
+
#evButtonsToBits(btns) {
|
|
1957
|
+
let bits = 0;
|
|
1958
|
+
for (let btn = 1; btn <= btns; btn <<= 1)
|
|
1959
|
+
if ((btn & btns) === btn) bits |= this.bitByButton[btn] ?? 0;
|
|
1960
|
+
return bits;
|
|
1961
|
+
}
|
|
1962
|
+
#onInput = (ev) => {
|
|
1963
|
+
if (!ev.isTrusted) return;
|
|
1964
|
+
this.invalid = true;
|
|
1965
|
+
const bits = ev.metaKey || ev.altKey || ev.ctrlKey ? 0 : this.#evButtonsToBits(ev.buttons);
|
|
1966
|
+
if (bits) ev.preventDefault();
|
|
1967
|
+
const locked = this.locked;
|
|
1968
|
+
if (ev.type === "pointerdown" && !locked)
|
|
1969
|
+
try {
|
|
1970
|
+
this.#target.setPointerCapture(ev.pointerId);
|
|
1971
|
+
} catch {
|
|
1972
|
+
}
|
|
1973
|
+
const prevPt = ev.isPrimary ? this.primary : this.secondary[ev.pointerId];
|
|
1974
|
+
let xyClient;
|
|
1975
|
+
if (locked) {
|
|
1976
|
+
const scale = 1 / devicePixelRatio;
|
|
1977
|
+
xyClient = {
|
|
1978
|
+
x: Math.min(
|
|
1979
|
+
Math.max(
|
|
1980
|
+
0,
|
|
1981
|
+
(prevPt?.xyClient.x ?? ev.offsetX) + ev.movementX * scale
|
|
1982
|
+
),
|
|
1983
|
+
this.#target.clientWidth
|
|
1984
|
+
),
|
|
1985
|
+
y: Math.min(
|
|
1986
|
+
Math.max(
|
|
1987
|
+
0,
|
|
1988
|
+
(prevPt?.xyClient.y ?? ev.offsetY) + ev.movementY * scale
|
|
1989
|
+
),
|
|
1990
|
+
this.#target.clientHeight
|
|
1991
|
+
)
|
|
1992
|
+
};
|
|
1993
|
+
} else xyClient = { x: ev.offsetX, y: ev.offsetY };
|
|
1994
|
+
const evType = ev.type;
|
|
1995
|
+
const type = pointTypeByPointerType[ev.pointerType];
|
|
1996
|
+
let clickClient;
|
|
1997
|
+
if (ev.type === "pointerdown") clickClient = { x: xyClient.x, y: xyClient.y };
|
|
1998
|
+
else if (ev.type === "pointermove") clickClient = prevPt?.clickClient;
|
|
1999
|
+
const drag = !!bits && (prevPt?.drag || !!clickClient && xyDistance(clickClient, xyClient) >= this.dragMinClient);
|
|
2000
|
+
const pt = {
|
|
2001
|
+
clickClient,
|
|
2002
|
+
bits,
|
|
2003
|
+
drag,
|
|
2004
|
+
ev: evType,
|
|
2005
|
+
id: ev.pointerId,
|
|
2006
|
+
primary: ev.isPrimary,
|
|
2007
|
+
type,
|
|
2008
|
+
xyClient
|
|
2009
|
+
};
|
|
2010
|
+
if (ev.isPrimary) this.primary = pt;
|
|
2011
|
+
else if (!bits) delete this.secondary[ev.pointerId];
|
|
2012
|
+
else this.secondary[ev.pointerId] = pt;
|
|
2013
|
+
this.onEvent();
|
|
2014
|
+
};
|
|
2015
|
+
get #newPinchClient() {
|
|
2016
|
+
if ((this.primary?.bits ? 1 : 0) + Object.values(this.secondary).length < 2)
|
|
2017
|
+
return;
|
|
2018
|
+
const bounds = this.boundsClient;
|
|
2019
|
+
return bounds ? { x: bounds.w, y: bounds.h } : void 0;
|
|
2020
|
+
}
|
|
2021
|
+
};
|
|
2022
|
+
|
|
2023
|
+
// src/input/wheel.ts
|
|
2024
|
+
var Wheel = class {
|
|
2025
|
+
deltaClient;
|
|
2026
|
+
onEvent = () => {
|
|
2027
|
+
};
|
|
2028
|
+
#target;
|
|
2029
|
+
constructor(target) {
|
|
2030
|
+
this.#target = target;
|
|
2031
|
+
}
|
|
2032
|
+
postupdate() {
|
|
2033
|
+
this.deltaClient = void 0;
|
|
2034
|
+
}
|
|
2035
|
+
register(op) {
|
|
2036
|
+
const fn = this.#target[`${op}EventListener`].bind(this.#target);
|
|
2037
|
+
fn("wheel", this.#onInput, { passive: true });
|
|
2038
|
+
return this;
|
|
2039
|
+
}
|
|
2040
|
+
reset() {
|
|
2041
|
+
this.deltaClient = void 0;
|
|
2042
|
+
}
|
|
2043
|
+
[Symbol.dispose]() {
|
|
2044
|
+
this.register("remove");
|
|
2045
|
+
}
|
|
2046
|
+
#onInput = (ev) => {
|
|
2047
|
+
if (!ev.isTrusted || ev.metaKey || ev.altKey || ev.ctrlKey) return;
|
|
2048
|
+
this.deltaClient = { x: ev.deltaX, y: ev.deltaY, z: ev.deltaZ };
|
|
2049
|
+
this.onEvent();
|
|
2050
|
+
};
|
|
2051
|
+
};
|
|
2052
|
+
|
|
2053
|
+
// src/input/input.ts
|
|
2054
|
+
var Input = class {
|
|
2055
|
+
/** time allowed between combo inputs. */
|
|
2056
|
+
comboMaxIntervalMillis = 300;
|
|
2057
|
+
/**
|
|
2058
|
+
* true if any button, key, or click was _ever_ on. doesn't consider handled.
|
|
2059
|
+
*/
|
|
2060
|
+
gestured = false;
|
|
2061
|
+
/** clear buttonish inputs for rest of frame. */
|
|
2062
|
+
handled = false;
|
|
2063
|
+
/** true if _any_ input has changed since previous update. */
|
|
2064
|
+
invalid = false;
|
|
2065
|
+
/**
|
|
2066
|
+
* minimum duration for an input to be considered held. durations are
|
|
2067
|
+
* calculated at frame boundaries, not on actual press. devices are treated
|
|
2068
|
+
* strictly as polled aggregates.
|
|
2069
|
+
*/
|
|
2070
|
+
minHeldMillis = 300;
|
|
2071
|
+
#bitByButton = {};
|
|
2072
|
+
#buttonByBit = {};
|
|
2073
|
+
#bits = 0;
|
|
2074
|
+
#cam;
|
|
2075
|
+
/**
|
|
2076
|
+
* sequence of nonzero bits ordered from oldest to latest. combos end only by
|
|
2077
|
+
* expiration.
|
|
2078
|
+
*/
|
|
2079
|
+
#combo = [];
|
|
2080
|
+
#contextMenu;
|
|
2081
|
+
#gamepad;
|
|
2082
|
+
/** time since buttons changed. */
|
|
2083
|
+
#heldMillis = 0;
|
|
2084
|
+
#keyboard;
|
|
2085
|
+
#pointer;
|
|
2086
|
+
#pointerState;
|
|
2087
|
+
/** bits last update. may not be equal to `#combo.at(-1)`. */
|
|
2088
|
+
#prevBits = 0;
|
|
2089
|
+
#wheel;
|
|
2090
|
+
#wheelState;
|
|
2091
|
+
constructor(cam, target) {
|
|
2092
|
+
this.#cam = cam;
|
|
2093
|
+
this.#contextMenu = new ContextMenu(target);
|
|
2094
|
+
this.#gamepad = new Gamepad(globalThis);
|
|
2095
|
+
this.#keyboard = new Keyboard(target.ownerDocument);
|
|
2096
|
+
this.#pointer = new Pointer(target);
|
|
2097
|
+
this.#wheel = new Wheel(target);
|
|
2098
|
+
}
|
|
2099
|
+
get anyOn() {
|
|
2100
|
+
return this.#bits !== 0;
|
|
2101
|
+
}
|
|
2102
|
+
/** for debugging. */
|
|
2103
|
+
get combo() {
|
|
2104
|
+
const chords = [];
|
|
2105
|
+
for (const bits of this.#combo) {
|
|
2106
|
+
const chord = [];
|
|
2107
|
+
for (let bit = 1; bit <= bits; bit <<= 1) {
|
|
2108
|
+
if ((bit & bits) === bit && this.#buttonByBit[bit])
|
|
2109
|
+
chord.push(this.#buttonByBit[bit]);
|
|
2110
|
+
}
|
|
2111
|
+
chord.sort();
|
|
2112
|
+
chords.push(chord);
|
|
2113
|
+
}
|
|
2114
|
+
return chords;
|
|
2115
|
+
}
|
|
2116
|
+
/**
|
|
2117
|
+
* enable when game is paused or in photo mode to allow right clicks and long
|
|
2118
|
+
* presses to save canvas.
|
|
2119
|
+
*/
|
|
2120
|
+
get contextMenu() {
|
|
2121
|
+
return this.#contextMenu;
|
|
2122
|
+
}
|
|
2123
|
+
/** doesn't consider handled. gamepads must be polled. */
|
|
2124
|
+
get gamepad() {
|
|
2125
|
+
return this.#gamepad.connected ? {} : void 0;
|
|
2126
|
+
}
|
|
2127
|
+
/** true if bits hasn't changed for a while. */
|
|
2128
|
+
get held() {
|
|
2129
|
+
return !this.handled && this.#heldMillis >= this.minHeldMillis;
|
|
2130
|
+
}
|
|
2131
|
+
isAnyOn(...btns) {
|
|
2132
|
+
return !this.handled && !!(this.#bits & this.#mapBits(btns));
|
|
2133
|
+
}
|
|
2134
|
+
isAnyOnStart(...btns) {
|
|
2135
|
+
return this.started && this.isAnyOn(...btns);
|
|
2136
|
+
}
|
|
2137
|
+
/**
|
|
2138
|
+
* buttons are exact. eg, up won't match up AND down like `isOn('U')` will.
|
|
2139
|
+
* combo is exact too. `['A'], ['A']` will match `['A'], ['A']` but not
|
|
2140
|
+
* `['A'], ['A'], ['A']`.
|
|
2141
|
+
*/
|
|
2142
|
+
isCombo(...combo) {
|
|
2143
|
+
return combo.length === this.#combo.length && this.isComboEndsWith(...combo);
|
|
2144
|
+
}
|
|
2145
|
+
/**
|
|
2146
|
+
* `['A'], ['A']` will match `['A'], ['A']` and `['B'], ['A'], ['A']`. eg,
|
|
2147
|
+
* double-clicks often don't care about any preceding buttons.
|
|
2148
|
+
*/
|
|
2149
|
+
isComboEndsWith(...combo) {
|
|
2150
|
+
for (const [i, btns] of combo.entries()) {
|
|
2151
|
+
const bits = this.#mapBits(btns);
|
|
2152
|
+
if (this.#combo.at(-combo.length + i) !== bits) return false;
|
|
2153
|
+
}
|
|
2154
|
+
return !this.handled && (this.#combo.at(-1) === this.#bits || !this.#bits);
|
|
2155
|
+
}
|
|
2156
|
+
/** like isComboEndsWith() but test if the last button is triggered. */
|
|
2157
|
+
isComboEndsWithStart(...combo) {
|
|
2158
|
+
return this.isOnStart(...combo.at(-1)) && this.isComboEndsWith(...combo);
|
|
2159
|
+
}
|
|
2160
|
+
/** like isCombo() but test if the last button is triggered. */
|
|
2161
|
+
isComboStart(...combo) {
|
|
2162
|
+
return this.isOnStart(...combo.at(-1)) && this.isCombo(...combo);
|
|
2163
|
+
}
|
|
2164
|
+
/*:
|
|
2165
|
+
* true if any button in chord is not on. this is usually what's wanted. eg:
|
|
2166
|
+
* ```ts
|
|
2167
|
+
* if (isOn('A', 'B')) console.log('on')
|
|
2168
|
+
* if (isOff('A', 'B')) console.log('not A+B; A and/or B is off')
|
|
2169
|
+
* ```
|
|
2170
|
+
*/
|
|
2171
|
+
isOff(...btns) {
|
|
2172
|
+
return !this.handled && !this.isOn(...btns);
|
|
2173
|
+
}
|
|
2174
|
+
isOffStart(...btns) {
|
|
2175
|
+
const bits = this.#mapBits(btns);
|
|
2176
|
+
const wasOn = (this.#prevBits & bits) === bits;
|
|
2177
|
+
return wasOn && this.started && this.isOff(...btns);
|
|
2178
|
+
}
|
|
2179
|
+
/**
|
|
2180
|
+
* true if all buttons are on inclusively. eg, `isOn('U')` is true when up is
|
|
2181
|
+
* pressed or when up and down are pressed.
|
|
2182
|
+
*/
|
|
2183
|
+
isOn(...btns) {
|
|
2184
|
+
const bits = this.#mapBits(btns);
|
|
2185
|
+
return !this.handled && (this.#bits & bits) === bits;
|
|
2186
|
+
}
|
|
2187
|
+
isOnStart(...btns) {
|
|
2188
|
+
return this.started && this.isOn(...btns);
|
|
2189
|
+
}
|
|
2190
|
+
get key() {
|
|
2191
|
+
return { invalid: this.#keyboard.invalid };
|
|
2192
|
+
}
|
|
2193
|
+
mapDefault() {
|
|
2194
|
+
const input = this;
|
|
2195
|
+
input.mapKeyboardCode("L", "ArrowLeft");
|
|
2196
|
+
input.mapKeyboardCode("R", "ArrowRight");
|
|
2197
|
+
input.mapKeyboardCode("U", "ArrowUp");
|
|
2198
|
+
input.mapKeyboardCode("D", "ArrowDown");
|
|
2199
|
+
input.mapKeyboardCode("C", "KeyC");
|
|
2200
|
+
input.mapKeyboardCode("A", "KeyX");
|
|
2201
|
+
input.mapKeyboardCode("B", "KeyZ");
|
|
2202
|
+
input.mapKeyboardCode("Menu", "Enter");
|
|
2203
|
+
input.mapKeyboardCode("Back", "Escape");
|
|
2204
|
+
input.mapGamepadAxis("L", "R", 0, 2);
|
|
2205
|
+
input.mapGamepadAxis("U", "D", 1, 3);
|
|
2206
|
+
input.mapGamepadButton("L", 14);
|
|
2207
|
+
input.mapGamepadButton("R", 15);
|
|
2208
|
+
input.mapGamepadButton("U", 12);
|
|
2209
|
+
input.mapGamepadButton("D", 13);
|
|
2210
|
+
input.mapGamepadButton("C", 2);
|
|
2211
|
+
input.mapGamepadButton("B", 0);
|
|
2212
|
+
input.mapGamepadButton("A", 1);
|
|
2213
|
+
input.mapGamepadButton("Menu", 9);
|
|
2214
|
+
input.mapGamepadButton("Back", 8);
|
|
2215
|
+
input.mapPointerClick("Click", 1);
|
|
2216
|
+
input.mapPointerClick("Click2", 2);
|
|
2217
|
+
input.mapPointerClick("ClickMiddle", 4);
|
|
2218
|
+
return input;
|
|
2219
|
+
}
|
|
2220
|
+
// to-do: support analog values.
|
|
2221
|
+
mapGamepadAxis(less, more, ...axes) {
|
|
2222
|
+
for (const axis of axes) {
|
|
2223
|
+
this.#gamepad.bitByAxis[axis] = [
|
|
2224
|
+
this.#mapButton(less),
|
|
2225
|
+
this.#mapButton(more)
|
|
2226
|
+
];
|
|
2227
|
+
}
|
|
2228
|
+
}
|
|
2229
|
+
mapGamepadButton(btn, ...indices) {
|
|
2230
|
+
for (const index of indices)
|
|
2231
|
+
this.#gamepad.bitByButton[index] = this.#mapButton(btn);
|
|
2232
|
+
}
|
|
2233
|
+
/** @arg codes union of KeyboardEvent.code. */
|
|
2234
|
+
mapKeyboardCode(btn, ...codes) {
|
|
2235
|
+
for (const code of codes)
|
|
2236
|
+
this.#keyboard.bitByCode[code] = this.#mapButton(btn);
|
|
2237
|
+
}
|
|
2238
|
+
mapPointerClick(btn, ...clicks) {
|
|
2239
|
+
for (const click of clicks)
|
|
2240
|
+
this.#pointer.bitByButton[click] = this.#mapButton(btn);
|
|
2241
|
+
}
|
|
2242
|
+
get on() {
|
|
2243
|
+
const on = [];
|
|
2244
|
+
for (const btn in this.#bitByButton) if (this.isOn(btn)) on.push(btn);
|
|
2245
|
+
return on.sort();
|
|
2246
|
+
}
|
|
2247
|
+
set onEvent(cb) {
|
|
2248
|
+
this.#gamepad.onEvent = cb;
|
|
2249
|
+
this.#keyboard.onEvent = cb;
|
|
2250
|
+
this.#pointer.onEvent = cb;
|
|
2251
|
+
this.#wheel.onEvent = cb;
|
|
2252
|
+
}
|
|
2253
|
+
/** doesn't consider handled. */
|
|
2254
|
+
get point() {
|
|
2255
|
+
return this.#pointerState;
|
|
2256
|
+
}
|
|
2257
|
+
get pointer() {
|
|
2258
|
+
return this.#pointer;
|
|
2259
|
+
}
|
|
2260
|
+
register(op) {
|
|
2261
|
+
globalThis[`${op}EventListener`]("blur", this.reset);
|
|
2262
|
+
this.#contextMenu.register(op);
|
|
2263
|
+
this.#gamepad.register(op);
|
|
2264
|
+
this.#keyboard.register(op);
|
|
2265
|
+
this.#pointer.register(op);
|
|
2266
|
+
this.#wheel.register(op);
|
|
2267
|
+
return this;
|
|
2268
|
+
}
|
|
2269
|
+
reset = () => {
|
|
2270
|
+
this.#bits = 0;
|
|
2271
|
+
this.#prevBits = 0;
|
|
2272
|
+
this.handled = false;
|
|
2273
|
+
this.#heldMillis = 0;
|
|
2274
|
+
this.#combo.length = 0;
|
|
2275
|
+
this.#gamepad.reset();
|
|
2276
|
+
this.#keyboard.reset();
|
|
2277
|
+
this.#pointer.reset();
|
|
2278
|
+
this.#pointerState = void 0;
|
|
2279
|
+
this.#wheel.reset();
|
|
2280
|
+
this.#wheelState = void 0;
|
|
2281
|
+
};
|
|
2282
|
+
/** true if bits has changed. */
|
|
2283
|
+
get started() {
|
|
2284
|
+
return !this.handled && this.#bits !== this.#prevBits;
|
|
2285
|
+
}
|
|
2286
|
+
/**
|
|
2287
|
+
* call on new frame before altering cam. dispatches always occur before an
|
|
2288
|
+
* update.
|
|
2289
|
+
* @arg millis duration since last update.
|
|
2290
|
+
*/
|
|
2291
|
+
update(millis) {
|
|
2292
|
+
this.handled = false;
|
|
2293
|
+
this.#gamepad.update();
|
|
2294
|
+
this.#pointer.update();
|
|
2295
|
+
this.#prevBits = this.#bits;
|
|
2296
|
+
this.#bits = this.#gamepad.bits | this.#keyboard.bits | (this.#pointer.primary?.bits ?? 0);
|
|
2297
|
+
this.invalid = this.#bits !== this.#prevBits || this.#pointer.invalid || !!this.#wheel.deltaClient;
|
|
2298
|
+
this.gestured ||= !!this.#bits;
|
|
2299
|
+
if (millis > this.comboMaxIntervalMillis && this.#bits !== this.#prevBits || this.#heldMillis + millis > this.comboMaxIntervalMillis && !this.#bits)
|
|
2300
|
+
this.#combo.length = 0;
|
|
2301
|
+
if (this.#bits === this.#prevBits)
|
|
2302
|
+
this.#heldMillis = this.#heldMillis + millis;
|
|
2303
|
+
else this.#heldMillis = millis;
|
|
2304
|
+
if (this.#bits && this.#bits !== this.#prevBits) {
|
|
2305
|
+
if (this.#prevBits) this.#combo.length = 0;
|
|
2306
|
+
this.#combo.push(this.#bits);
|
|
2307
|
+
}
|
|
2308
|
+
if (this.#pointer.primary) {
|
|
2309
|
+
const pinchClient = this.#pointer.pinchClient;
|
|
2310
|
+
const dragOn = this.#pointer.primary.drag && !Object.values(this.#pointer.secondary).length;
|
|
2311
|
+
const secondary = [];
|
|
2312
|
+
for (const pt of Object.values(this.#pointer.secondary)) {
|
|
2313
|
+
secondary.push({
|
|
2314
|
+
type: pt.type,
|
|
2315
|
+
click: pt.clickClient ? {
|
|
2316
|
+
client: pt.clickClient,
|
|
2317
|
+
local: this.#cam.clientToXYLocal(pt.clickClient),
|
|
2318
|
+
...this.#cam.clientToXY(pt.clickClient)
|
|
2319
|
+
} : void 0,
|
|
2320
|
+
...this.#cam.clientToXY(pt.xyClient),
|
|
2321
|
+
client: pt.xyClient,
|
|
2322
|
+
local: this.#cam.clientToXYLocal(pt.xyClient)
|
|
2323
|
+
});
|
|
2324
|
+
}
|
|
2325
|
+
const centerClient = this.#pointer.centerClient;
|
|
2326
|
+
const center = {
|
|
2327
|
+
client: centerClient,
|
|
2328
|
+
local: this.#cam.clientToXYLocal(centerClient),
|
|
2329
|
+
...this.#cam.clientToXY(centerClient)
|
|
2330
|
+
};
|
|
2331
|
+
this.#pointerState = {
|
|
2332
|
+
center,
|
|
2333
|
+
click: this.#pointer.primary.clickClient ? {
|
|
2334
|
+
client: this.#pointer.primary.clickClient,
|
|
2335
|
+
local: this.#cam.clientToXYLocal(
|
|
2336
|
+
this.#pointer.primary.clickClient
|
|
2337
|
+
),
|
|
2338
|
+
...this.#cam.clientToXY(this.#pointer.primary.clickClient)
|
|
2339
|
+
} : void 0,
|
|
2340
|
+
drag: {
|
|
2341
|
+
on: dragOn,
|
|
2342
|
+
start: !this.#pointerState?.drag.on && dragOn,
|
|
2343
|
+
end: !!this.#pointerState?.drag.on && !dragOn
|
|
2344
|
+
},
|
|
2345
|
+
invalid: this.#pointer.invalid,
|
|
2346
|
+
pinch: pinchClient ? { client: pinchClient, xy: this.#cam.clientToXY(pinchClient) } : void 0,
|
|
2347
|
+
secondary,
|
|
2348
|
+
type: this.#pointer.primary.type,
|
|
2349
|
+
...this.#cam.clientToXY(this.#pointer.primary.xyClient),
|
|
2350
|
+
client: this.#pointer.primary.xyClient,
|
|
2351
|
+
local: this.#cam.clientToXYLocal(this.#pointer.primary.xyClient)
|
|
2352
|
+
};
|
|
2353
|
+
} else this.#pointerState = void 0;
|
|
2354
|
+
this.#wheelState = this.#wheel.deltaClient ? {
|
|
2355
|
+
delta: {
|
|
2356
|
+
client: this.#wheel.deltaClient,
|
|
2357
|
+
xy: this.#cam.clientToXY(this.#wheel.deltaClient)
|
|
2358
|
+
}
|
|
2359
|
+
} : void 0;
|
|
2360
|
+
this.#keyboard.postupdate();
|
|
2361
|
+
this.#pointer.postupdate();
|
|
2362
|
+
this.#wheel.postupdate();
|
|
2363
|
+
}
|
|
2364
|
+
[Symbol.dispose]() {
|
|
2365
|
+
this.register("remove");
|
|
2366
|
+
}
|
|
2367
|
+
/** doesn't consider handled. */
|
|
2368
|
+
get wheel() {
|
|
2369
|
+
return this.#wheelState;
|
|
2370
|
+
}
|
|
2371
|
+
/** get bits for buttons. */
|
|
2372
|
+
#mapBits(btns) {
|
|
2373
|
+
let bits = 0;
|
|
2374
|
+
for (const btn of btns) bits |= this.#bitByButton[btn] ?? 0;
|
|
2375
|
+
return bits;
|
|
2376
|
+
}
|
|
2377
|
+
/** assign button to bit. */
|
|
2378
|
+
#mapButton(btn) {
|
|
2379
|
+
const bit = this.#bitByButton[btn] ??= 1 << Object.keys(this.#bitByButton).length;
|
|
2380
|
+
this.#buttonByBit[bit] = btn;
|
|
2381
|
+
return bit;
|
|
2382
|
+
}
|
|
2383
|
+
};
|
|
2384
|
+
|
|
2385
|
+
// src/utils/debug.ts
|
|
2386
|
+
var debug = Debug(
|
|
2387
|
+
globalThis.location?.href
|
|
2388
|
+
);
|
|
2389
|
+
function Debug(url) {
|
|
2390
|
+
if (!url) return;
|
|
2391
|
+
const csv = [...new URL(url).searchParams].find(
|
|
2392
|
+
([k]) => k.toLowerCase() === "debug"
|
|
2393
|
+
)?.[1];
|
|
2394
|
+
if (csv == null) return;
|
|
2395
|
+
const map = Object.fromEntries(
|
|
2396
|
+
csv.split(",").filter(Boolean).map((kv) => kv.split("="))
|
|
2397
|
+
// split each pair.
|
|
2398
|
+
);
|
|
2399
|
+
const target = {};
|
|
2400
|
+
for (const k in map) target[k.toLowerCase()] = map[k] || "true";
|
|
2401
|
+
const voidKeyset = {
|
|
2402
|
+
cam: void 0,
|
|
2403
|
+
input: void 0,
|
|
2404
|
+
mem: void 0,
|
|
2405
|
+
render: void 0
|
|
2406
|
+
};
|
|
2407
|
+
return new Proxy(target, {
|
|
2408
|
+
get(target2, k) {
|
|
2409
|
+
if (typeof k !== "string") return target2[k];
|
|
2410
|
+
k = k.toLowerCase();
|
|
2411
|
+
return !csv || "all" in map || k in voidKeyset && "void" in map ? target2[k] || "true" : target2[k];
|
|
2412
|
+
}
|
|
2413
|
+
});
|
|
2414
|
+
}
|
|
2415
|
+
|
|
2416
|
+
// src/mem/pool.ts
|
|
2417
|
+
var Pool = class {
|
|
2418
|
+
/** the next free block is always at size. */
|
|
2419
|
+
#blocks;
|
|
2420
|
+
#opts;
|
|
2421
|
+
#size = 0;
|
|
2422
|
+
#u8;
|
|
2423
|
+
#view;
|
|
2424
|
+
constructor(opts) {
|
|
2425
|
+
if (opts.allocBytes <= 0) throw Error("byte allocation must be > 0");
|
|
2426
|
+
if (opts.pageBlocks <= 0) throw Error("page blocks must be > 0");
|
|
2427
|
+
this.#opts = { ...opts, minPages: opts.minPages ?? 1 };
|
|
2428
|
+
const initSize = this.#opts.minPages * opts.pageBlocks;
|
|
2429
|
+
this.#blocks = new Array(initSize);
|
|
2430
|
+
this.#u8 = new Uint8Array();
|
|
2431
|
+
this.#resize(initSize, "Init");
|
|
2432
|
+
}
|
|
2433
|
+
alloc() {
|
|
2434
|
+
if (this.#size >= this.#currentCapacity)
|
|
2435
|
+
this.#resize(this.#currentCapacity + this.#opts.pageBlocks, "Call");
|
|
2436
|
+
const block = this.#blocks[this.#size];
|
|
2437
|
+
block.i = this.#size * this.#opts.allocBytes;
|
|
2438
|
+
this.#size++;
|
|
2439
|
+
return block;
|
|
2440
|
+
}
|
|
2441
|
+
clear() {
|
|
2442
|
+
this.#size = 0;
|
|
2443
|
+
const minCapacity = this.#opts.minPages * this.#opts.pageBlocks;
|
|
2444
|
+
if (this.#currentCapacity > minCapacity) this.#resize(minCapacity, "Call");
|
|
2445
|
+
}
|
|
2446
|
+
free(...blocks) {
|
|
2447
|
+
for (const block of blocks) this.#freeBlock(block);
|
|
2448
|
+
}
|
|
2449
|
+
get size() {
|
|
2450
|
+
return this.#size;
|
|
2451
|
+
}
|
|
2452
|
+
get view() {
|
|
2453
|
+
return this.#view;
|
|
2454
|
+
}
|
|
2455
|
+
toDebugString() {
|
|
2456
|
+
let str = "";
|
|
2457
|
+
for (let i = 0; i < this.#u8.buffer.byteLength; i++) {
|
|
2458
|
+
if (i && !(i % this.#opts.allocBytes)) str += " ";
|
|
2459
|
+
str += this.#u8[i].toString(16).padStart(2, "0");
|
|
2460
|
+
}
|
|
2461
|
+
return str;
|
|
2462
|
+
}
|
|
2463
|
+
get #currentCapacity() {
|
|
2464
|
+
return this.#u8.buffer.byteLength / this.#opts.allocBytes;
|
|
2465
|
+
}
|
|
2466
|
+
#freeBlock(block) {
|
|
2467
|
+
if (!this.#size) throw Error("pool underflow");
|
|
2468
|
+
this.#size--;
|
|
2469
|
+
const start = this.#size * this.#opts.allocBytes;
|
|
2470
|
+
this.#u8.copyWithin(block.i, start, start + this.#opts.allocBytes);
|
|
2471
|
+
this.#blocks[this.#size].i = block.i;
|
|
2472
|
+
[this.#blocks[block.i], this.#blocks[this.#size]] = [
|
|
2473
|
+
this.#blocks[this.#size],
|
|
2474
|
+
this.#blocks[block.i]
|
|
2475
|
+
];
|
|
2476
|
+
const free = Math.floor(
|
|
2477
|
+
(this.#currentCapacity - this.#size) / this.#opts.pageBlocks
|
|
2478
|
+
);
|
|
2479
|
+
if (free && this.#currentCapacity / this.#opts.pageBlocks - free >= this.#opts.minPages)
|
|
2480
|
+
this.#resize(this.#currentCapacity - free * this.#opts.pageBlocks, "Call");
|
|
2481
|
+
}
|
|
2482
|
+
#resize(capacity, origin) {
|
|
2483
|
+
if (origin === "Call" && debug?.mem)
|
|
2484
|
+
console.debug(
|
|
2485
|
+
`[mem] ${capacity < this.#currentCapacity ? "shrinking" : "growing"} pool to ${capacity}`
|
|
2486
|
+
);
|
|
2487
|
+
this.#blocks.length = capacity;
|
|
2488
|
+
for (let i = this.#currentCapacity; i < capacity; i++)
|
|
2489
|
+
this.#blocks[i] = this.#opts.alloc(this);
|
|
2490
|
+
const buffer = new ArrayBuffer(capacity * this.#opts.allocBytes);
|
|
2491
|
+
const u8 = new Uint8Array(buffer);
|
|
2492
|
+
u8.set(this.#u8.subarray(0, capacity * this.#opts.allocBytes));
|
|
2493
|
+
this.#u8 = u8;
|
|
2494
|
+
this.#view = new DataView(buffer);
|
|
2495
|
+
}
|
|
2496
|
+
};
|
|
2497
|
+
|
|
2498
|
+
// src/utils/color-util.ts
|
|
2499
|
+
function rgbaHex(rgba) {
|
|
2500
|
+
return `#${rgba.toString(16).padStart(8, "0")}`;
|
|
2501
|
+
}
|
|
2502
|
+
|
|
2503
|
+
// src/utils/dom-util.ts
|
|
2504
|
+
function initMetaViewport() {
|
|
2505
|
+
if (document.querySelector('meta[name="viewport"]')) return;
|
|
2506
|
+
const meta = document.createElement("meta");
|
|
2507
|
+
meta.name = "viewport";
|
|
2508
|
+
meta.content = "width=device-width, maximum-scale=1, minimum-scale=1, user-scalable=no";
|
|
2509
|
+
document.head.appendChild(meta);
|
|
2510
|
+
}
|
|
2511
|
+
function initBody(canvas, rgba) {
|
|
2512
|
+
if (canvas.parentNode !== document.body) return;
|
|
2513
|
+
document.body.style.margin = "0";
|
|
2514
|
+
document.body.style.width = "100dvw";
|
|
2515
|
+
document.body.style.height = "100dvh";
|
|
2516
|
+
document.body.style.overflow = "hidden";
|
|
2517
|
+
document.body.style.background = rgbaHex(rgba);
|
|
2518
|
+
}
|
|
2519
|
+
|
|
2520
|
+
// src/utils/canvas-util.ts
|
|
2521
|
+
function initCanvas(canvas, mode) {
|
|
2522
|
+
canvas ??= document.createElement("canvas");
|
|
2523
|
+
canvas.width = 0;
|
|
2524
|
+
canvas.style.cursor = "none";
|
|
2525
|
+
canvas.style.display = "block";
|
|
2526
|
+
canvas.style.outline = "none";
|
|
2527
|
+
canvas.style.cursor = "none";
|
|
2528
|
+
if (mode === "Int") canvas.style.imageRendering = "pixelated";
|
|
2529
|
+
canvas.style.touchAction = "none";
|
|
2530
|
+
canvas.tabIndex = 0;
|
|
2531
|
+
canvas.focus();
|
|
2532
|
+
if (!canvas.parentNode) document.body.append(canvas);
|
|
2533
|
+
return canvas;
|
|
2534
|
+
}
|
|
2535
|
+
|
|
2536
|
+
// src/utils/fetch-util.ts
|
|
2537
|
+
async function loadImage(img) {
|
|
2538
|
+
const promise = new Promise((fulfil, reject) => {
|
|
2539
|
+
img.onload = () => fulfil(img);
|
|
2540
|
+
img.onerror = () => reject(Error(`image load error for ${img.src}`));
|
|
2541
|
+
});
|
|
2542
|
+
return img.complete ? img : await promise;
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2545
|
+
// src/graphics/gl.ts
|
|
2546
|
+
function Shader(gl, vertGLSL, fragGLSL, textures) {
|
|
2547
|
+
const program = loadProgram(gl, vertGLSL, fragGLSL);
|
|
2548
|
+
gl.useProgram(program);
|
|
2549
|
+
return {
|
|
2550
|
+
buffer: gl.createBuffer(),
|
|
2551
|
+
program,
|
|
2552
|
+
textures,
|
|
2553
|
+
uniform: GLUniformMap(gl, program),
|
|
2554
|
+
vao: gl.createVertexArray()
|
|
2555
|
+
};
|
|
2556
|
+
}
|
|
2557
|
+
function GLUniformMap(gl, pgm) {
|
|
2558
|
+
const len = pgm ? gl.getProgramParameter(pgm, gl.ACTIVE_UNIFORMS) : 0;
|
|
2559
|
+
const map = debug?.render ? new Proxy(
|
|
2560
|
+
{},
|
|
2561
|
+
{
|
|
2562
|
+
get(target, k) {
|
|
2563
|
+
if (target[k] == null) throw Error(`no shader uniform "${k}"`);
|
|
2564
|
+
return target[k];
|
|
2565
|
+
}
|
|
2566
|
+
}
|
|
2567
|
+
) : {};
|
|
2568
|
+
for (let i = 0; i < len; ++i) {
|
|
2569
|
+
const uniform = gl.getActiveUniform(pgm, i);
|
|
2570
|
+
if (!uniform) throw Error(`no shader uniform at index ${i}`);
|
|
2571
|
+
const location = gl.getUniformLocation(pgm, uniform.name);
|
|
2572
|
+
if (!location) throw Error(`no shader uniform "${uniform.name}"`);
|
|
2573
|
+
const name = uniform.name.replace("[0]", "");
|
|
2574
|
+
map[name] = location;
|
|
2575
|
+
}
|
|
2576
|
+
return map;
|
|
2577
|
+
}
|
|
2578
|
+
function loadProgram(gl, vertGLSL, fragGLSL) {
|
|
2579
|
+
const pgm = gl.createProgram();
|
|
2580
|
+
if (!pgm) return null;
|
|
2581
|
+
const vert = compileShader(gl, "VERTEX_SHADER", vertGLSL);
|
|
2582
|
+
const frag = compileShader(gl, "FRAGMENT_SHADER", fragGLSL);
|
|
2583
|
+
if (!vert || !frag) return null;
|
|
2584
|
+
gl.attachShader(pgm, vert);
|
|
2585
|
+
gl.attachShader(pgm, frag);
|
|
2586
|
+
gl.linkProgram(pgm);
|
|
2587
|
+
if (debug?.render && !gl.getProgramParameter(pgm, gl.LINK_STATUS)) {
|
|
2588
|
+
const log = gl.getProgramInfoLog(pgm)?.slice(0, -1);
|
|
2589
|
+
throw Error(`shader link failure; ${log}`);
|
|
2590
|
+
}
|
|
2591
|
+
gl.detachShader(pgm, frag);
|
|
2592
|
+
gl.detachShader(pgm, vert);
|
|
2593
|
+
gl.deleteShader(frag);
|
|
2594
|
+
gl.deleteShader(vert);
|
|
2595
|
+
return pgm;
|
|
2596
|
+
}
|
|
2597
|
+
function compileShader(gl, type, glsl) {
|
|
2598
|
+
const shader = gl.createShader(gl[type]);
|
|
2599
|
+
if (!shader) return shader;
|
|
2600
|
+
gl.shaderSource(shader, glsl.trim());
|
|
2601
|
+
gl.compileShader(shader);
|
|
2602
|
+
if (debug?.render && !gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
2603
|
+
const log = gl.getShaderInfoLog(shader)?.slice(0, -1);
|
|
2604
|
+
throw Error(`shader compile failure; ${log}`);
|
|
2605
|
+
}
|
|
2606
|
+
return shader;
|
|
2607
|
+
}
|
|
2608
|
+
|
|
2609
|
+
// src/graphics/sprite-frag.glsl.ts
|
|
2610
|
+
var spriteFragGLSL = `#version 300 es
|
|
2611
|
+
#pragma debug(${debug?.render ? "on" : "off"})
|
|
2612
|
+
#pragma optimize(${debug?.render ? "off" : "on"})
|
|
2613
|
+
|
|
2614
|
+
precision highp int;
|
|
2615
|
+
precision highp float;
|
|
2616
|
+
precision highp usampler2D;
|
|
2617
|
+
|
|
2618
|
+
uniform sampler2D uTex;
|
|
2619
|
+
uniform uvec2 uTexWH;
|
|
2620
|
+
|
|
2621
|
+
flat in uint vStretch;
|
|
2622
|
+
flat in ivec4 vTexXYWH;
|
|
2623
|
+
flat in int vZ;
|
|
2624
|
+
in vec2 vDstWH;
|
|
2625
|
+
flat in ivec2 vDstWHFixed;
|
|
2626
|
+
|
|
2627
|
+
out vec4 oRGBA;
|
|
2628
|
+
|
|
2629
|
+
void main() {
|
|
2630
|
+
if (vZ == ${Layer.Hidden} || vDstWHFixed.x == 0 || vDstWHFixed.y == 0)
|
|
2631
|
+
discard;
|
|
2632
|
+
|
|
2633
|
+
vec2 px = vec2(vTexXYWH.xy) + (
|
|
2634
|
+
vStretch == 1u ? (vDstWH * vec2(vTexXYWH.zw) / vec2(vDstWHFixed))
|
|
2635
|
+
: mod(vDstWH, vec2(vTexXYWH.zw))
|
|
2636
|
+
);
|
|
2637
|
+
|
|
2638
|
+
oRGBA = texture(uTex, px / vec2(uTexWH));
|
|
2639
|
+
if(oRGBA.a < .001) discard;
|
|
2640
|
+
}
|
|
2641
|
+
`;
|
|
2642
|
+
|
|
2643
|
+
// src/graphics/sprite-vert.glsl.ts
|
|
2644
|
+
var spriteVertGLSL = `#version 300 es
|
|
2645
|
+
#pragma debug(${debug?.render ? "on" : "off"})
|
|
2646
|
+
#pragma optimize(${debug?.render ? "off" : "on"})
|
|
2647
|
+
|
|
2648
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/WebGL_best_practices#essl300_minimum_requirements_webgl_2
|
|
2649
|
+
precision highp int;
|
|
2650
|
+
precision highp float;
|
|
2651
|
+
precision highp usampler2D;
|
|
2652
|
+
|
|
2653
|
+
uniform ivec4 uCam;
|
|
2654
|
+
uniform usampler2D uCels;
|
|
2655
|
+
uniform float uAge;
|
|
2656
|
+
|
|
2657
|
+
layout (location=0) in ivec2 iUV;
|
|
2658
|
+
layout (location=1) in uint iy8_x24;
|
|
2659
|
+
layout (location=2) in uint iw8_sxyz_llll_y16;
|
|
2660
|
+
layout (location=3) in uint ii11_c5_h12_w4;
|
|
2661
|
+
|
|
2662
|
+
const int maxY = 0x20000;
|
|
2663
|
+
const int layers = 16;
|
|
2664
|
+
const int maxDepth = maxY * layers;
|
|
2665
|
+
|
|
2666
|
+
flat out uint vStretch;
|
|
2667
|
+
flat out ivec4 vTexXYWH;
|
|
2668
|
+
flat out int vZ;
|
|
2669
|
+
out vec2 vDstWH;
|
|
2670
|
+
flat out ivec2 vDstWHFixed;
|
|
2671
|
+
|
|
2672
|
+
void main() {
|
|
2673
|
+
int x = (int((iy8_x24 & 0xffffffu) << 8) >> 8) / 64;
|
|
2674
|
+
int y = (int(iy8_x24 >> 24) | (int(iw8_sxyz_llll_y16 & 0xffffu) << 16 >> 8)) / 64;
|
|
2675
|
+
int z = int((iw8_sxyz_llll_y16 >> 16) & 0xfu);
|
|
2676
|
+
bool zend = bool(iw8_sxyz_llll_y16 & 0x100000u);
|
|
2677
|
+
bool flipY = bool(iw8_sxyz_llll_y16 & 0x200000u);
|
|
2678
|
+
bool flipX = bool(iw8_sxyz_llll_y16 & 0x400000u);
|
|
2679
|
+
bool stretch = bool(iw8_sxyz_llll_y16 & 0x800000u);
|
|
2680
|
+
int id = int((ii11_c5_h12_w4 >> 17) & 0x7ff0u); // ignore cel.
|
|
2681
|
+
int cel = int((ii11_c5_h12_w4 >> 16) & 0xfu); // ignore the MSB.
|
|
2682
|
+
int w = int(((ii11_c5_h12_w4 & 0xfu) << 8) | (iw8_sxyz_llll_y16 >> 24));
|
|
2683
|
+
int h = int((ii11_c5_h12_w4 >> 4) & 0xfffu);
|
|
2684
|
+
|
|
2685
|
+
// https://www.patternsgameprog.com/opengl-2d-facade-25-get-the-z-of-a-pixel
|
|
2686
|
+
float depth = float((z + 1) * maxY - (y + (zend ? 0 : h))) / float(maxDepth);
|
|
2687
|
+
|
|
2688
|
+
ivec2 targetWH = iUV * ivec2(w, h);
|
|
2689
|
+
|
|
2690
|
+
vec2 end = vec2(x + targetWH.x, y + targetWH.y);
|
|
2691
|
+
// UI layers are always given in screen coordinates.
|
|
2692
|
+
// to-do: how to handle non-int mode?
|
|
2693
|
+
vec2 camXY = z < ${Layer.A} ? vec2(0, 0) : vec2(uCam.xy);
|
|
2694
|
+
vec2 clip = ((-2. * camXY + 2. * end) / vec2(uCam.zw) - 1.) * vec2(1, -1);
|
|
2695
|
+
gl_Position = vec4(clip, depth, 1);
|
|
2696
|
+
|
|
2697
|
+
int frame = (((int(uAge / ${celMillis}) & 0x1f) - cel) + ${animCels}) & 0xf;
|
|
2698
|
+
uvec4 texXYWH = texelFetch(uCels, ivec2(0, id + frame), 0);
|
|
2699
|
+
vTexXYWH = ivec4(texXYWH);
|
|
2700
|
+
vZ = z;
|
|
2701
|
+
|
|
2702
|
+
vDstWH = vec2(targetWH * ivec2(flipX ? -1 : 1, flipY ? -1 : 1));
|
|
2703
|
+
vDstWHFixed = ivec2(w, h) * ivec2(flipX ? -1 : 1, flipY ? -1 : 1);
|
|
2704
|
+
|
|
2705
|
+
vStretch = stretch ? 1u : 0u;
|
|
2706
|
+
}
|
|
2707
|
+
`;
|
|
2708
|
+
|
|
2709
|
+
// src/graphics/renderer.ts
|
|
2710
|
+
var uv = new Int8Array([1, 1, 0, 1, 1, 0, 0, 0]);
|
|
2711
|
+
var Renderer = class {
|
|
2712
|
+
/** when off, ents should avoid requesting renders. */
|
|
2713
|
+
always = false;
|
|
2714
|
+
invalid = false;
|
|
2715
|
+
loseContext;
|
|
2716
|
+
#canvas;
|
|
2717
|
+
#clearRGBA = 0;
|
|
2718
|
+
#ctx;
|
|
2719
|
+
#preloadAtlas;
|
|
2720
|
+
#preloadAtlasImage;
|
|
2721
|
+
constructor(preloadAtlas, canvas) {
|
|
2722
|
+
this.#preloadAtlas = preloadAtlas;
|
|
2723
|
+
this.#canvas = canvas;
|
|
2724
|
+
this.#ctx = this.#Context();
|
|
2725
|
+
}
|
|
2726
|
+
clear(rgba) {
|
|
2727
|
+
if (!this.#ctx) return;
|
|
2728
|
+
const { gl } = this.#ctx;
|
|
2729
|
+
if (this.#clearRGBA !== rgba) {
|
|
2730
|
+
this.#clearRGBA = rgba;
|
|
2731
|
+
gl.clearColor(
|
|
2732
|
+
(rgba >>> 24 & 255) / 255,
|
|
2733
|
+
(rgba >>> 16 & 255) / 255,
|
|
2734
|
+
(rgba >>> 8 & 255) / 255,
|
|
2735
|
+
(rgba >>> 0 & 255) / 255
|
|
2736
|
+
);
|
|
2737
|
+
}
|
|
2738
|
+
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
2739
|
+
}
|
|
2740
|
+
draw(pool) {
|
|
2741
|
+
if (!this.#preloadAtlasImage || !this.#ctx) return;
|
|
2742
|
+
const { gl, spriteShader } = this.#ctx;
|
|
2743
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, spriteShader.buffer);
|
|
2744
|
+
gl.bufferData(
|
|
2745
|
+
gl.ARRAY_BUFFER,
|
|
2746
|
+
pool.view,
|
|
2747
|
+
gl.DYNAMIC_DRAW,
|
|
2748
|
+
0,
|
|
2749
|
+
pool.size * drawableBytes
|
|
2750
|
+
);
|
|
2751
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
2752
|
+
gl.bindVertexArray(spriteShader.vao);
|
|
2753
|
+
gl.drawArraysInstanced(
|
|
2754
|
+
gl.TRIANGLE_STRIP,
|
|
2755
|
+
0,
|
|
2756
|
+
uv.length / 2,
|
|
2757
|
+
// d
|
|
2758
|
+
pool.size
|
|
2759
|
+
);
|
|
2760
|
+
gl.bindVertexArray(null);
|
|
2761
|
+
this.invalid = false;
|
|
2762
|
+
}
|
|
2763
|
+
load(preloadAtlas) {
|
|
2764
|
+
this.#preloadAtlasImage = preloadAtlas;
|
|
2765
|
+
this.#ctx = this.#Context();
|
|
2766
|
+
}
|
|
2767
|
+
predraw(cam, framer) {
|
|
2768
|
+
if (!this.#ctx) return;
|
|
2769
|
+
const { gl, spriteShader, viewport } = this.#ctx;
|
|
2770
|
+
if (!whEq(viewport, cam)) {
|
|
2771
|
+
gl.viewport(0, 0, cam.w, cam.h);
|
|
2772
|
+
viewport.w = cam.w;
|
|
2773
|
+
viewport.h = cam.h;
|
|
2774
|
+
}
|
|
2775
|
+
gl.useProgram(spriteShader.program);
|
|
2776
|
+
gl.uniform4i(spriteShader.uniform.uCam, cam.x, cam.y, cam.w, cam.h);
|
|
2777
|
+
gl.uniform1f(spriteShader.uniform.uAge, framer.age);
|
|
2778
|
+
for (const [i, tex] of spriteShader.textures.entries()) {
|
|
2779
|
+
gl.activeTexture(gl.TEXTURE0 + i);
|
|
2780
|
+
gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
2781
|
+
}
|
|
2782
|
+
}
|
|
2783
|
+
register(op) {
|
|
2784
|
+
this.#canvas[`${op}EventListener`]("webglcontextlost", this.#onContextLost);
|
|
2785
|
+
this.#canvas[`${op}EventListener`](
|
|
2786
|
+
"webglcontextrestored",
|
|
2787
|
+
this.#onContextRestored
|
|
2788
|
+
);
|
|
2789
|
+
return this;
|
|
2790
|
+
}
|
|
2791
|
+
setDepth(enable) {
|
|
2792
|
+
if (!this.#ctx) return;
|
|
2793
|
+
if (enable) this.#ctx.gl.enable(this.#ctx.gl.DEPTH_TEST);
|
|
2794
|
+
else this.#ctx.gl.disable(this.#ctx.gl.DEPTH_TEST);
|
|
2795
|
+
}
|
|
2796
|
+
[Symbol.dispose]() {
|
|
2797
|
+
this.register("remove");
|
|
2798
|
+
}
|
|
2799
|
+
#Context() {
|
|
2800
|
+
const gl = this.#ctx?.gl ?? GL2(this.#canvas);
|
|
2801
|
+
if (!gl) return;
|
|
2802
|
+
const shader = Shader(gl, spriteVertGLSL, spriteFragGLSL, [
|
|
2803
|
+
gl.createTexture(),
|
|
2804
|
+
gl.createTexture()
|
|
2805
|
+
]);
|
|
2806
|
+
gl.enable(gl.BLEND);
|
|
2807
|
+
gl.blendFuncSeparate(
|
|
2808
|
+
gl.SRC_ALPHA,
|
|
2809
|
+
gl.ONE_MINUS_SRC_ALPHA,
|
|
2810
|
+
gl.ONE,
|
|
2811
|
+
gl.ONE_MINUS_SRC_ALPHA
|
|
2812
|
+
);
|
|
2813
|
+
gl.depthRange(0, 1);
|
|
2814
|
+
gl.clearDepth(1);
|
|
2815
|
+
gl.depthFunc(gl.LESS);
|
|
2816
|
+
gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, false);
|
|
2817
|
+
gl.bindVertexArray(shader.vao);
|
|
2818
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
|
|
2819
|
+
gl.bufferData(gl.ARRAY_BUFFER, uv, gl.STATIC_DRAW);
|
|
2820
|
+
gl.enableVertexAttribArray(0);
|
|
2821
|
+
gl.vertexAttribIPointer(0, 2, gl.BYTE, 0, 0);
|
|
2822
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
2823
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, shader.buffer);
|
|
2824
|
+
gl.enableVertexAttribArray(1);
|
|
2825
|
+
gl.vertexAttribIPointer(1, 1, gl.UNSIGNED_INT, drawableBytes, 0);
|
|
2826
|
+
gl.vertexAttribDivisor(1, 1);
|
|
2827
|
+
gl.enableVertexAttribArray(2);
|
|
2828
|
+
gl.vertexAttribIPointer(2, 1, gl.UNSIGNED_INT, drawableBytes, 4);
|
|
2829
|
+
gl.vertexAttribDivisor(2, 1);
|
|
2830
|
+
gl.enableVertexAttribArray(3);
|
|
2831
|
+
gl.vertexAttribIPointer(3, 1, gl.UNSIGNED_INT, drawableBytes, 8);
|
|
2832
|
+
gl.vertexAttribDivisor(3, 1);
|
|
2833
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
2834
|
+
gl.bindTexture(gl.TEXTURE_2D, shader.textures[0]);
|
|
2835
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
2836
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
2837
|
+
if (this.#preloadAtlasImage)
|
|
2838
|
+
gl.texImage2D(
|
|
2839
|
+
gl.TEXTURE_2D,
|
|
2840
|
+
0,
|
|
2841
|
+
gl.RGBA,
|
|
2842
|
+
gl.RGBA,
|
|
2843
|
+
gl.UNSIGNED_BYTE,
|
|
2844
|
+
this.#preloadAtlasImage
|
|
2845
|
+
);
|
|
2846
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
2847
|
+
gl.bindTexture(gl.TEXTURE_2D, shader.textures[1]);
|
|
2848
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
2849
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
2850
|
+
gl.texImage2D(
|
|
2851
|
+
gl.TEXTURE_2D,
|
|
2852
|
+
0,
|
|
2853
|
+
gl.RGBA16UI,
|
|
2854
|
+
// source XYWH cannot be > 65535.
|
|
2855
|
+
1,
|
|
2856
|
+
this.#preloadAtlas.celXYWH.length / 4,
|
|
2857
|
+
// 4 u16s per row
|
|
2858
|
+
0,
|
|
2859
|
+
gl.RGBA_INTEGER,
|
|
2860
|
+
gl.UNSIGNED_SHORT,
|
|
2861
|
+
new Uint16Array(this.#preloadAtlas.celXYWH)
|
|
2862
|
+
);
|
|
2863
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
2864
|
+
gl.bindVertexArray(null);
|
|
2865
|
+
gl.uniform1i(shader.uniform.uTex, 0);
|
|
2866
|
+
gl.uniform1i(shader.uniform.uCels, 1);
|
|
2867
|
+
if (this.#preloadAtlasImage)
|
|
2868
|
+
gl.uniform2ui(
|
|
2869
|
+
shader.uniform.uTexWH,
|
|
2870
|
+
this.#preloadAtlasImage.naturalWidth,
|
|
2871
|
+
this.#preloadAtlasImage.naturalHeight
|
|
2872
|
+
);
|
|
2873
|
+
this.invalid = true;
|
|
2874
|
+
this.loseContext = gl.getExtension("WEBGL_lose_context") ?? void 0;
|
|
2875
|
+
return this.#ctx = { gl, spriteShader: shader, viewport: { w: 0, h: 0 } };
|
|
2876
|
+
}
|
|
2877
|
+
#onContextLost = (ev) => {
|
|
2878
|
+
ev.preventDefault();
|
|
2879
|
+
console.debug("[render] WebGL context lost");
|
|
2880
|
+
this.#ctx = void 0;
|
|
2881
|
+
};
|
|
2882
|
+
#onContextRestored = () => {
|
|
2883
|
+
console.debug("[render] WebGL context restored");
|
|
2884
|
+
this.#ctx = this.#Context();
|
|
2885
|
+
};
|
|
2886
|
+
};
|
|
2887
|
+
function GL2(canvas) {
|
|
2888
|
+
const gl = canvas.getContext("webgl2", {
|
|
2889
|
+
// to-do: expose.
|
|
2890
|
+
antialias: false,
|
|
2891
|
+
powerPreference: "low-power",
|
|
2892
|
+
// avoid flicker caused by clearing the drawing buffer. see
|
|
2893
|
+
// https://developer.chrome.com/blog/desynchronized/.
|
|
2894
|
+
preserveDrawingBuffer: true,
|
|
2895
|
+
...!debug?.render && { desynchronized: true }
|
|
2896
|
+
});
|
|
2897
|
+
if (!gl) {
|
|
2898
|
+
console.debug("[render] no GL context");
|
|
2899
|
+
return;
|
|
2900
|
+
}
|
|
2901
|
+
if (debug?.render && !gl.getContextAttributes()?.desynchronized)
|
|
2902
|
+
console.debug("[render] no WebGL DOM desynchronization");
|
|
2903
|
+
return gl;
|
|
2904
|
+
}
|
|
2905
|
+
|
|
2906
|
+
// src/looper.ts
|
|
2907
|
+
var Looper = class {
|
|
2908
|
+
/** duration of frames observed. */
|
|
2909
|
+
age = 0;
|
|
2910
|
+
onFrame;
|
|
2911
|
+
#req = 0;
|
|
2912
|
+
#registered = false;
|
|
2913
|
+
register(op) {
|
|
2914
|
+
const fn = `${op}EventListener`;
|
|
2915
|
+
document[fn]("visibilitychange", this.#onVisibility);
|
|
2916
|
+
if (op === "remove") this.#cancel();
|
|
2917
|
+
this.#registered = op === "add";
|
|
2918
|
+
return this;
|
|
2919
|
+
}
|
|
2920
|
+
requestFrame() {
|
|
2921
|
+
if (this.#req || document.hidden || !this.#registered) return;
|
|
2922
|
+
this.#req = requestAnimationFrame(this.#onFrame);
|
|
2923
|
+
}
|
|
2924
|
+
[Symbol.dispose]() {
|
|
2925
|
+
this.register("remove");
|
|
2926
|
+
}
|
|
2927
|
+
#cancel() {
|
|
2928
|
+
if (this.#req) cancelAnimationFrame(this.#req);
|
|
2929
|
+
this.#req = 0;
|
|
2930
|
+
}
|
|
2931
|
+
#onFrame = (now) => {
|
|
2932
|
+
this.age = now;
|
|
2933
|
+
this.#req = 0;
|
|
2934
|
+
this.onFrame?.(now - (this.age || now));
|
|
2935
|
+
};
|
|
2936
|
+
#onVisibility = (ev) => {
|
|
2937
|
+
if (!ev.isTrusted) return;
|
|
2938
|
+
if (document.hidden) this.#cancel();
|
|
2939
|
+
else this.requestFrame();
|
|
2940
|
+
};
|
|
2941
|
+
};
|
|
2942
|
+
|
|
2943
|
+
// src/pixel-ratio-observer.ts
|
|
2944
|
+
var PixelRatioObserver = class {
|
|
2945
|
+
onChange = () => {
|
|
2946
|
+
};
|
|
2947
|
+
#mediaQuery;
|
|
2948
|
+
register(op) {
|
|
2949
|
+
this.#mediaQuery?.removeEventListener("change", this.#onChange);
|
|
2950
|
+
if (op === "add") {
|
|
2951
|
+
this.#mediaQuery = matchMedia(`not (resolution: ${devicePixelRatio}dppx)`);
|
|
2952
|
+
this.#mediaQuery.addEventListener("change", this.#onChange);
|
|
2953
|
+
} else this.#mediaQuery = void 0;
|
|
2954
|
+
return this;
|
|
2955
|
+
}
|
|
2956
|
+
[Symbol.dispose]() {
|
|
2957
|
+
this.register("remove");
|
|
2958
|
+
}
|
|
2959
|
+
#onChange = () => {
|
|
2960
|
+
this.register("add");
|
|
2961
|
+
this.onChange();
|
|
2962
|
+
};
|
|
2963
|
+
};
|
|
2964
|
+
|
|
2965
|
+
// src/void.ts
|
|
2966
|
+
var Void = class {
|
|
2967
|
+
cam = new Cam();
|
|
2968
|
+
canvas;
|
|
2969
|
+
framer = new Looper();
|
|
2970
|
+
input;
|
|
2971
|
+
preload;
|
|
2972
|
+
renderer;
|
|
2973
|
+
sprites;
|
|
2974
|
+
zoo = new Zoo();
|
|
2975
|
+
#pixelRatioObserver = new PixelRatioObserver();
|
|
2976
|
+
#preloadAtlasImage;
|
|
2977
|
+
#resizeObserver = new ResizeObserver(() => this.onResize());
|
|
2978
|
+
constructor(opts) {
|
|
2979
|
+
initMetaViewport();
|
|
2980
|
+
this.canvas = initCanvas(opts.canvas, opts.mode ?? "Int");
|
|
2981
|
+
initBody(this.canvas, opts.backgroundRGBA ?? 255);
|
|
2982
|
+
if (opts.minWH) this.cam.minWH = opts.minWH;
|
|
2983
|
+
this.cam.mode = opts.mode ?? "Int";
|
|
2984
|
+
this.cam.update(this.canvas);
|
|
2985
|
+
this.input = new Input(this.cam, this.canvas);
|
|
2986
|
+
if (opts.input !== "Custom") this.input.mapDefault();
|
|
2987
|
+
this.input.onEvent = () => this.onEvent();
|
|
2988
|
+
this.#pixelRatioObserver.onChange = () => this.onResize();
|
|
2989
|
+
if (opts.preloadAtlas) this.#preloadAtlasImage = opts.preloadAtlas.image;
|
|
2990
|
+
this.preload = opts.preloadAtlas ? parseAtlas(opts.preloadAtlas.json) : { anim: {}, celXYWH: [], tags: [] };
|
|
2991
|
+
this.renderer = new Renderer(this.preload ?? {}, this.canvas);
|
|
2992
|
+
this.sprites = new Pool({
|
|
2993
|
+
alloc: (pool) => this.onAllocSprite(pool),
|
|
2994
|
+
allocBytes: drawableBytes,
|
|
2995
|
+
minPages: opts.sprites?.minPages ?? 3,
|
|
2996
|
+
pageBlocks: opts.sprites?.pageBlocks ?? 1e3
|
|
2997
|
+
});
|
|
2998
|
+
this.framer.onFrame = (millis) => this.onFrame(millis);
|
|
2999
|
+
}
|
|
3000
|
+
onAllocSprite(pool) {
|
|
3001
|
+
return new Sprite(pool, 0, this.preload, this.framer);
|
|
3002
|
+
}
|
|
3003
|
+
onEvent() {
|
|
3004
|
+
this.framer.requestFrame();
|
|
3005
|
+
}
|
|
3006
|
+
/** update input, update canvas, update cam, update world, then render. */
|
|
3007
|
+
onFrame(millis) {
|
|
3008
|
+
if (document.hidden) return;
|
|
3009
|
+
this.input.update(millis);
|
|
3010
|
+
this.onLoop(millis);
|
|
3011
|
+
this.cam.postupdate();
|
|
3012
|
+
}
|
|
3013
|
+
// biome-ignore lint/correctness/noUnusedFunctionParameters:;
|
|
3014
|
+
onLoop(millis) {
|
|
3015
|
+
}
|
|
3016
|
+
onResize() {
|
|
3017
|
+
this.framer.requestFrame();
|
|
3018
|
+
}
|
|
3019
|
+
async register(op) {
|
|
3020
|
+
this.input.register(op);
|
|
3021
|
+
this.renderer.register(op);
|
|
3022
|
+
this.framer.register(op);
|
|
3023
|
+
if (!this.canvas.parentElement) throw Error("no canvas parent");
|
|
3024
|
+
if (op === "add") this.#resizeObserver.observe(this.canvas.parentElement);
|
|
3025
|
+
else this.#resizeObserver.unobserve(this.canvas.parentElement);
|
|
3026
|
+
this.#pixelRatioObserver.register(op);
|
|
3027
|
+
this.framer.requestFrame();
|
|
3028
|
+
if (this.#preloadAtlasImage) await loadImage(this.#preloadAtlasImage);
|
|
3029
|
+
this.renderer.load(this.#preloadAtlasImage);
|
|
3030
|
+
}
|
|
3031
|
+
requestFrame() {
|
|
3032
|
+
if (this.renderer.always || this.input.anyOn || this.input.gamepad)
|
|
3033
|
+
this.framer.requestFrame();
|
|
3034
|
+
}
|
|
3035
|
+
async [Symbol.asyncDispose]() {
|
|
3036
|
+
await this.register("remove");
|
|
3037
|
+
}
|
|
3038
|
+
};
|
|
3039
|
+
|
|
3040
|
+
// src/index.ts
|
|
3041
|
+
var version = voidVersion ? `${voidVersion.version}+${voidVersion.published}.${voidVersion.hash}` : "?";
|
|
3042
|
+
|
|
3043
|
+
// src/demo/assets/preload-atlas.json
|
|
3044
|
+
var preload_atlas_default = {
|
|
3045
|
+
anim: {
|
|
3046
|
+
"background--OrangeCheckerboard": { cels: 1, h: 2, id: 0, w: 2 },
|
|
3047
|
+
"background--GreyCheckerboard": { cels: 1, h: 2, id: 1, w: 2 },
|
|
3048
|
+
"background--Kiwi": { cels: 1, h: 2, id: 2, w: 2 },
|
|
3049
|
+
"background--Strawberry": { cels: 1, h: 2, id: 3, w: 2 },
|
|
3050
|
+
"background--Grape": { cels: 1, h: 2, id: 4, w: 2 },
|
|
3051
|
+
"background--Blueberry": { cels: 1, h: 2, id: 5, w: 2 },
|
|
3052
|
+
"background--Bubblegum": { cels: 1, h: 2, id: 6, w: 2 },
|
|
3053
|
+
"background--Transparent": { cels: 1, h: 2, id: 7, w: 2 },
|
|
3054
|
+
"background--Black": { cels: 1, h: 2, id: 8, w: 2 },
|
|
3055
|
+
"backpacker--WalkRight": {
|
|
3056
|
+
cels: 16,
|
|
3057
|
+
h: 13,
|
|
3058
|
+
hitbox: { x: 2, y: 0, w: 4, h: 4 },
|
|
3059
|
+
id: 9,
|
|
3060
|
+
w: 8
|
|
3061
|
+
},
|
|
3062
|
+
"backpacker--WalkDown": {
|
|
3063
|
+
cels: 16,
|
|
3064
|
+
h: 13,
|
|
3065
|
+
hitbox: { x: 2, y: 0, w: 4, h: 4 },
|
|
3066
|
+
id: 10,
|
|
3067
|
+
w: 8
|
|
3068
|
+
},
|
|
3069
|
+
"backpacker--WalkUp": {
|
|
3070
|
+
cels: 16,
|
|
3071
|
+
h: 13,
|
|
3072
|
+
hitbox: { x: 2, y: 0, w: 4, h: 4 },
|
|
3073
|
+
id: 11,
|
|
3074
|
+
w: 8
|
|
3075
|
+
},
|
|
3076
|
+
"cursor--Pointer": {
|
|
3077
|
+
cels: 1,
|
|
3078
|
+
h: 14,
|
|
3079
|
+
hitbox: { x: 0, y: 0, w: 2, h: 2 },
|
|
3080
|
+
hurtbox: { x: 0, y: 0, w: 2, h: 2 },
|
|
3081
|
+
id: 12,
|
|
3082
|
+
w: 8
|
|
3083
|
+
},
|
|
3084
|
+
"mem-prop-5x6--00": { cels: 1, h: 6, id: 13, w: 5 },
|
|
3085
|
+
"mem-prop-5x6--01": { cels: 1, h: 6, id: 14, w: 5 },
|
|
3086
|
+
"mem-prop-5x6--02": { cels: 1, h: 6, id: 15, w: 5 },
|
|
3087
|
+
"mem-prop-5x6--03": { cels: 1, h: 6, id: 16, w: 5 },
|
|
3088
|
+
"mem-prop-5x6--04": { cels: 1, h: 6, id: 17, w: 5 },
|
|
3089
|
+
"mem-prop-5x6--05": { cels: 1, h: 6, id: 18, w: 5 },
|
|
3090
|
+
"mem-prop-5x6--06": { cels: 1, h: 6, id: 19, w: 5 },
|
|
3091
|
+
"mem-prop-5x6--07": { cels: 1, h: 6, id: 20, w: 5 },
|
|
3092
|
+
"mem-prop-5x6--08": { cels: 1, h: 6, id: 21, w: 5 },
|
|
3093
|
+
"mem-prop-5x6--09": { cels: 1, h: 6, id: 22, w: 5 },
|
|
3094
|
+
"mem-prop-5x6--0a": { cels: 1, h: 6, id: 23, w: 5 },
|
|
3095
|
+
"mem-prop-5x6--0b": { cels: 1, h: 6, id: 24, w: 5 },
|
|
3096
|
+
"mem-prop-5x6--0c": { cels: 1, h: 6, id: 25, w: 5 },
|
|
3097
|
+
"mem-prop-5x6--0d": { cels: 1, h: 6, id: 26, w: 5 },
|
|
3098
|
+
"mem-prop-5x6--0e": { cels: 1, h: 6, id: 27, w: 5 },
|
|
3099
|
+
"mem-prop-5x6--0f": { cels: 1, h: 6, id: 28, w: 5 },
|
|
3100
|
+
"mem-prop-5x6--10": { cels: 1, h: 6, id: 29, w: 5 },
|
|
3101
|
+
"mem-prop-5x6--11": { cels: 1, h: 6, id: 30, w: 5 },
|
|
3102
|
+
"mem-prop-5x6--12": { cels: 1, h: 6, id: 31, w: 5 },
|
|
3103
|
+
"mem-prop-5x6--13": { cels: 1, h: 6, id: 32, w: 5 },
|
|
3104
|
+
"mem-prop-5x6--14": { cels: 1, h: 6, id: 33, w: 5 },
|
|
3105
|
+
"mem-prop-5x6--15": { cels: 1, h: 6, id: 34, w: 5 },
|
|
3106
|
+
"mem-prop-5x6--16": { cels: 1, h: 6, id: 35, w: 5 },
|
|
3107
|
+
"mem-prop-5x6--17": { cels: 1, h: 6, id: 36, w: 5 },
|
|
3108
|
+
"mem-prop-5x6--18": { cels: 1, h: 6, id: 37, w: 5 },
|
|
3109
|
+
"mem-prop-5x6--19": { cels: 1, h: 6, id: 38, w: 5 },
|
|
3110
|
+
"mem-prop-5x6--1a": { cels: 1, h: 6, id: 39, w: 5 },
|
|
3111
|
+
"mem-prop-5x6--1b": { cels: 1, h: 6, id: 40, w: 5 },
|
|
3112
|
+
"mem-prop-5x6--1c": { cels: 1, h: 6, id: 41, w: 5 },
|
|
3113
|
+
"mem-prop-5x6--1d": { cels: 1, h: 6, id: 42, w: 5 },
|
|
3114
|
+
"mem-prop-5x6--1e": { cels: 1, h: 6, id: 43, w: 5 },
|
|
3115
|
+
"mem-prop-5x6--1f": { cels: 1, h: 6, id: 44, w: 5 },
|
|
3116
|
+
"mem-prop-5x6--20": { cels: 1, h: 6, id: 45, w: 5 },
|
|
3117
|
+
"mem-prop-5x6--21": { cels: 1, h: 6, id: 46, w: 5 },
|
|
3118
|
+
"mem-prop-5x6--22": { cels: 1, h: 6, id: 47, w: 5 },
|
|
3119
|
+
"mem-prop-5x6--23": { cels: 1, h: 6, id: 48, w: 5 },
|
|
3120
|
+
"mem-prop-5x6--24": { cels: 1, h: 6, id: 49, w: 5 },
|
|
3121
|
+
"mem-prop-5x6--25": { cels: 1, h: 6, id: 50, w: 5 },
|
|
3122
|
+
"mem-prop-5x6--26": { cels: 1, h: 6, id: 51, w: 5 },
|
|
3123
|
+
"mem-prop-5x6--27": { cels: 1, h: 6, id: 52, w: 5 },
|
|
3124
|
+
"mem-prop-5x6--28": { cels: 1, h: 6, id: 53, w: 5 },
|
|
3125
|
+
"mem-prop-5x6--29": { cels: 1, h: 6, id: 54, w: 5 },
|
|
3126
|
+
"mem-prop-5x6--2a": { cels: 1, h: 6, id: 55, w: 5 },
|
|
3127
|
+
"mem-prop-5x6--2b": { cels: 1, h: 6, id: 56, w: 5 },
|
|
3128
|
+
"mem-prop-5x6--2c": { cels: 1, h: 6, id: 57, w: 5 },
|
|
3129
|
+
"mem-prop-5x6--2d": { cels: 1, h: 6, id: 58, w: 5 },
|
|
3130
|
+
"mem-prop-5x6--2e": { cels: 1, h: 6, id: 59, w: 5 },
|
|
3131
|
+
"mem-prop-5x6--2f": { cels: 1, h: 6, id: 60, w: 5 },
|
|
3132
|
+
"mem-prop-5x6--30": { cels: 1, h: 6, id: 61, w: 5 },
|
|
3133
|
+
"mem-prop-5x6--31": { cels: 1, h: 6, id: 62, w: 5 },
|
|
3134
|
+
"mem-prop-5x6--32": { cels: 1, h: 6, id: 63, w: 5 },
|
|
3135
|
+
"mem-prop-5x6--33": { cels: 1, h: 6, id: 64, w: 5 },
|
|
3136
|
+
"mem-prop-5x6--34": { cels: 1, h: 6, id: 65, w: 5 },
|
|
3137
|
+
"mem-prop-5x6--35": { cels: 1, h: 6, id: 66, w: 5 },
|
|
3138
|
+
"mem-prop-5x6--36": { cels: 1, h: 6, id: 67, w: 5 },
|
|
3139
|
+
"mem-prop-5x6--37": { cels: 1, h: 6, id: 68, w: 5 },
|
|
3140
|
+
"mem-prop-5x6--38": { cels: 1, h: 6, id: 69, w: 5 },
|
|
3141
|
+
"mem-prop-5x6--39": { cels: 1, h: 6, id: 70, w: 5 },
|
|
3142
|
+
"mem-prop-5x6--3a": { cels: 1, h: 6, id: 71, w: 5 },
|
|
3143
|
+
"mem-prop-5x6--3b": { cels: 1, h: 6, id: 72, w: 5 },
|
|
3144
|
+
"mem-prop-5x6--3c": { cels: 1, h: 6, id: 73, w: 5 },
|
|
3145
|
+
"mem-prop-5x6--3d": { cels: 1, h: 6, id: 74, w: 5 },
|
|
3146
|
+
"mem-prop-5x6--3e": { cels: 1, h: 6, id: 75, w: 5 },
|
|
3147
|
+
"mem-prop-5x6--3f": { cels: 1, h: 6, id: 76, w: 5 },
|
|
3148
|
+
"mem-prop-5x6--40": { cels: 1, h: 6, id: 77, w: 5 },
|
|
3149
|
+
"mem-prop-5x6--41": { cels: 1, h: 6, id: 78, w: 5 },
|
|
3150
|
+
"mem-prop-5x6--42": { cels: 1, h: 6, id: 79, w: 5 },
|
|
3151
|
+
"mem-prop-5x6--43": { cels: 1, h: 6, id: 80, w: 5 },
|
|
3152
|
+
"mem-prop-5x6--44": { cels: 1, h: 6, id: 81, w: 5 },
|
|
3153
|
+
"mem-prop-5x6--45": { cels: 1, h: 6, id: 82, w: 5 },
|
|
3154
|
+
"mem-prop-5x6--46": { cels: 1, h: 6, id: 83, w: 5 },
|
|
3155
|
+
"mem-prop-5x6--47": { cels: 1, h: 6, id: 84, w: 5 },
|
|
3156
|
+
"mem-prop-5x6--48": { cels: 1, h: 6, id: 85, w: 5 },
|
|
3157
|
+
"mem-prop-5x6--49": { cels: 1, h: 6, id: 86, w: 5 },
|
|
3158
|
+
"mem-prop-5x6--4a": { cels: 1, h: 6, id: 87, w: 5 },
|
|
3159
|
+
"mem-prop-5x6--4b": { cels: 1, h: 6, id: 88, w: 5 },
|
|
3160
|
+
"mem-prop-5x6--4c": { cels: 1, h: 6, id: 89, w: 5 },
|
|
3161
|
+
"mem-prop-5x6--4d": { cels: 1, h: 6, id: 90, w: 5 },
|
|
3162
|
+
"mem-prop-5x6--4e": { cels: 1, h: 6, id: 91, w: 5 },
|
|
3163
|
+
"mem-prop-5x6--4f": { cels: 1, h: 6, id: 92, w: 5 },
|
|
3164
|
+
"mem-prop-5x6--50": { cels: 1, h: 6, id: 93, w: 5 },
|
|
3165
|
+
"mem-prop-5x6--51": { cels: 1, h: 6, id: 94, w: 5 },
|
|
3166
|
+
"mem-prop-5x6--52": { cels: 1, h: 6, id: 95, w: 5 },
|
|
3167
|
+
"mem-prop-5x6--53": { cels: 1, h: 6, id: 96, w: 5 },
|
|
3168
|
+
"mem-prop-5x6--54": { cels: 1, h: 6, id: 97, w: 5 },
|
|
3169
|
+
"mem-prop-5x6--55": { cels: 1, h: 6, id: 98, w: 5 },
|
|
3170
|
+
"mem-prop-5x6--56": { cels: 1, h: 6, id: 99, w: 5 },
|
|
3171
|
+
"mem-prop-5x6--57": { cels: 1, h: 6, id: 100, w: 5 },
|
|
3172
|
+
"mem-prop-5x6--58": { cels: 1, h: 6, id: 101, w: 5 },
|
|
3173
|
+
"mem-prop-5x6--59": { cels: 1, h: 6, id: 102, w: 5 },
|
|
3174
|
+
"mem-prop-5x6--5a": { cels: 1, h: 6, id: 103, w: 5 },
|
|
3175
|
+
"mem-prop-5x6--5b": { cels: 1, h: 6, id: 104, w: 5 },
|
|
3176
|
+
"mem-prop-5x6--5c": { cels: 1, h: 6, id: 105, w: 5 },
|
|
3177
|
+
"mem-prop-5x6--5d": { cels: 1, h: 6, id: 106, w: 5 },
|
|
3178
|
+
"mem-prop-5x6--5e": { cels: 1, h: 6, id: 107, w: 5 },
|
|
3179
|
+
"mem-prop-5x6--5f": { cels: 1, h: 6, id: 108, w: 5 },
|
|
3180
|
+
"mem-prop-5x6--60": { cels: 1, h: 6, id: 109, w: 5 },
|
|
3181
|
+
"mem-prop-5x6--61": { cels: 1, h: 6, id: 110, w: 5 },
|
|
3182
|
+
"mem-prop-5x6--62": { cels: 1, h: 6, id: 111, w: 5 },
|
|
3183
|
+
"mem-prop-5x6--63": { cels: 1, h: 6, id: 112, w: 5 },
|
|
3184
|
+
"mem-prop-5x6--64": { cels: 1, h: 6, id: 113, w: 5 },
|
|
3185
|
+
"mem-prop-5x6--65": { cels: 1, h: 6, id: 114, w: 5 },
|
|
3186
|
+
"mem-prop-5x6--66": { cels: 1, h: 6, id: 115, w: 5 },
|
|
3187
|
+
"mem-prop-5x6--67": { cels: 1, h: 6, id: 116, w: 5 },
|
|
3188
|
+
"mem-prop-5x6--68": { cels: 1, h: 6, id: 117, w: 5 },
|
|
3189
|
+
"mem-prop-5x6--69": { cels: 1, h: 6, id: 118, w: 5 },
|
|
3190
|
+
"mem-prop-5x6--6a": { cels: 1, h: 6, id: 119, w: 5 },
|
|
3191
|
+
"mem-prop-5x6--6b": { cels: 1, h: 6, id: 120, w: 5 },
|
|
3192
|
+
"mem-prop-5x6--6c": { cels: 1, h: 6, id: 121, w: 5 },
|
|
3193
|
+
"mem-prop-5x6--6d": { cels: 1, h: 6, id: 122, w: 5 },
|
|
3194
|
+
"mem-prop-5x6--6e": { cels: 1, h: 6, id: 123, w: 5 },
|
|
3195
|
+
"mem-prop-5x6--6f": { cels: 1, h: 6, id: 124, w: 5 },
|
|
3196
|
+
"mem-prop-5x6--70": { cels: 1, h: 6, id: 125, w: 5 },
|
|
3197
|
+
"mem-prop-5x6--71": { cels: 1, h: 6, id: 126, w: 5 },
|
|
3198
|
+
"mem-prop-5x6--72": { cels: 1, h: 6, id: 127, w: 5 },
|
|
3199
|
+
"mem-prop-5x6--73": { cels: 1, h: 6, id: 128, w: 5 },
|
|
3200
|
+
"mem-prop-5x6--74": { cels: 1, h: 6, id: 129, w: 5 },
|
|
3201
|
+
"mem-prop-5x6--75": { cels: 1, h: 6, id: 130, w: 5 },
|
|
3202
|
+
"mem-prop-5x6--76": { cels: 1, h: 6, id: 131, w: 5 },
|
|
3203
|
+
"mem-prop-5x6--77": { cels: 1, h: 6, id: 132, w: 5 },
|
|
3204
|
+
"mem-prop-5x6--78": { cels: 1, h: 6, id: 133, w: 5 },
|
|
3205
|
+
"mem-prop-5x6--79": { cels: 1, h: 6, id: 134, w: 5 },
|
|
3206
|
+
"mem-prop-5x6--7a": { cels: 1, h: 6, id: 135, w: 5 },
|
|
3207
|
+
"mem-prop-5x6--7b": { cels: 1, h: 6, id: 136, w: 5 },
|
|
3208
|
+
"mem-prop-5x6--7c": { cels: 1, h: 6, id: 137, w: 5 },
|
|
3209
|
+
"mem-prop-5x6--7d": { cels: 1, h: 6, id: 138, w: 5 },
|
|
3210
|
+
"mem-prop-5x6--7e": { cels: 1, h: 6, id: 139, w: 5 },
|
|
3211
|
+
"mem-prop-5x6--7f": { cels: 1, h: 6, id: 140, w: 5 },
|
|
3212
|
+
"oidoid--Default": { cels: 1, h: 16, id: 141, w: 16 }
|
|
3213
|
+
},
|
|
3214
|
+
celXY: [
|
|
3215
|
+
22,
|
|
3216
|
+
37,
|
|
3217
|
+
21,
|
|
3218
|
+
27,
|
|
3219
|
+
21,
|
|
3220
|
+
29,
|
|
3221
|
+
21,
|
|
3222
|
+
31,
|
|
3223
|
+
20,
|
|
3224
|
+
33,
|
|
3225
|
+
22,
|
|
3226
|
+
33,
|
|
3227
|
+
20,
|
|
3228
|
+
35,
|
|
3229
|
+
22,
|
|
3230
|
+
35,
|
|
3231
|
+
20,
|
|
3232
|
+
37,
|
|
3233
|
+
24,
|
|
3234
|
+
26,
|
|
3235
|
+
24,
|
|
3236
|
+
26,
|
|
3237
|
+
8,
|
|
3238
|
+
16,
|
|
3239
|
+
8,
|
|
3240
|
+
16,
|
|
3241
|
+
0,
|
|
3242
|
+
16,
|
|
3243
|
+
0,
|
|
3244
|
+
16,
|
|
3245
|
+
16,
|
|
3246
|
+
14,
|
|
3247
|
+
16,
|
|
3248
|
+
14,
|
|
3249
|
+
72,
|
|
3250
|
+
13,
|
|
3251
|
+
72,
|
|
3252
|
+
13,
|
|
3253
|
+
32,
|
|
3254
|
+
26,
|
|
3255
|
+
32,
|
|
3256
|
+
26,
|
|
3257
|
+
0,
|
|
3258
|
+
16,
|
|
3259
|
+
0,
|
|
3260
|
+
16,
|
|
3261
|
+
64,
|
|
3262
|
+
13,
|
|
3263
|
+
64,
|
|
3264
|
+
13,
|
|
3265
|
+
56,
|
|
3266
|
+
13,
|
|
3267
|
+
56,
|
|
3268
|
+
13,
|
|
3269
|
+
48,
|
|
3270
|
+
13,
|
|
3271
|
+
48,
|
|
3272
|
+
13,
|
|
3273
|
+
40,
|
|
3274
|
+
13,
|
|
3275
|
+
40,
|
|
3276
|
+
13,
|
|
3277
|
+
32,
|
|
3278
|
+
13,
|
|
3279
|
+
32,
|
|
3280
|
+
13,
|
|
3281
|
+
56,
|
|
3282
|
+
13,
|
|
3283
|
+
56,
|
|
3284
|
+
13,
|
|
3285
|
+
24,
|
|
3286
|
+
13,
|
|
3287
|
+
24,
|
|
3288
|
+
13,
|
|
3289
|
+
72,
|
|
3290
|
+
0,
|
|
3291
|
+
72,
|
|
3292
|
+
0,
|
|
3293
|
+
64,
|
|
3294
|
+
0,
|
|
3295
|
+
64,
|
|
3296
|
+
0,
|
|
3297
|
+
24,
|
|
3298
|
+
0,
|
|
3299
|
+
24,
|
|
3300
|
+
0,
|
|
3301
|
+
56,
|
|
3302
|
+
0,
|
|
3303
|
+
56,
|
|
3304
|
+
0,
|
|
3305
|
+
48,
|
|
3306
|
+
0,
|
|
3307
|
+
48,
|
|
3308
|
+
0,
|
|
3309
|
+
48,
|
|
3310
|
+
0,
|
|
3311
|
+
48,
|
|
3312
|
+
0,
|
|
3313
|
+
24,
|
|
3314
|
+
0,
|
|
3315
|
+
24,
|
|
3316
|
+
0,
|
|
3317
|
+
40,
|
|
3318
|
+
0,
|
|
3319
|
+
40,
|
|
3320
|
+
0,
|
|
3321
|
+
32,
|
|
3322
|
+
0,
|
|
3323
|
+
32,
|
|
3324
|
+
0,
|
|
3325
|
+
32,
|
|
3326
|
+
0,
|
|
3327
|
+
32,
|
|
3328
|
+
0,
|
|
3329
|
+
16,
|
|
3330
|
+
0,
|
|
3331
|
+
45,
|
|
3332
|
+
56,
|
|
3333
|
+
45,
|
|
3334
|
+
56,
|
|
3335
|
+
45,
|
|
3336
|
+
56,
|
|
3337
|
+
45,
|
|
3338
|
+
56,
|
|
3339
|
+
45,
|
|
3340
|
+
56,
|
|
3341
|
+
45,
|
|
3342
|
+
56,
|
|
3343
|
+
45,
|
|
3344
|
+
56,
|
|
3345
|
+
45,
|
|
3346
|
+
56,
|
|
3347
|
+
45,
|
|
3348
|
+
56,
|
|
3349
|
+
45,
|
|
3350
|
+
56,
|
|
3351
|
+
45,
|
|
3352
|
+
56,
|
|
3353
|
+
45,
|
|
3354
|
+
56,
|
|
3355
|
+
45,
|
|
3356
|
+
56,
|
|
3357
|
+
45,
|
|
3358
|
+
56,
|
|
3359
|
+
45,
|
|
3360
|
+
56,
|
|
3361
|
+
45,
|
|
3362
|
+
56,
|
|
3363
|
+
45,
|
|
3364
|
+
56,
|
|
3365
|
+
45,
|
|
3366
|
+
56,
|
|
3367
|
+
45,
|
|
3368
|
+
56,
|
|
3369
|
+
45,
|
|
3370
|
+
56,
|
|
3371
|
+
45,
|
|
3372
|
+
56,
|
|
3373
|
+
45,
|
|
3374
|
+
56,
|
|
3375
|
+
45,
|
|
3376
|
+
56,
|
|
3377
|
+
45,
|
|
3378
|
+
56,
|
|
3379
|
+
45,
|
|
3380
|
+
56,
|
|
3381
|
+
45,
|
|
3382
|
+
56,
|
|
3383
|
+
45,
|
|
3384
|
+
56,
|
|
3385
|
+
45,
|
|
3386
|
+
56,
|
|
3387
|
+
45,
|
|
3388
|
+
56,
|
|
3389
|
+
45,
|
|
3390
|
+
56,
|
|
3391
|
+
45,
|
|
3392
|
+
56,
|
|
3393
|
+
45,
|
|
3394
|
+
56,
|
|
3395
|
+
45,
|
|
3396
|
+
56,
|
|
3397
|
+
40,
|
|
3398
|
+
56,
|
|
3399
|
+
10,
|
|
3400
|
+
53,
|
|
3401
|
+
5,
|
|
3402
|
+
53,
|
|
3403
|
+
0,
|
|
3404
|
+
53,
|
|
3405
|
+
35,
|
|
3406
|
+
51,
|
|
3407
|
+
30,
|
|
3408
|
+
51,
|
|
3409
|
+
25,
|
|
3410
|
+
51,
|
|
3411
|
+
20,
|
|
3412
|
+
51,
|
|
3413
|
+
15,
|
|
3414
|
+
51,
|
|
3415
|
+
35,
|
|
3416
|
+
45,
|
|
3417
|
+
70,
|
|
3418
|
+
50,
|
|
3419
|
+
65,
|
|
3420
|
+
50,
|
|
3421
|
+
60,
|
|
3422
|
+
50,
|
|
3423
|
+
55,
|
|
3424
|
+
50,
|
|
3425
|
+
50,
|
|
3426
|
+
50,
|
|
3427
|
+
45,
|
|
3428
|
+
50,
|
|
3429
|
+
40,
|
|
3430
|
+
50,
|
|
3431
|
+
10,
|
|
3432
|
+
47,
|
|
3433
|
+
5,
|
|
3434
|
+
47,
|
|
3435
|
+
0,
|
|
3436
|
+
47,
|
|
3437
|
+
70,
|
|
3438
|
+
62,
|
|
3439
|
+
50,
|
|
3440
|
+
56,
|
|
3441
|
+
65,
|
|
3442
|
+
62,
|
|
3443
|
+
60,
|
|
3444
|
+
62,
|
|
3445
|
+
55,
|
|
3446
|
+
62,
|
|
3447
|
+
50,
|
|
3448
|
+
62,
|
|
3449
|
+
45,
|
|
3450
|
+
62,
|
|
3451
|
+
40,
|
|
3452
|
+
62,
|
|
3453
|
+
10,
|
|
3454
|
+
59,
|
|
3455
|
+
5,
|
|
3456
|
+
59,
|
|
3457
|
+
0,
|
|
3458
|
+
59,
|
|
3459
|
+
35,
|
|
3460
|
+
57,
|
|
3461
|
+
70,
|
|
3462
|
+
32,
|
|
3463
|
+
30,
|
|
3464
|
+
57,
|
|
3465
|
+
25,
|
|
3466
|
+
57,
|
|
3467
|
+
20,
|
|
3468
|
+
57,
|
|
3469
|
+
15,
|
|
3470
|
+
57,
|
|
3471
|
+
75,
|
|
3472
|
+
56,
|
|
3473
|
+
70,
|
|
3474
|
+
56,
|
|
3475
|
+
65,
|
|
3476
|
+
56,
|
|
3477
|
+
60,
|
|
3478
|
+
56,
|
|
3479
|
+
75,
|
|
3480
|
+
50,
|
|
3481
|
+
55,
|
|
3482
|
+
56,
|
|
3483
|
+
10,
|
|
3484
|
+
35,
|
|
3485
|
+
75,
|
|
3486
|
+
32,
|
|
3487
|
+
15,
|
|
3488
|
+
33,
|
|
3489
|
+
0,
|
|
3490
|
+
35,
|
|
3491
|
+
5,
|
|
3492
|
+
35,
|
|
3493
|
+
40,
|
|
3494
|
+
38,
|
|
3495
|
+
45,
|
|
3496
|
+
38,
|
|
3497
|
+
65,
|
|
3498
|
+
32,
|
|
3499
|
+
60,
|
|
3500
|
+
32,
|
|
3501
|
+
55,
|
|
3502
|
+
32,
|
|
3503
|
+
50,
|
|
3504
|
+
32,
|
|
3505
|
+
45,
|
|
3506
|
+
32,
|
|
3507
|
+
40,
|
|
3508
|
+
26,
|
|
3509
|
+
50,
|
|
3510
|
+
26,
|
|
3511
|
+
55,
|
|
3512
|
+
26,
|
|
3513
|
+
60,
|
|
3514
|
+
26,
|
|
3515
|
+
65,
|
|
3516
|
+
26,
|
|
3517
|
+
70,
|
|
3518
|
+
26,
|
|
3519
|
+
75,
|
|
3520
|
+
26,
|
|
3521
|
+
16,
|
|
3522
|
+
27,
|
|
3523
|
+
0,
|
|
3524
|
+
29,
|
|
3525
|
+
5,
|
|
3526
|
+
29,
|
|
3527
|
+
10,
|
|
3528
|
+
29,
|
|
3529
|
+
40,
|
|
3530
|
+
32,
|
|
3531
|
+
45,
|
|
3532
|
+
26,
|
|
3533
|
+
10,
|
|
3534
|
+
41,
|
|
3535
|
+
30,
|
|
3536
|
+
45,
|
|
3537
|
+
25,
|
|
3538
|
+
45,
|
|
3539
|
+
20,
|
|
3540
|
+
45,
|
|
3541
|
+
15,
|
|
3542
|
+
45,
|
|
3543
|
+
75,
|
|
3544
|
+
44,
|
|
3545
|
+
70,
|
|
3546
|
+
44,
|
|
3547
|
+
65,
|
|
3548
|
+
44,
|
|
3549
|
+
60,
|
|
3550
|
+
44,
|
|
3551
|
+
55,
|
|
3552
|
+
44,
|
|
3553
|
+
50,
|
|
3554
|
+
44,
|
|
3555
|
+
45,
|
|
3556
|
+
44,
|
|
3557
|
+
40,
|
|
3558
|
+
44,
|
|
3559
|
+
50,
|
|
3560
|
+
38,
|
|
3561
|
+
5,
|
|
3562
|
+
41,
|
|
3563
|
+
0,
|
|
3564
|
+
41,
|
|
3565
|
+
35,
|
|
3566
|
+
39,
|
|
3567
|
+
30,
|
|
3568
|
+
39,
|
|
3569
|
+
25,
|
|
3570
|
+
39,
|
|
3571
|
+
20,
|
|
3572
|
+
39,
|
|
3573
|
+
15,
|
|
3574
|
+
39,
|
|
3575
|
+
75,
|
|
3576
|
+
38,
|
|
3577
|
+
70,
|
|
3578
|
+
38,
|
|
3579
|
+
65,
|
|
3580
|
+
38,
|
|
3581
|
+
60,
|
|
3582
|
+
38,
|
|
3583
|
+
55,
|
|
3584
|
+
38,
|
|
3585
|
+
45,
|
|
3586
|
+
56,
|
|
3587
|
+
0,
|
|
3588
|
+
0
|
|
3589
|
+
]
|
|
3590
|
+
};
|
|
3591
|
+
|
|
3592
|
+
// src/demo/ents/clock-ent.ts
|
|
3593
|
+
var ClockEnt = class {
|
|
3594
|
+
#time = new TextEnt();
|
|
3595
|
+
constructor() {
|
|
3596
|
+
this.#time.scale = 3;
|
|
3597
|
+
this.#time.z = Layer.A;
|
|
3598
|
+
}
|
|
3599
|
+
free(v2) {
|
|
3600
|
+
this.#time.free(v2);
|
|
3601
|
+
}
|
|
3602
|
+
update(v2) {
|
|
3603
|
+
const now = /* @__PURE__ */ new Date();
|
|
3604
|
+
this.#time.text = timeString(now);
|
|
3605
|
+
if (this.#time.layout(v2) || v2.cam.invalid)
|
|
3606
|
+
this.#time.xy = v2.cam.follow(
|
|
3607
|
+
{ w: this.#time.wh.w, h: this.#time.wh.h - this.#time.scaledLeading },
|
|
3608
|
+
this.#time.z,
|
|
3609
|
+
"N",
|
|
3610
|
+
{ margin: { h: 8 } }
|
|
3611
|
+
);
|
|
3612
|
+
return this.#time.update(v2);
|
|
3613
|
+
}
|
|
3614
|
+
};
|
|
3615
|
+
function timeString(time) {
|
|
3616
|
+
const hh = `${time.getHours() % 12 || 12}`.padStart(2, " ");
|
|
3617
|
+
const mm = `${time.getMinutes()}`.padStart(2, "0");
|
|
3618
|
+
const ss = `${time.getSeconds()}`.padStart(2, "0");
|
|
3619
|
+
return `${hh}:${mm}:${ss}`;
|
|
3620
|
+
}
|
|
3621
|
+
|
|
3622
|
+
// src/demo/ents/render-toggle-ent.ts
|
|
3623
|
+
var RenderToggleEnt = class {
|
|
3624
|
+
#toggle;
|
|
3625
|
+
constructor(v2) {
|
|
3626
|
+
this.#toggle = new ButtonEnt(v2, {
|
|
3627
|
+
button: {
|
|
3628
|
+
w: { tag: "background--Strawberry" },
|
|
3629
|
+
nw: { tag: "background--Transparent" },
|
|
3630
|
+
n: { tag: "background--Bubblegum" },
|
|
3631
|
+
e: { tag: "background--Blueberry" },
|
|
3632
|
+
s: { tag: "background--Kiwi" },
|
|
3633
|
+
origin: { tag: "background--Grape" },
|
|
3634
|
+
border: { n: 1 },
|
|
3635
|
+
margin: { w: 2, h: 2 }
|
|
3636
|
+
},
|
|
3637
|
+
selected: { tag: "background--OrangeCheckerboard" },
|
|
3638
|
+
toggle: true,
|
|
3639
|
+
text: { text: "render", scale: 2 },
|
|
3640
|
+
w: 64,
|
|
3641
|
+
h: 22,
|
|
3642
|
+
x: 50,
|
|
3643
|
+
y: 25,
|
|
3644
|
+
pressed: { tag: "background--Bubblegum" }
|
|
3645
|
+
});
|
|
3646
|
+
}
|
|
3647
|
+
get on() {
|
|
3648
|
+
return this.#toggle.on;
|
|
3649
|
+
}
|
|
3650
|
+
free(v2) {
|
|
3651
|
+
this.#toggle.free(v2);
|
|
3652
|
+
}
|
|
3653
|
+
/** always updates but never invalidates. */
|
|
3654
|
+
update(v2) {
|
|
3655
|
+
return this.#toggle.update(v2);
|
|
3656
|
+
}
|
|
3657
|
+
};
|
|
3658
|
+
|
|
3659
|
+
// src/demo/ents/work-counter-ent.ts
|
|
3660
|
+
var WorkCounterEnt = class {
|
|
3661
|
+
#renders = 0;
|
|
3662
|
+
#text = new TextEnt();
|
|
3663
|
+
#updates = 0;
|
|
3664
|
+
constructor() {
|
|
3665
|
+
this.#text.z = Layer.A;
|
|
3666
|
+
}
|
|
3667
|
+
free(v2) {
|
|
3668
|
+
this.#text.free(v2);
|
|
3669
|
+
}
|
|
3670
|
+
incrementRender() {
|
|
3671
|
+
this.#renders++;
|
|
3672
|
+
}
|
|
3673
|
+
/** always updates but never invalidates. */
|
|
3674
|
+
update(v2) {
|
|
3675
|
+
this.#updates++;
|
|
3676
|
+
this.#text.text = `${this.#updates} updates
|
|
3677
|
+
${this.#renders + 1} renders`;
|
|
3678
|
+
this.#text.layout(v2);
|
|
3679
|
+
this.#text.xy = v2.cam.follow(
|
|
3680
|
+
{ w: this.#text.wh.w, h: this.#text.wh.h - this.#text.scaledLeading },
|
|
3681
|
+
this.#text.z,
|
|
3682
|
+
"NE",
|
|
3683
|
+
{ margin: { w: 8, h: 8 } }
|
|
3684
|
+
);
|
|
3685
|
+
this.#text.update(v2);
|
|
3686
|
+
}
|
|
3687
|
+
};
|
|
3688
|
+
|
|
3689
|
+
// src/demo/game.ts
|
|
3690
|
+
var Game = class extends Void {
|
|
3691
|
+
#filterSprites;
|
|
3692
|
+
#interval = 0;
|
|
3693
|
+
#renderToggle;
|
|
3694
|
+
#timer = 0;
|
|
3695
|
+
#workCounter;
|
|
3696
|
+
constructor() {
|
|
3697
|
+
super({
|
|
3698
|
+
preloadAtlas: {
|
|
3699
|
+
image: document.querySelector("#preload-atlas"),
|
|
3700
|
+
json: preload_atlas_default
|
|
3701
|
+
},
|
|
3702
|
+
backgroundRGBA: 4294947327,
|
|
3703
|
+
minWH: { w: 320, h: 240 }
|
|
3704
|
+
});
|
|
3705
|
+
this.#filterSprites = new Pool({
|
|
3706
|
+
alloc: (pool) => new Sprite(pool, 0, this.preload, this.framer),
|
|
3707
|
+
allocBytes: drawableBytes,
|
|
3708
|
+
pageBlocks: 10
|
|
3709
|
+
});
|
|
3710
|
+
this.#renderToggle = new RenderToggleEnt(this);
|
|
3711
|
+
this.#workCounter = new WorkCounterEnt();
|
|
3712
|
+
this.#initZoo();
|
|
3713
|
+
}
|
|
3714
|
+
async register(op) {
|
|
3715
|
+
await super.register(op);
|
|
3716
|
+
if (op === "add") {
|
|
3717
|
+
this.framer.requestFrame();
|
|
3718
|
+
this.#startTimer();
|
|
3719
|
+
} else {
|
|
3720
|
+
this.#stopTimer();
|
|
3721
|
+
}
|
|
3722
|
+
}
|
|
3723
|
+
onLoop(_millis) {
|
|
3724
|
+
this.renderer.always = this.#renderToggle.on || !!debug?.invalid;
|
|
3725
|
+
let render = this.#updateCam();
|
|
3726
|
+
const updated = this.zoo.update(this);
|
|
3727
|
+
if (debug?.input) this.#printInput();
|
|
3728
|
+
render ||= updated || this.cam.invalid || this.renderer.invalid || this.renderer.always;
|
|
3729
|
+
if (render) {
|
|
3730
|
+
this.#workCounter.incrementRender();
|
|
3731
|
+
this.renderer.clear(4294947327);
|
|
3732
|
+
this.renderer.predraw(this.cam, this.framer);
|
|
3733
|
+
this.renderer.setDepth(true);
|
|
3734
|
+
this.renderer.draw(this.sprites);
|
|
3735
|
+
this.renderer.setDepth(false);
|
|
3736
|
+
this.renderer.draw(this.#filterSprites);
|
|
3737
|
+
}
|
|
3738
|
+
this.requestFrame();
|
|
3739
|
+
}
|
|
3740
|
+
#initZoo() {
|
|
3741
|
+
const border = new NinePatchEnt(this, {
|
|
3742
|
+
n: { tag: "background--Black" },
|
|
3743
|
+
origin: { tag: "background--Transparent" },
|
|
3744
|
+
border: { n: 1 },
|
|
3745
|
+
z: Layer.UIA
|
|
3746
|
+
// to-do: default 0 layer is dumb.
|
|
3747
|
+
});
|
|
3748
|
+
this.zoo.add(border);
|
|
3749
|
+
const box = this.cam.follow({ w: 0, h: 0 }, Layer.UIA, "NW", { fill: "XY" });
|
|
3750
|
+
border.xy = box;
|
|
3751
|
+
border.wh = box;
|
|
3752
|
+
const backpacker = this.sprites.alloc();
|
|
3753
|
+
backpacker.tag = "backpacker--WalkRight";
|
|
3754
|
+
backpacker.x = 7;
|
|
3755
|
+
backpacker.y = 7;
|
|
3756
|
+
backpacker.z = Layer.C;
|
|
3757
|
+
backpacker.stretch = true;
|
|
3758
|
+
backpacker.w *= 5;
|
|
3759
|
+
backpacker.h *= 5;
|
|
3760
|
+
const oidoid = new FollowCamEnt(this, "oidoid--Default", "SW");
|
|
3761
|
+
oidoid.z = Layer.UIG;
|
|
3762
|
+
oidoid.margin = { w: 4, h: 4 };
|
|
3763
|
+
this.zoo.add(
|
|
3764
|
+
new CursorEnt(this, "cursor--Pointer"),
|
|
3765
|
+
this.#renderToggle,
|
|
3766
|
+
new ClockEnt(),
|
|
3767
|
+
this.#workCounter,
|
|
3768
|
+
oidoid
|
|
3769
|
+
);
|
|
3770
|
+
const overlay = this.#filterSprites.alloc();
|
|
3771
|
+
overlay.tag = "background--GreyCheckerboard";
|
|
3772
|
+
overlay.w = drawableMaxWH.w;
|
|
3773
|
+
overlay.h = drawableMaxWH.h;
|
|
3774
|
+
overlay.z = Layer.UIA;
|
|
3775
|
+
}
|
|
3776
|
+
#printInput() {
|
|
3777
|
+
if (this.input.started) {
|
|
3778
|
+
const on = !!this.input.on.length;
|
|
3779
|
+
if (on) console.debug(`[input] buttons on: ${this.input.on.join(" ")}.`);
|
|
3780
|
+
else console.debug(`[input] buttons off.`);
|
|
3781
|
+
const combo = this.input.combo;
|
|
3782
|
+
if (combo.length > 1 && on)
|
|
3783
|
+
console.debug(
|
|
3784
|
+
`[input] combo: ${combo.map((set) => set.join("+")).join(" ")}.`
|
|
3785
|
+
);
|
|
3786
|
+
}
|
|
3787
|
+
if (this.input.point?.invalid && this.input.point?.click && !this.input.point.pinch)
|
|
3788
|
+
console.debug(
|
|
3789
|
+
`[input] ${this.input.point.drag.on ? "drag" : "click"} xy: ${this.input.point.x} ${this.input.point.y}.`
|
|
3790
|
+
);
|
|
3791
|
+
if (this.input.point?.pinch)
|
|
3792
|
+
console.debug(
|
|
3793
|
+
`[input] pinch xy: ${this.input.point.pinch.xy.x} ${this.input.point.pinch.xy.y}.`
|
|
3794
|
+
);
|
|
3795
|
+
if (this.input.wheel)
|
|
3796
|
+
console.debug(
|
|
3797
|
+
`[input] wheel xy: ${this.input.wheel.delta.xy.x} ${this.input.wheel.delta.xy.y}.`
|
|
3798
|
+
);
|
|
3799
|
+
}
|
|
3800
|
+
#startTimer() {
|
|
3801
|
+
this.#timer = setTimeout(
|
|
3802
|
+
() => {
|
|
3803
|
+
this.framer.requestFrame();
|
|
3804
|
+
this.#interval = setInterval(
|
|
3805
|
+
() => this.framer.requestFrame(),
|
|
3806
|
+
(debug?.seconds ? 1 : 60) * 1e3
|
|
3807
|
+
);
|
|
3808
|
+
},
|
|
3809
|
+
renderDelayMillis(/* @__PURE__ */ new Date(), debug?.seconds)
|
|
3810
|
+
);
|
|
3811
|
+
}
|
|
3812
|
+
#stopTimer() {
|
|
3813
|
+
clearTimeout(this.#timer);
|
|
3814
|
+
clearInterval(this.#interval);
|
|
3815
|
+
}
|
|
3816
|
+
#updateCam() {
|
|
3817
|
+
let render = this.input.isAnyOn("L", "R", "U", "D");
|
|
3818
|
+
if (this.input.isAnyOnStart("L", "R", "U", "D")) {
|
|
3819
|
+
this.cam.x = Math.trunc(this.cam.x);
|
|
3820
|
+
this.cam.y = Math.trunc(this.cam.y);
|
|
3821
|
+
}
|
|
3822
|
+
const d = 1 / 4;
|
|
3823
|
+
if (this.input.isOn("L")) this.cam.x -= d;
|
|
3824
|
+
if (this.input.isOn("R")) this.cam.x += d;
|
|
3825
|
+
if (this.input.isOn("U")) this.cam.y -= d;
|
|
3826
|
+
if (this.input.isOn("D")) this.cam.y += d;
|
|
3827
|
+
if (this.input.wheel?.delta.xy.y) {
|
|
3828
|
+
render = true;
|
|
3829
|
+
this.cam.zoomOut -= this.input.wheel.delta.client.y * 0.01;
|
|
3830
|
+
}
|
|
3831
|
+
this.cam.update(this.canvas);
|
|
3832
|
+
return render;
|
|
3833
|
+
}
|
|
3834
|
+
};
|
|
3835
|
+
function renderDelayMillis(time, debugSecs) {
|
|
3836
|
+
return ((debugSecs ? 0 : (59 - time.getSeconds() % 60) * 1e3) + 1e3 - time.getMilliseconds() % 1e3) % (debugSecs ? 1e3 : 6e4);
|
|
3837
|
+
}
|
|
3838
|
+
|
|
3839
|
+
// src/demo/index.ts
|
|
3840
|
+
console.debug(`void v${version} \u2500\u2500\u2500oidoid>\xB0\u2500\u2500`);
|
|
3841
|
+
var v = new Game();
|
|
3842
|
+
await v.register("add");
|
|
3843
|
+
if (debug) globalThis.v = v;
|
|
3844
|
+
//# sourceMappingURL=index.js.map
|