aurasu 0.1.7 → 0.1.8
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/assets/splash/aurajs-gg-wordmark.webp +0 -0
- package/assets/splash/bg.webp +0 -0
- package/assets/splash/boot-loop.wav +0 -0
- package/assets/splash/boot-sting.wav +0 -0
- package/assets/splash/logo-mascot-sheet.webp +0 -0
- package/assets/splash/logoholo.webp +0 -0
- package/aura.package-integrity.json +42 -7
- package/aura.package-integrity.sig +1 -1
- package/bin/play.js +67 -1
- package/package.json +2 -2
- package/src/main.js +4 -0
- package/src/runtime/splash.js +305 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -150,6 +150,36 @@
|
|
|
150
150
|
"sha256": "7f0f8344db9fda1d6b3d0c6a45e36ae51d5198b7613deee326a85e67cd2f413b",
|
|
151
151
|
"size": 2142
|
|
152
152
|
},
|
|
153
|
+
{
|
|
154
|
+
"path": "assets/splash/aurajs-gg-wordmark.webp",
|
|
155
|
+
"sha256": "80a4ebd7d23f624aa1ead31c4702b3c21ce8c99075e80e4f3a371870585c73af",
|
|
156
|
+
"size": 21970
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"path": "assets/splash/bg.webp",
|
|
160
|
+
"sha256": "3a8892862610ce453314dae576f6707470a7761eb2be5987b55501d9ccd41f54",
|
|
161
|
+
"size": 46216
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"path": "assets/splash/boot-loop.wav",
|
|
165
|
+
"sha256": "569b8c457d478b003011d62f165ffd73ad11a598d28337b2c98ee8bb4357c0f7",
|
|
166
|
+
"size": 70604
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
"path": "assets/splash/boot-sting.wav",
|
|
170
|
+
"sha256": "386abbb357537ec0a284c9ff64de26821782de10002b2b5c9675b26bb755c44d",
|
|
171
|
+
"size": 48554
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"path": "assets/splash/logo-mascot-sheet.webp",
|
|
175
|
+
"sha256": "aaa75bea690285b2c6df08182c248cdae6ca374057978cdba25d57d8fb70c225",
|
|
176
|
+
"size": 22036
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"path": "assets/splash/logoholo.webp",
|
|
180
|
+
"sha256": "65bec52e3ecb6417aa74832a3153c837b9aaee6b3dd5d7e8536235b7d11442cd",
|
|
181
|
+
"size": 12782
|
|
182
|
+
},
|
|
153
183
|
{
|
|
154
184
|
"path": "assets/ui-back.wav",
|
|
155
185
|
"sha256": "a4e071c73866aa94a7e34a636c18aff4a9c83a4bd3d5333f63f07704e982b793",
|
|
@@ -177,8 +207,8 @@
|
|
|
177
207
|
},
|
|
178
208
|
{
|
|
179
209
|
"path": "bin/play.js",
|
|
180
|
-
"sha256": "
|
|
181
|
-
"size":
|
|
210
|
+
"sha256": "c29cc4a29d0470e46ce5555cbc4001f96d7458ab7a5975ad55b3248fb5859520",
|
|
211
|
+
"size": 42416
|
|
182
212
|
},
|
|
183
213
|
{
|
|
184
214
|
"path": "config/gameplay/game.config.js",
|
|
@@ -192,7 +222,7 @@
|
|
|
192
222
|
},
|
|
193
223
|
{
|
|
194
224
|
"path": "package.json",
|
|
195
|
-
"sha256": "
|
|
225
|
+
"sha256": "4c081cac3332359fef0c3c4e224ccf1d3f48441c38e70dd54394225110dca757",
|
|
196
226
|
"size": 568
|
|
197
227
|
},
|
|
198
228
|
{
|
|
@@ -212,8 +242,8 @@
|
|
|
212
242
|
},
|
|
213
243
|
{
|
|
214
244
|
"path": "src/main.js",
|
|
215
|
-
"sha256": "
|
|
216
|
-
"size":
|
|
245
|
+
"sha256": "0b2f36b0a56d38529289077b7a43795edc4c064d9747c47f3c200426bbfb67d9",
|
|
246
|
+
"size": 577
|
|
217
247
|
},
|
|
218
248
|
{
|
|
219
249
|
"path": "src/runtime/app-state.js",
|
|
@@ -255,6 +285,11 @@
|
|
|
255
285
|
"sha256": "56321b896b4368973feb6f5581a9e27d2553b1be91d66206e88cf9ffb25723f8",
|
|
256
286
|
"size": 6384
|
|
257
287
|
},
|
|
288
|
+
{
|
|
289
|
+
"path": "src/runtime/splash.js",
|
|
290
|
+
"sha256": "00cd80250f0abffd14b27241d65dc0b3402c3814a5bb4395d0cd538b20ae59fc",
|
|
291
|
+
"size": 9799
|
|
292
|
+
},
|
|
258
293
|
{
|
|
259
294
|
"path": "src/runtime/ui-settings.js",
|
|
260
295
|
"sha256": "c09e6ae51fa3dc507da5c8b1975598629081bad0af98faa32471ca5fb1b32c6e",
|
|
@@ -272,14 +307,14 @@
|
|
|
272
307
|
}
|
|
273
308
|
],
|
|
274
309
|
"package": {
|
|
275
|
-
"aurajsVersion": "0.1.
|
|
310
|
+
"aurajsVersion": "0.1.3",
|
|
276
311
|
"bin": {
|
|
277
312
|
"aurasu": "bin/play.js"
|
|
278
313
|
},
|
|
279
314
|
"description": "A hit-circle rhythm game built with AuraJS.",
|
|
280
315
|
"name": "aurasu",
|
|
281
316
|
"type": "module",
|
|
282
|
-
"version": "0.1.
|
|
317
|
+
"version": "0.1.8"
|
|
283
318
|
},
|
|
284
319
|
"publishedMetadata": {
|
|
285
320
|
"authored": {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
dVntP3f6ovlY/3IR88FwdOm1RuqOGaSJlY4d4r0gcWHGG5C2uyapbrNxm2ufha+zqpUXCCma3tTrnEl0Y7oQBg==
|
package/bin/play.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { spawn } from 'node:child_process';
|
|
3
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
4
4
|
import { cpSync, createWriteStream, existsSync, mkdirSync, readFileSync } from 'node:fs';
|
|
5
5
|
import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
6
6
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
@@ -58,6 +58,39 @@ const ALL_COMMANDS = ['dev', 'join', 'play', 'fork', 'publish', 'session', 'stat
|
|
|
58
58
|
const ROOM_CODE_PATTERN = /^[A-Z0-9]{4,8}$/;
|
|
59
59
|
const FORK_EXCLUDED_TOP_LEVEL = new Set(['.aura', '.git', '.logs', 'build', 'dist', 'node_modules']);
|
|
60
60
|
|
|
61
|
+
function resolveAuraMaxxBinary() {
|
|
62
|
+
return process.platform === 'win32' ? 'auramaxx.cmd' : 'auramaxx';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function resolveNpmBinary() {
|
|
66
|
+
return process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function isAuraMaxxInstalled() {
|
|
70
|
+
const probe = spawnSync(resolveAuraMaxxBinary(), ['--version'], {
|
|
71
|
+
stdio: 'ignore',
|
|
72
|
+
env: process.env,
|
|
73
|
+
});
|
|
74
|
+
return !probe.error && probe.status === 0;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function installAuraMaxxGlobally() {
|
|
78
|
+
return new Promise((resolveInstall) => {
|
|
79
|
+
const child = spawn(
|
|
80
|
+
resolveNpmBinary(),
|
|
81
|
+
['install', '-g', 'auramaxx', '--foreground-scripts'],
|
|
82
|
+
{
|
|
83
|
+
cwd: process.cwd(),
|
|
84
|
+
stdio: 'inherit',
|
|
85
|
+
env: process.env,
|
|
86
|
+
},
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
child.on('error', () => resolveInstall(false));
|
|
90
|
+
child.on('close', (code) => resolveInstall((code ?? 1) === 0));
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
61
94
|
function resolveLocalAuraCli(startRoot) {
|
|
62
95
|
let current = resolve(startRoot);
|
|
63
96
|
while (true) {
|
|
@@ -1063,6 +1096,38 @@ async function chooseDefaultCommand() {
|
|
|
1063
1096
|
return choice;
|
|
1064
1097
|
}
|
|
1065
1098
|
|
|
1099
|
+
async function maybeOfferAuraMaxxInstall() {
|
|
1100
|
+
if (isAuraMaxxInstalled()) {
|
|
1101
|
+
return;
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
1105
|
+
return;
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
printSection('AuraMaxx', 'AuraMaxx is not installed globally.');
|
|
1109
|
+
const choice = await promptSelect(
|
|
1110
|
+
' Install AuraMaxx now?',
|
|
1111
|
+
[
|
|
1112
|
+
{ value: 'yes', label: 'Yes, install AuraMaxx' },
|
|
1113
|
+
{ value: 'no', label: 'No, continue playing' },
|
|
1114
|
+
],
|
|
1115
|
+
'yes',
|
|
1116
|
+
);
|
|
1117
|
+
|
|
1118
|
+
if (choice !== 'yes') {
|
|
1119
|
+
return;
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
printSection('AuraMaxx', 'Installing global CLI...');
|
|
1123
|
+
const installed = await installAuraMaxxGlobally();
|
|
1124
|
+
if (installed) {
|
|
1125
|
+
printSection('AuraMaxx', 'Installed. Continuing play...');
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1128
|
+
printSection('AuraMaxx', 'Install failed. Continuing play...');
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1066
1131
|
async function main() {
|
|
1067
1132
|
const parsed = parseArgs(process.argv.slice(2));
|
|
1068
1133
|
|
|
@@ -1092,6 +1157,7 @@ async function main() {
|
|
|
1092
1157
|
if (command === 'play') {
|
|
1093
1158
|
printBanner('PLAY');
|
|
1094
1159
|
printSection(toDisplayTitle(packageName), 'Starting packaged local game session...');
|
|
1160
|
+
await maybeOfferAuraMaxxInstall();
|
|
1095
1161
|
const externalAssets = await maybePrepareExternalAssets('play');
|
|
1096
1162
|
const multiplayerEnv = await resolveLocalMultiplayerCommandEnv();
|
|
1097
1163
|
await runCommand(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aurasu",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "A hit-circle rhythm game built with AuraJS.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"aura.package-integrity.sig"
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@auraindustry/aurajs": "0.1.
|
|
24
|
+
"@auraindustry/aurajs": "0.1.3"
|
|
25
25
|
},
|
|
26
26
|
"keywords": [
|
|
27
27
|
"aurajs",
|
package/src/main.js
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { createApp } from './runtime/app.js';
|
|
2
|
+
import { initSplash, updateSplash, drawSplash, isSplashActive } from './runtime/splash.js';
|
|
2
3
|
|
|
3
4
|
const app = createApp();
|
|
4
5
|
|
|
5
6
|
aura.setup = function setup() {
|
|
7
|
+
initSplash();
|
|
6
8
|
return app.setup();
|
|
7
9
|
};
|
|
8
10
|
|
|
9
11
|
aura.update = function update(dt) {
|
|
12
|
+
if (isSplashActive()) { updateSplash(dt); return; }
|
|
10
13
|
app.update(dt);
|
|
11
14
|
};
|
|
12
15
|
|
|
13
16
|
aura.draw = function draw() {
|
|
17
|
+
if (isSplashActive()) { drawSplash(); return; }
|
|
14
18
|
app.draw();
|
|
15
19
|
};
|
|
16
20
|
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
// AuraJS Splash — unified retro paper-card boot screen.
|
|
2
|
+
// Auto-wired by createApp(). Shows once on launch, then hands off to the game.
|
|
3
|
+
|
|
4
|
+
const FADE_IN = 0.7;
|
|
5
|
+
const HOLD = 1.8;
|
|
6
|
+
const FADE_OUT = 0.7;
|
|
7
|
+
const TOTAL = FADE_IN + HOLD + FADE_OUT;
|
|
8
|
+
|
|
9
|
+
const PAPER = [0.89, 0.89, 0.89];
|
|
10
|
+
const PAPER_SHADOW = [0.80, 0.80, 0.80];
|
|
11
|
+
const PAPER_EDGE = [0.41, 0.41, 0.41];
|
|
12
|
+
const INK = [0.1, 0.1, 0.1];
|
|
13
|
+
const INK_MUTED = [0.42, 0.42, 0.42];
|
|
14
|
+
const MASCOT_FRAME_W = 64;
|
|
15
|
+
const MASCOT_FRAME_H = 84;
|
|
16
|
+
const MASCOT_SEQUENCE = Object.freeze([0, 1, 2, 1]);
|
|
17
|
+
const SPLASH_STING_PATH = 'splash/boot-sting.wav';
|
|
18
|
+
const SPLASH_LOOP_PATH = 'splash/boot-loop.wav';
|
|
19
|
+
const SPLASH_BUS = 'splash';
|
|
20
|
+
const QUIET_BUSES = Object.freeze(['default', 'music', 'sfx']);
|
|
21
|
+
|
|
22
|
+
let state = null;
|
|
23
|
+
|
|
24
|
+
function has(obj, method) {
|
|
25
|
+
return Boolean(obj) && typeof obj[method] === 'function';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function color(rgb, alpha = 1) {
|
|
29
|
+
return aura.rgba(rgb[0], rgb[1], rgb[2], alpha);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function drawShadowText(text, x, y, options = {}) {
|
|
33
|
+
const {
|
|
34
|
+
shadowOffset = 2,
|
|
35
|
+
shadowColor = color(INK_MUTED, 0.3),
|
|
36
|
+
...rest
|
|
37
|
+
} = options;
|
|
38
|
+
aura.draw2d.text(text, x + shadowOffset, y + shadowOffset, {
|
|
39
|
+
...rest,
|
|
40
|
+
color: shadowColor,
|
|
41
|
+
});
|
|
42
|
+
aura.draw2d.text(text, x, y, rest);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function initSplash() {
|
|
46
|
+
state = {
|
|
47
|
+
t: 0,
|
|
48
|
+
logo: null,
|
|
49
|
+
mascot: null,
|
|
50
|
+
wordmark: null,
|
|
51
|
+
font: null,
|
|
52
|
+
stingHandle: null,
|
|
53
|
+
loopHandle: null,
|
|
54
|
+
busVolumes: null,
|
|
55
|
+
pausedHandles: [],
|
|
56
|
+
};
|
|
57
|
+
try { if (has(aura.assets, 'load')) state.logo = aura.assets.load('splash/logoholo.webp'); } catch (_) {}
|
|
58
|
+
try { if (has(aura.assets, 'load')) state.mascot = aura.assets.load('splash/logo-mascot-sheet.webp'); } catch (_) {}
|
|
59
|
+
try { if (has(aura.assets, 'load')) state.wordmark = aura.assets.load('splash/aurajs-gg-wordmark.webp'); } catch (_) {}
|
|
60
|
+
try {
|
|
61
|
+
if (has(aura.assets, 'loadBitmapFont')) {
|
|
62
|
+
const result = aura.assets.loadBitmapFont();
|
|
63
|
+
if (result && result.ok && result.font) state.font = result.font;
|
|
64
|
+
}
|
|
65
|
+
} catch (_) {}
|
|
66
|
+
captureBusVolumes();
|
|
67
|
+
applySplashBusIsolation();
|
|
68
|
+
try {
|
|
69
|
+
if (aura.audio && aura.audio.supported !== false && typeof aura.audio.play === 'function') {
|
|
70
|
+
state.loopHandle = aura.audio.play(SPLASH_LOOP_PATH, {
|
|
71
|
+
loop: true,
|
|
72
|
+
volume: 0.22,
|
|
73
|
+
bus: SPLASH_BUS,
|
|
74
|
+
});
|
|
75
|
+
state.stingHandle = aura.audio.play(SPLASH_STING_PATH, {
|
|
76
|
+
loop: false,
|
|
77
|
+
volume: 0.54,
|
|
78
|
+
bus: SPLASH_BUS,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
} catch (_) {}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function isSplashActive() {
|
|
85
|
+
return state !== null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function updateSplash(dt) {
|
|
89
|
+
if (!state) return;
|
|
90
|
+
syncPausedTracks();
|
|
91
|
+
try {
|
|
92
|
+
if (aura.audio && typeof aura.audio.update === 'function') {
|
|
93
|
+
aura.audio.update(Number(dt) > 0 ? Number(dt) : (1 / 60));
|
|
94
|
+
}
|
|
95
|
+
} catch (_) {}
|
|
96
|
+
state.t += dt;
|
|
97
|
+
if (state.t >= TOTAL) {
|
|
98
|
+
stopSplashAudio();
|
|
99
|
+
state = null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function drawSplash() {
|
|
104
|
+
if (!state) return;
|
|
105
|
+
const { width: w, height: h } = has(aura.window, 'getSize')
|
|
106
|
+
? aura.window.getSize()
|
|
107
|
+
: { width: 640, height: 480 };
|
|
108
|
+
const t = state.t;
|
|
109
|
+
const cx = w / 2;
|
|
110
|
+
const cy = h / 2;
|
|
111
|
+
|
|
112
|
+
let a = 1;
|
|
113
|
+
if (t < FADE_IN) a = easeOut(t / FADE_IN);
|
|
114
|
+
else if (t > FADE_IN + HOLD) a = 1 - easeIn((t - FADE_IN - HOLD) / FADE_OUT);
|
|
115
|
+
|
|
116
|
+
aura.draw2d.clear(color(PAPER));
|
|
117
|
+
|
|
118
|
+
const panelW = Math.min(Math.floor(w * 0.48), 580);
|
|
119
|
+
const panelH = Math.min(Math.floor(h * 0.72), 620);
|
|
120
|
+
const panelX = Math.floor(cx - (panelW * 0.5));
|
|
121
|
+
const panelY = Math.floor(cy - (panelH * 0.5));
|
|
122
|
+
|
|
123
|
+
aura.draw2d.rectFill(panelX + 6, panelY + 6, panelW, panelH, color(INK, 0.08 * a));
|
|
124
|
+
aura.draw2d.rectFill(panelX, panelY, panelW, panelH, color(PAPER_EDGE, a));
|
|
125
|
+
aura.draw2d.rectFill(panelX + 6, panelY + 6, panelW - 12, panelH - 12, color(PAPER, a));
|
|
126
|
+
aura.draw2d.rectFill(panelX + 12, panelY + 12, panelW - 24, panelH - 24, color(PAPER, a * 0.96));
|
|
127
|
+
|
|
128
|
+
const floatY = Math.sin(t * 1.4 * Math.PI * 2) * 2;
|
|
129
|
+
const breathe = 0.985 + 0.015 * (0.5 + 0.5 * Math.sin(t * Math.PI * 2));
|
|
130
|
+
const mascotScale = Math.max(1, Math.min(Math.floor(Math.min(w, h) / 260), 2));
|
|
131
|
+
const mascotW = Math.floor(MASCOT_FRAME_W * mascotScale * breathe);
|
|
132
|
+
const mascotH = Math.floor(MASCOT_FRAME_H * mascotScale * breathe);
|
|
133
|
+
const mascotX = Math.floor(cx - (mascotW * 0.5));
|
|
134
|
+
const mascotY = Math.floor(panelY + panelH * 0.40 + floatY);
|
|
135
|
+
const mascotFrame = MASCOT_SEQUENCE[Math.floor(t * 7.5) % MASCOT_SEQUENCE.length] || 0;
|
|
136
|
+
|
|
137
|
+
aura.draw2d.rectFill(
|
|
138
|
+
mascotX + Math.floor(mascotW * 0.18),
|
|
139
|
+
mascotY + mascotH - 8,
|
|
140
|
+
Math.floor(mascotW * 0.64),
|
|
141
|
+
6,
|
|
142
|
+
color(INK, a * 0.08),
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
if (state.mascot) {
|
|
146
|
+
aura.draw2d.sprite(state.mascot, mascotX, mascotY, {
|
|
147
|
+
width: mascotW,
|
|
148
|
+
height: mascotH,
|
|
149
|
+
frameX: mascotFrame * MASCOT_FRAME_W,
|
|
150
|
+
frameY: 0,
|
|
151
|
+
frameW: MASCOT_FRAME_W,
|
|
152
|
+
frameH: MASCOT_FRAME_H,
|
|
153
|
+
alpha: a,
|
|
154
|
+
});
|
|
155
|
+
} else if (state.logo) {
|
|
156
|
+
const sz = Math.min(Math.floor(panelW * 0.24), Math.floor(h * 0.14)) * breathe;
|
|
157
|
+
aura.draw2d.sprite(state.logo, Math.floor(cx - sz / 2), Math.floor(mascotY + 6), {
|
|
158
|
+
width: sz,
|
|
159
|
+
height: sz,
|
|
160
|
+
alpha: a,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const ta = clamp(a * easeOut(clamp((t - 0.2) / (FADE_IN * 0.6))));
|
|
165
|
+
const sa = clamp(a * easeOut(clamp((t - 0.4) / (FADE_IN * 0.6))));
|
|
166
|
+
const scale = Math.min(w, h) / 480;
|
|
167
|
+
const tsz = Math.max(24, Math.round(scale * 28));
|
|
168
|
+
const ssz = Math.max(11, Math.round(scale * 12));
|
|
169
|
+
const wordmarkW = Math.min(Math.floor(panelW * 0.52), 290);
|
|
170
|
+
const wordmarkH = Math.floor(wordmarkW * (768 / 1408));
|
|
171
|
+
const wordmarkX = Math.floor(cx - (wordmarkW * 0.5));
|
|
172
|
+
const wordmarkY = Math.floor(panelY + 36);
|
|
173
|
+
const sY = Math.floor(panelY + panelH - 108);
|
|
174
|
+
const fo = state.font ? { font: state.font } : {};
|
|
175
|
+
|
|
176
|
+
if (state.wordmark) {
|
|
177
|
+
aura.draw2d.sprite(state.wordmark, wordmarkX, wordmarkY, {
|
|
178
|
+
width: wordmarkW,
|
|
179
|
+
height: wordmarkH,
|
|
180
|
+
alpha: ta,
|
|
181
|
+
tint: color(INK, ta),
|
|
182
|
+
});
|
|
183
|
+
} else {
|
|
184
|
+
drawShadowText('AuraJS.gg', cx, wordmarkY + Math.floor(wordmarkH * 0.55), {
|
|
185
|
+
...fo,
|
|
186
|
+
size: tsz,
|
|
187
|
+
color: color(INK, ta),
|
|
188
|
+
shadowColor: color(INK_MUTED, ta * 0.28),
|
|
189
|
+
align: 'center',
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
drawShadowText('Open-Source. MIT.', cx, sY, {
|
|
194
|
+
...fo,
|
|
195
|
+
size: ssz,
|
|
196
|
+
color: color(INK_MUTED, sa),
|
|
197
|
+
shadowColor: color(PAPER_EDGE, sa * 0.18),
|
|
198
|
+
shadowOffset: 1,
|
|
199
|
+
align: 'center',
|
|
200
|
+
});
|
|
201
|
+
drawShadowText('Who needs publishers?', cx, sY + Math.max(16, Math.round(ssz * 1.45)), {
|
|
202
|
+
...fo,
|
|
203
|
+
size: ssz,
|
|
204
|
+
color: color(INK_MUTED, sa),
|
|
205
|
+
shadowColor: color(PAPER_EDGE, sa * 0.18),
|
|
206
|
+
shadowOffset: 1,
|
|
207
|
+
align: 'center',
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
const rw = Math.min(panelW - 140, 240);
|
|
211
|
+
aura.draw2d.rectFill(Math.floor(cx - rw / 2), Math.floor(sY + Math.max(34, ssz * 3.2)), rw, 2, color(PAPER_EDGE, sa * 0.38));
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function easeOut(t) {
|
|
215
|
+
const u = 1 - clamp(t);
|
|
216
|
+
return 1 - (u * u * u);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function easeIn(t) {
|
|
220
|
+
const c = clamp(t);
|
|
221
|
+
return c * c * c;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function clamp(v) {
|
|
225
|
+
return v < 0 ? 0 : v > 1 ? 1 : v;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function stopSplashAudio() {
|
|
229
|
+
if (!state || !aura.audio || typeof aura.audio.stop !== 'function') return;
|
|
230
|
+
try {
|
|
231
|
+
if (state.stingHandle != null) aura.audio.stop(state.stingHandle);
|
|
232
|
+
} catch (_) {}
|
|
233
|
+
try {
|
|
234
|
+
if (state.loopHandle != null) aura.audio.stop(state.loopHandle);
|
|
235
|
+
} catch (_) {}
|
|
236
|
+
restoreAudioState();
|
|
237
|
+
state.stingHandle = null;
|
|
238
|
+
state.loopHandle = null;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function captureBusVolumes() {
|
|
242
|
+
if (!state || !aura.audio || typeof aura.audio.getMixerState !== 'function') return;
|
|
243
|
+
try {
|
|
244
|
+
const mixer = aura.audio.getMixerState();
|
|
245
|
+
const buses = Array.isArray(mixer?.buses) ? mixer.buses : [];
|
|
246
|
+
state.busVolumes = buses.reduce((acc, entry) => {
|
|
247
|
+
const bus = String(entry?.bus || '').trim();
|
|
248
|
+
if (!bus) return acc;
|
|
249
|
+
acc[bus] = Number(entry?.volume);
|
|
250
|
+
return acc;
|
|
251
|
+
}, {});
|
|
252
|
+
} catch (_) {}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function applySplashBusIsolation() {
|
|
256
|
+
if (!state || !aura.audio || typeof aura.audio.setBusVolume !== 'function') return;
|
|
257
|
+
try { aura.audio.setBusVolume(SPLASH_BUS, 1); } catch (_) {}
|
|
258
|
+
for (const bus of QUIET_BUSES) {
|
|
259
|
+
try { aura.audio.setBusVolume(bus, 0); } catch (_) {}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function syncPausedTracks() {
|
|
264
|
+
if (!state || !aura.audio || typeof aura.audio.getMixerState !== 'function' || typeof aura.audio.pause !== 'function') return;
|
|
265
|
+
try {
|
|
266
|
+
const mixer = aura.audio.getMixerState();
|
|
267
|
+
const tracks = Array.isArray(mixer?.tracks) ? mixer.tracks : [];
|
|
268
|
+
const splashHandles = [state.stingHandle, state.loopHandle].filter((handle) => handle != null);
|
|
269
|
+
const pausedHandles = new Set(Array.isArray(state.pausedHandles) ? state.pausedHandles : []);
|
|
270
|
+
for (const track of tracks) {
|
|
271
|
+
const handle = Number(track?.handle);
|
|
272
|
+
if (!Number.isInteger(handle) || handle <= 0) continue;
|
|
273
|
+
if (splashHandles.includes(handle)) continue;
|
|
274
|
+
if (track?.paused === true || pausedHandles.has(handle)) continue;
|
|
275
|
+
try {
|
|
276
|
+
aura.audio.pause(handle);
|
|
277
|
+
pausedHandles.add(handle);
|
|
278
|
+
} catch (_) {}
|
|
279
|
+
}
|
|
280
|
+
state.pausedHandles = Array.from(pausedHandles);
|
|
281
|
+
} catch (_) {}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function restoreAudioState() {
|
|
285
|
+
if (!state || !aura.audio) return;
|
|
286
|
+
if (typeof aura.audio.setBusVolume === 'function') {
|
|
287
|
+
const snapshot = state.busVolumes && typeof state.busVolumes === 'object' ? state.busVolumes : null;
|
|
288
|
+
if (snapshot) {
|
|
289
|
+
for (const [bus, volume] of Object.entries(snapshot)) {
|
|
290
|
+
try { aura.audio.setBusVolume(bus, Number(volume)); } catch (_) {}
|
|
291
|
+
}
|
|
292
|
+
} else {
|
|
293
|
+
for (const bus of QUIET_BUSES) {
|
|
294
|
+
try { aura.audio.setBusVolume(bus, 1); } catch (_) {}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
try { aura.audio.setBusVolume(SPLASH_BUS, 1); } catch (_) {}
|
|
298
|
+
}
|
|
299
|
+
if (typeof aura.audio.resume === 'function') {
|
|
300
|
+
for (const handle of Array.isArray(state.pausedHandles) ? state.pausedHandles : []) {
|
|
301
|
+
try { aura.audio.resume(handle); } catch (_) {}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
state.pausedHandles = [];
|
|
305
|
+
}
|