easter-egg-quest 1.0.18 → 1.0.20
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/easter-egg-quest.es.js +159 -79
- package/dist/easter-egg-quest.umd.js +1 -1
- package/dist/types/input/InputTracker.d.ts +9 -2
- package/dist/types/rendering/NarrativeRenderer.d.ts +3 -1
- package/dist/types/rendering/PageBreather.d.ts +1 -0
- package/dist/types/rendering/ThreeRenderer.d.ts +3 -2
- package/dist/types/stages/RhythmStage.d.ts +5 -3
- package/package.json +1 -1
|
@@ -57,33 +57,25 @@ const DEFAULT_SCRIPT = {
|
|
|
57
57
|
stage2Success: [
|
|
58
58
|
"movement was the answer",
|
|
59
59
|
"the second egg appears",
|
|
60
|
-
"
|
|
61
|
-
"not stillness this time",
|
|
62
|
-
"but life in motion"
|
|
60
|
+
"hold it to collect"
|
|
63
61
|
],
|
|
64
62
|
// ── Stage 3: Rhythm ───────────────────────────────────────────────────
|
|
65
63
|
stage3Intro: [
|
|
66
|
-
"two truths that shouldn’t exist together",
|
|
67
64
|
"the final riddle:",
|
|
68
|
-
"
|
|
65
|
+
"Every living thing knows it. You’ve been doing it your whole life without thinking."
|
|
69
66
|
],
|
|
70
67
|
stage3Reactions: [
|
|
71
|
-
"one truth alone
|
|
72
|
-
"the other alone
|
|
68
|
+
"one truth alone is not enough",
|
|
69
|
+
"the other alone is not enough either",
|
|
73
70
|
"what do all living things share?",
|
|
74
|
-
"you
|
|
75
|
-
"you’ve been doing it since birth",
|
|
71
|
+
"you have known it since the beginning",
|
|
76
72
|
"listen to yourself",
|
|
77
|
-
"closer...",
|
|
78
|
-
"can you feel it?",
|
|
79
|
-
"the body remembers",
|
|
80
73
|
"in",
|
|
81
74
|
"out"
|
|
82
75
|
],
|
|
83
76
|
stage3Success: [
|
|
84
77
|
"rhythm was the answer",
|
|
85
|
-
"you found the third egg"
|
|
86
|
-
"nice work"
|
|
78
|
+
"you found the third egg"
|
|
87
79
|
],
|
|
88
80
|
// ── Finale ────────────────────────────────────────────────────────────
|
|
89
81
|
finale: [
|
|
@@ -331,8 +323,10 @@ class InputTracker {
|
|
|
331
323
|
this._prevX = 0;
|
|
332
324
|
this._prevY = 0;
|
|
333
325
|
this._prevMoveTs = 0;
|
|
334
|
-
this.
|
|
335
|
-
this.
|
|
326
|
+
this.DEFAULT_STILL_THRESHOLD_MS = 400;
|
|
327
|
+
this._stillThresholdMs = this.DEFAULT_STILL_THRESHOLD_MS;
|
|
328
|
+
this.DEFAULT_MIN_PHASE_MS = 300;
|
|
329
|
+
this._minPhaseMs = this.DEFAULT_MIN_PHASE_MS;
|
|
336
330
|
this._stillTimer = null;
|
|
337
331
|
this._handlers = [];
|
|
338
332
|
this._active = false;
|
|
@@ -471,6 +465,18 @@ class InputTracker {
|
|
|
471
465
|
this._snapshot.totalDistance = 0;
|
|
472
466
|
this._snapshot.maxVelocity = 0;
|
|
473
467
|
}
|
|
468
|
+
configurePhaseDetection(opts) {
|
|
469
|
+
if (typeof opts.stillThresholdMs === "number") {
|
|
470
|
+
this._stillThresholdMs = Math.max(250, opts.stillThresholdMs);
|
|
471
|
+
}
|
|
472
|
+
if (typeof opts.minPhaseMs === "number") {
|
|
473
|
+
this._minPhaseMs = Math.max(150, opts.minPhaseMs);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
resetPhaseDetection() {
|
|
477
|
+
this._stillThresholdMs = this.DEFAULT_STILL_THRESHOLD_MS;
|
|
478
|
+
this._minPhaseMs = this.DEFAULT_MIN_PHASE_MS;
|
|
479
|
+
}
|
|
474
480
|
// ─── Movement / Stillness transition logic ─────────────────────────────
|
|
475
481
|
_registerMove(now) {
|
|
476
482
|
this._snapshot.lastMoveTime = now;
|
|
@@ -483,7 +489,7 @@ class InputTracker {
|
|
|
483
489
|
if (this._stillTimer) clearTimeout(this._stillTimer);
|
|
484
490
|
this._stillTimer = setTimeout(() => {
|
|
485
491
|
this._becomeStill();
|
|
486
|
-
}, this.
|
|
492
|
+
}, this._stillThresholdMs);
|
|
487
493
|
}
|
|
488
494
|
_becomeStill() {
|
|
489
495
|
if (!this._snapshot.isMoving) return;
|
|
@@ -497,7 +503,7 @@ class InputTracker {
|
|
|
497
503
|
}
|
|
498
504
|
_completePhase(type, endTime) {
|
|
499
505
|
const duration = endTime - this._currentPhaseStart;
|
|
500
|
-
if (duration >= this.
|
|
506
|
+
if (duration >= this._minPhaseMs) {
|
|
501
507
|
this._phases.push({
|
|
502
508
|
type,
|
|
503
509
|
startTime: this._currentPhaseStart,
|
|
@@ -1312,6 +1318,7 @@ class NarrativeRenderer {
|
|
|
1312
1318
|
this.container = null;
|
|
1313
1319
|
this.currentLine = null;
|
|
1314
1320
|
this.clearTimer = null;
|
|
1321
|
+
this.awaitingConfirm = false;
|
|
1315
1322
|
this.config = config;
|
|
1316
1323
|
}
|
|
1317
1324
|
mount() {
|
|
@@ -1335,14 +1342,22 @@ class NarrativeRenderer {
|
|
|
1335
1342
|
this.container.className = "eeq-narrative";
|
|
1336
1343
|
this.shadow.appendChild(this.container);
|
|
1337
1344
|
}
|
|
1345
|
+
_removeCurrentLine(immediate = false) {
|
|
1346
|
+
if (!this.currentLine) return;
|
|
1347
|
+
const prev = this.currentLine;
|
|
1348
|
+
this.currentLine = null;
|
|
1349
|
+
if (immediate) {
|
|
1350
|
+
prev.remove();
|
|
1351
|
+
return;
|
|
1352
|
+
}
|
|
1353
|
+
prev.classList.add("eeq-narrative-exit");
|
|
1354
|
+
setTimeout(() => prev.remove(), 750);
|
|
1355
|
+
}
|
|
1338
1356
|
/** Show a single narrative line. Fades in, replaces any previous line. */
|
|
1339
1357
|
showLine(text, className = "eeq-line") {
|
|
1340
1358
|
if (!this.container) return;
|
|
1341
|
-
if (this.
|
|
1342
|
-
|
|
1343
|
-
prev.classList.add("eeq-narrative-exit");
|
|
1344
|
-
setTimeout(() => prev.remove(), 750);
|
|
1345
|
-
}
|
|
1359
|
+
if (this.awaitingConfirm) return;
|
|
1360
|
+
this._removeCurrentLine(true);
|
|
1346
1361
|
if (this.clearTimer) {
|
|
1347
1362
|
clearTimeout(this.clearTimer);
|
|
1348
1363
|
this.clearTimer = null;
|
|
@@ -1371,11 +1386,8 @@ class NarrativeRenderer {
|
|
|
1371
1386
|
resolve();
|
|
1372
1387
|
return;
|
|
1373
1388
|
}
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
prev.classList.add("eeq-narrative-exit");
|
|
1377
|
-
setTimeout(() => prev.remove(), 750);
|
|
1378
|
-
}
|
|
1389
|
+
this.awaitingConfirm = true;
|
|
1390
|
+
this._removeCurrentLine(true);
|
|
1379
1391
|
if (this.clearTimer) {
|
|
1380
1392
|
clearTimeout(this.clearTimer);
|
|
1381
1393
|
this.clearTimer = null;
|
|
@@ -1387,7 +1399,10 @@ class NarrativeRenderer {
|
|
|
1387
1399
|
const btn = document.createElement("button");
|
|
1388
1400
|
btn.className = "eeq-confirm-btn";
|
|
1389
1401
|
btn.textContent = "OK";
|
|
1390
|
-
btn.addEventListener("click", () =>
|
|
1402
|
+
btn.addEventListener("click", () => {
|
|
1403
|
+
this.awaitingConfirm = false;
|
|
1404
|
+
resolve();
|
|
1405
|
+
}, { once: true });
|
|
1391
1406
|
line.appendChild(btn);
|
|
1392
1407
|
requestAnimationFrame(() => {
|
|
1393
1408
|
requestAnimationFrame(() => {
|
|
@@ -1409,22 +1424,19 @@ class NarrativeRenderer {
|
|
|
1409
1424
|
this.showLine(text, "eeq-line eeq-celebration");
|
|
1410
1425
|
}
|
|
1411
1426
|
/** Clear current narrative text. */
|
|
1412
|
-
clear() {
|
|
1427
|
+
clear(force = false) {
|
|
1428
|
+
if (this.awaitingConfirm && !force) return;
|
|
1413
1429
|
if (this.clearTimer) {
|
|
1414
1430
|
clearTimeout(this.clearTimer);
|
|
1415
1431
|
this.clearTimer = null;
|
|
1416
1432
|
}
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
const ref = this.currentLine;
|
|
1420
|
-
setTimeout(() => ref.remove(), 750);
|
|
1421
|
-
this.currentLine = null;
|
|
1422
|
-
}
|
|
1433
|
+
this._removeCurrentLine(force);
|
|
1434
|
+
this.awaitingConfirm = false;
|
|
1423
1435
|
}
|
|
1424
1436
|
/** Remove all DOM. */
|
|
1425
1437
|
destroy() {
|
|
1426
1438
|
var _a2;
|
|
1427
|
-
this.clear();
|
|
1439
|
+
this.clear(true);
|
|
1428
1440
|
(_a2 = this.host) == null ? void 0 : _a2.remove();
|
|
1429
1441
|
this.host = null;
|
|
1430
1442
|
this.shadow = null;
|
|
@@ -1753,6 +1765,7 @@ class ThreeRenderer {
|
|
|
1753
1765
|
this._greetingOverlay = null;
|
|
1754
1766
|
this._trailParticles = [];
|
|
1755
1767
|
this._ambientParticles = [];
|
|
1768
|
+
this._lastAmbientSpawnAt = 0;
|
|
1756
1769
|
this._revealParticles = [];
|
|
1757
1770
|
this._disposed = false;
|
|
1758
1771
|
this._interactiveEgg = null;
|
|
@@ -2119,32 +2132,43 @@ class ThreeRenderer {
|
|
|
2119
2132
|
}
|
|
2120
2133
|
}
|
|
2121
2134
|
}
|
|
2122
|
-
/** Spawn
|
|
2123
|
-
showProgressParticles(progress) {
|
|
2135
|
+
/** Spawn ambient particles to show stage progress. */
|
|
2136
|
+
showProgressParticles(progress, source = "default") {
|
|
2124
2137
|
if (!this.THREE || !this.scene || progress < 0.05) return;
|
|
2125
2138
|
const T = this.THREE;
|
|
2126
|
-
|
|
2127
|
-
const
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
Math.random() * Math.PI
|
|
2138
|
-
Math.random() * Math.
|
|
2139
|
-
Math.
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2139
|
+
const now = performance.now();
|
|
2140
|
+
const isRhythm = source === "rhythm";
|
|
2141
|
+
if (isRhythm) {
|
|
2142
|
+
const minGap = Math.max(80, 180 - progress * 120);
|
|
2143
|
+
if (now - this._lastAmbientSpawnAt < minGap) return;
|
|
2144
|
+
} else if (Math.random() > progress * 0.3) {
|
|
2145
|
+
return;
|
|
2146
|
+
}
|
|
2147
|
+
this._lastAmbientSpawnAt = now;
|
|
2148
|
+
const spawnCount = isRhythm && progress > 0.6 ? 2 : 1;
|
|
2149
|
+
for (let i = 0; i < spawnCount; i++) {
|
|
2150
|
+
const angle = Math.random() * Math.PI * 2;
|
|
2151
|
+
const radius = isRhythm ? 1.1 + Math.random() * 1.8 : 2 + Math.random() * 2;
|
|
2152
|
+
const x = Math.cos(angle) * radius;
|
|
2153
|
+
const y = isRhythm ? -2.8 - Math.random() * 0.9 : -2 + Math.random() * 4;
|
|
2154
|
+
const size = isRhythm ? 0.03 + Math.random() * 0.03 : 0.02 + Math.random() * 0.025;
|
|
2155
|
+
const geo = this._createMiniEggGeo(T, size);
|
|
2156
|
+
const mat = this._createMiniEggMat(T, 0);
|
|
2157
|
+
const p = new T.Mesh(geo, mat);
|
|
2158
|
+
p.position.set(x, y, -1 + Math.random() * 0.5);
|
|
2159
|
+
p.rotation.set(
|
|
2160
|
+
Math.random() * Math.PI,
|
|
2161
|
+
Math.random() * Math.PI,
|
|
2162
|
+
Math.random() * Math.PI
|
|
2163
|
+
);
|
|
2164
|
+
this.scene.add(p);
|
|
2165
|
+
this._ambientParticles.push({
|
|
2166
|
+
mesh: p,
|
|
2167
|
+
life: isRhythm ? 1.25 : 1,
|
|
2168
|
+
vy: isRhythm ? 0.45 + Math.random() * 0.35 : 0.2 + Math.random() * 0.3,
|
|
2169
|
+
fadeIn: true
|
|
2170
|
+
});
|
|
2171
|
+
}
|
|
2148
2172
|
if (this._ambientParticles.length > 60) {
|
|
2149
2173
|
const old = this._ambientParticles.shift();
|
|
2150
2174
|
if (old) {
|
|
@@ -4569,6 +4593,8 @@ class StillnessStage {
|
|
|
4569
4593
|
this._attempts = 1;
|
|
4570
4594
|
this.input.resetPhases();
|
|
4571
4595
|
this.input.resetCounts();
|
|
4596
|
+
this.bus.emit("narrative:clear");
|
|
4597
|
+
await this._wait(850);
|
|
4572
4598
|
this._introPlayed = false;
|
|
4573
4599
|
const introLines = this.script.stage1Intro;
|
|
4574
4600
|
for (let i = 0; i < introLines.length; i++) {
|
|
@@ -4663,6 +4689,8 @@ class MotionStage {
|
|
|
4663
4689
|
this._attempts = 1;
|
|
4664
4690
|
this.input.resetPhases();
|
|
4665
4691
|
this.input.resetCounts();
|
|
4692
|
+
this.bus.emit("narrative:clear");
|
|
4693
|
+
await this._wait(850);
|
|
4666
4694
|
this._introPlayed = false;
|
|
4667
4695
|
const introLines = this.script.stage2Intro;
|
|
4668
4696
|
for (let i = 0; i < introLines.length; i++) {
|
|
@@ -4762,10 +4790,11 @@ class RhythmStage {
|
|
|
4762
4790
|
this._totalCycles = 0;
|
|
4763
4791
|
this._lastPhaseCount = 0;
|
|
4764
4792
|
this._bestAccuracy = 0;
|
|
4765
|
-
this.
|
|
4766
|
-
this.
|
|
4767
|
-
this.
|
|
4768
|
-
this.
|
|
4793
|
+
this._lastGuideTime = 0;
|
|
4794
|
+
this.IDEAL_MOVE_MIN = 900;
|
|
4795
|
+
this.IDEAL_MOVE_MAX = 4200;
|
|
4796
|
+
this.IDEAL_PAUSE_MIN = 600;
|
|
4797
|
+
this.IDEAL_PAUSE_MAX = 2800;
|
|
4769
4798
|
this.config = config;
|
|
4770
4799
|
this.script = script;
|
|
4771
4800
|
this.input = input;
|
|
@@ -4776,8 +4805,11 @@ class RhythmStage {
|
|
|
4776
4805
|
this._attempts = 1;
|
|
4777
4806
|
this._goodCycles = 0;
|
|
4778
4807
|
this._totalCycles = 0;
|
|
4808
|
+
this.input.configurePhaseDetection({ stillThresholdMs: 450, minPhaseMs: 350 });
|
|
4779
4809
|
this.input.resetPhases();
|
|
4780
4810
|
this.input.resetCounts();
|
|
4811
|
+
this.bus.emit("narrative:clear");
|
|
4812
|
+
await this._wait(850);
|
|
4781
4813
|
this._introPlayed = false;
|
|
4782
4814
|
const introLines = this.script.stage3Intro;
|
|
4783
4815
|
for (let i = 0; i < introLines.length; i++) {
|
|
@@ -4793,6 +4825,7 @@ class RhythmStage {
|
|
|
4793
4825
|
this.input.resetPhases();
|
|
4794
4826
|
this._lastPhaseCount = this.input.phases.length;
|
|
4795
4827
|
this._introPlayed = true;
|
|
4828
|
+
this._lastGuideTime = Date.now();
|
|
4796
4829
|
}
|
|
4797
4830
|
update(_dt) {
|
|
4798
4831
|
if (this._status === "complete" || !this._introPlayed) return this._status;
|
|
@@ -4807,7 +4840,7 @@ class RhythmStage {
|
|
|
4807
4840
|
if (isGood) {
|
|
4808
4841
|
this._goodCycles++;
|
|
4809
4842
|
} else {
|
|
4810
|
-
this._goodCycles = Math.max(0, this._goodCycles -
|
|
4843
|
+
this._goodCycles = Math.max(0, this._goodCycles - 0.5);
|
|
4811
4844
|
this._showReaction();
|
|
4812
4845
|
}
|
|
4813
4846
|
this._lastPhaseCount += 2;
|
|
@@ -4819,7 +4852,17 @@ class RhythmStage {
|
|
|
4819
4852
|
if (accuracy > this._bestAccuracy) this._bestAccuracy = accuracy;
|
|
4820
4853
|
const progress = Math.min(1, this._goodCycles / requiredCycles);
|
|
4821
4854
|
this.bus.emit("stage:progress", progress);
|
|
4822
|
-
this.bus.emit("rhythm:breathe", {
|
|
4855
|
+
this.bus.emit("rhythm:breathe", {
|
|
4856
|
+
accuracy,
|
|
4857
|
+
isMoving: this.input.snapshot.isMoving,
|
|
4858
|
+
progress,
|
|
4859
|
+
moveDuration: this.input.moveDuration,
|
|
4860
|
+
stillDuration: this.input.stillDuration
|
|
4861
|
+
});
|
|
4862
|
+
if (accuracy === 0 && Date.now() - this._lastGuideTime > 12e3) {
|
|
4863
|
+
this._lastGuideTime = Date.now();
|
|
4864
|
+
this._showReaction();
|
|
4865
|
+
}
|
|
4823
4866
|
if (this._goodCycles >= requiredCycles) {
|
|
4824
4867
|
this._status = "complete";
|
|
4825
4868
|
this.bus.emit("stage:progress", 1);
|
|
@@ -4829,6 +4872,7 @@ class RhythmStage {
|
|
|
4829
4872
|
return this._status;
|
|
4830
4873
|
}
|
|
4831
4874
|
cleanup() {
|
|
4875
|
+
this.input.resetPhaseDetection();
|
|
4832
4876
|
}
|
|
4833
4877
|
getResult() {
|
|
4834
4878
|
return {
|
|
@@ -4848,7 +4892,7 @@ class RhythmStage {
|
|
|
4848
4892
|
}
|
|
4849
4893
|
_showReaction() {
|
|
4850
4894
|
const now = Date.now();
|
|
4851
|
-
if (now - this._lastNarrativeTime >
|
|
4895
|
+
if (now - this._lastNarrativeTime > 12e3) {
|
|
4852
4896
|
this._lastNarrativeTime = now;
|
|
4853
4897
|
const reactions = this.script.stage3Reactions;
|
|
4854
4898
|
const line = reactions[this._narrativeIndex % reactions.length];
|
|
@@ -4964,6 +5008,7 @@ class PageBreather {
|
|
|
4964
5008
|
this._targetIntensity = 0;
|
|
4965
5009
|
this._rafId = 0;
|
|
4966
5010
|
this._overlay = null;
|
|
5011
|
+
this._label = null;
|
|
4967
5012
|
this._startTime = 0;
|
|
4968
5013
|
this._isUserMoving = false;
|
|
4969
5014
|
this._inSync = false;
|
|
@@ -4979,9 +5024,16 @@ class PageBreather {
|
|
|
4979
5024
|
const shouldMove = phase < 0.5;
|
|
4980
5025
|
this._inSync = this._accuracy > 0 && shouldMove === this._isUserMoving;
|
|
4981
5026
|
const baseOpacity = wave * 0.85;
|
|
4982
|
-
const syncBonus = this._inSync ? 0.
|
|
4983
|
-
const opacity = this._intensity * (baseOpacity + (1 - wave) * 0.
|
|
4984
|
-
this._overlay.style.opacity = String(Math.min(
|
|
5027
|
+
const syncBonus = this._inSync ? 0.22 : 0;
|
|
5028
|
+
const opacity = this._intensity * (0.18 + baseOpacity + (1 - wave) * 0.12 + syncBonus);
|
|
5029
|
+
this._overlay.style.opacity = String(Math.min(0.9, opacity));
|
|
5030
|
+
this._overlay.style.transform = `scale(${1 + wave * 0.015})`;
|
|
5031
|
+
if (this._label) {
|
|
5032
|
+
this._label.textContent = shouldMove ? "In" : "Out";
|
|
5033
|
+
this._label.style.opacity = shouldMove === this._isUserMoving ? "0.98" : "0.82";
|
|
5034
|
+
this._label.style.boxShadow = this._inSync ? "0 0 28px rgba(212,165,80,0.4)" : "0 0 20px rgba(255,255,255,0.08)";
|
|
5035
|
+
this._label.style.borderColor = this._inSync ? "rgba(212,165,80,0.55)" : "rgba(255,255,255,0.12)";
|
|
5036
|
+
}
|
|
4985
5037
|
};
|
|
4986
5038
|
}
|
|
4987
5039
|
start() {
|
|
@@ -4998,31 +5050,56 @@ class PageBreather {
|
|
|
4998
5050
|
"pointer-events:none",
|
|
4999
5051
|
"z-index:999980",
|
|
5000
5052
|
"opacity:0",
|
|
5001
|
-
"background:radial-gradient(ellipse at center,
|
|
5053
|
+
"background:radial-gradient(ellipse at center, rgba(255,255,255,0.03) 0%, rgba(255,255,255,0.02) 24%, rgba(8,12,22,0.18) 46%, rgba(4,6,12,0.82) 100%)",
|
|
5002
5054
|
"transition:opacity 0.3s ease"
|
|
5003
5055
|
].join(";");
|
|
5004
5056
|
document.body.appendChild(el);
|
|
5005
5057
|
this._overlay = el;
|
|
5058
|
+
const label = document.createElement("div");
|
|
5059
|
+
label.style.cssText = [
|
|
5060
|
+
"position:fixed",
|
|
5061
|
+
"left:50%",
|
|
5062
|
+
"top:18%",
|
|
5063
|
+
"transform:translateX(-50%)",
|
|
5064
|
+
"pointer-events:none",
|
|
5065
|
+
"z-index:999981",
|
|
5066
|
+
"padding:8px 14px",
|
|
5067
|
+
"border-radius:999px",
|
|
5068
|
+
"font-family:Georgia, Times New Roman, serif",
|
|
5069
|
+
"font-size:12px",
|
|
5070
|
+
"letter-spacing:0.12em",
|
|
5071
|
+
"text-transform:uppercase",
|
|
5072
|
+
"color:rgba(255,248,232,0.95)",
|
|
5073
|
+
"background:rgba(8,10,18,0.36)",
|
|
5074
|
+
"border:1px solid rgba(255,255,255,0.12)",
|
|
5075
|
+
"box-shadow:0 0 20px rgba(255,255,255,0.08)",
|
|
5076
|
+
"opacity:0.78"
|
|
5077
|
+
].join(";");
|
|
5078
|
+
label.textContent = "In";
|
|
5079
|
+
document.body.appendChild(label);
|
|
5080
|
+
this._label = label;
|
|
5006
5081
|
this._tick();
|
|
5007
5082
|
}
|
|
5008
5083
|
update(accuracy, isMoving) {
|
|
5009
5084
|
if (!this._active) return;
|
|
5010
5085
|
this._isUserMoving = isMoving;
|
|
5011
5086
|
this._accuracy = accuracy;
|
|
5012
|
-
const raw = Math.max(0, Math.min(1, (accuracy - 0.
|
|
5013
|
-
this._targetIntensity = 0.
|
|
5087
|
+
const raw = Math.max(0, Math.min(1, (accuracy - 0.02) / 0.45));
|
|
5088
|
+
this._targetIntensity = 0.68 + raw * 0.32;
|
|
5014
5089
|
}
|
|
5015
5090
|
/** Whether the user is currently in sync with the breathing rhythm. */
|
|
5016
5091
|
isInSync() {
|
|
5017
5092
|
return this._inSync;
|
|
5018
5093
|
}
|
|
5019
5094
|
stop() {
|
|
5020
|
-
var _a2;
|
|
5095
|
+
var _a2, _b2;
|
|
5021
5096
|
if (!this._active) return;
|
|
5022
5097
|
this._active = false;
|
|
5023
5098
|
cancelAnimationFrame(this._rafId);
|
|
5024
5099
|
(_a2 = this._overlay) == null ? void 0 : _a2.remove();
|
|
5025
5100
|
this._overlay = null;
|
|
5101
|
+
(_b2 = this._label) == null ? void 0 : _b2.remove();
|
|
5102
|
+
this._label = null;
|
|
5026
5103
|
this._intensity = 0;
|
|
5027
5104
|
this._targetIntensity = 0;
|
|
5028
5105
|
this._inSync = false;
|
|
@@ -5116,7 +5193,7 @@ class GameController {
|
|
|
5116
5193
|
});
|
|
5117
5194
|
this.bus.on("narrative:clear", () => {
|
|
5118
5195
|
var _a3;
|
|
5119
|
-
return (_a3 = this.narrative) == null ? void 0 : _a3.clear();
|
|
5196
|
+
return (_a3 = this.narrative) == null ? void 0 : _a3.clear(true);
|
|
5120
5197
|
});
|
|
5121
5198
|
this.bus.on("egg:reveal", (index) => this._handleEggReveal(index));
|
|
5122
5199
|
this.bus.on("stage:progress", (p) => this._handleStageProgress(p));
|
|
@@ -5128,8 +5205,11 @@ class GameController {
|
|
|
5128
5205
|
var _a3, _b3;
|
|
5129
5206
|
(_a3 = this.eggRenderer) == null ? void 0 : _a3.setBreathIntensity(data.accuracy);
|
|
5130
5207
|
(_b3 = this.pageBreather) == null ? void 0 : _b3.update(data.accuracy, data.isMoving);
|
|
5131
|
-
|
|
5132
|
-
|
|
5208
|
+
const rhythmSignal = Math.max(data.accuracy, data.progress * 0.75);
|
|
5209
|
+
const hasLiveCycleSignal = data.moveDuration > 700 || data.stillDuration > 700;
|
|
5210
|
+
if ((rhythmSignal > 0.08 || hasLiveCycleSignal) && this.threeRenderer) {
|
|
5211
|
+
const liveSignal = hasLiveCycleSignal ? 0.2 : 0;
|
|
5212
|
+
this.threeRenderer.showProgressParticles(Math.max(0.35, 0.45 + Math.max(rhythmSignal, liveSignal) * 0.55), "rhythm");
|
|
5133
5213
|
} else if (this.threeRenderer) {
|
|
5134
5214
|
this.threeRenderer.fadeOutAmbientParticles();
|
|
5135
5215
|
}
|
|
@@ -5493,7 +5573,7 @@ class GameController {
|
|
|
5493
5573
|
(_d = this.narrative) == null ? void 0 : _d.showCelebration(congrats[eggIndex] ?? "egg collected");
|
|
5494
5574
|
await this._wait(3500);
|
|
5495
5575
|
(_e = this.narrative) == null ? void 0 : _e.clear();
|
|
5496
|
-
await this._wait(
|
|
5576
|
+
await this._wait(900);
|
|
5497
5577
|
if (eggIndex < 2) {
|
|
5498
5578
|
if (eggIndex === 0) {
|
|
5499
5579
|
this.fsm.transitionTo("stage2-intro");
|