@gamebob/axon-surge 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,28 +1,28 @@
1
- class G {
1
+ class B {
2
2
  listeners = /* @__PURE__ */ new Map();
3
- on(t, i) {
4
- return this.listeners.has(t) || this.listeners.set(t, /* @__PURE__ */ new Set()), this.listeners.get(t).add(i), () => this.off(t, i);
3
+ on(t, e) {
4
+ return this.listeners.has(t) || this.listeners.set(t, /* @__PURE__ */ new Set()), this.listeners.get(t).add(e), () => this.off(t, e);
5
5
  }
6
- off(t, i) {
7
- const e = this.listeners.get(t);
8
- e && e.delete(i);
6
+ off(t, e) {
7
+ const i = this.listeners.get(t);
8
+ i && i.delete(e);
9
9
  }
10
- emit(t, i) {
11
- const e = this.listeners.get(t);
12
- e && e.forEach((s) => s(i));
10
+ emit(t, e) {
11
+ const i = this.listeners.get(t);
12
+ i && i.forEach((s) => s(e));
13
13
  }
14
14
  clear() {
15
15
  this.listeners.clear();
16
16
  }
17
17
  }
18
- class B {
18
+ class H {
19
19
  animationFrameId = null;
20
20
  lastTime = 0;
21
21
  isRunning = !1;
22
22
  updateCallback;
23
23
  renderCallback;
24
- constructor(t, i) {
25
- this.updateCallback = t, this.renderCallback = i;
24
+ constructor(t, e) {
25
+ this.updateCallback = t, this.renderCallback = e;
26
26
  }
27
27
  start() {
28
28
  this.isRunning || (this.isRunning = !0, this.lastTime = performance.now(), this.tick = this.tick.bind(this), this.animationFrameId = requestAnimationFrame(this.tick));
@@ -32,35 +32,35 @@ class B {
32
32
  }
33
33
  tick(t) {
34
34
  if (!this.isRunning) return;
35
- const i = Math.min((t - this.lastTime) / 1e3, 0.1);
36
- this.lastTime = t, this.updateCallback(i), this.renderCallback(), this.animationFrameId = requestAnimationFrame(this.tick);
35
+ const e = Math.min((t - this.lastTime) / 1e3, 0.1);
36
+ this.lastTime = t, this.updateCallback(e), this.renderCallback(), this.animationFrameId = requestAnimationFrame(this.tick);
37
37
  }
38
38
  }
39
- class U {
39
+ class K {
40
40
  position;
41
- radius = 44;
41
+ radius = 32;
42
42
  integrity = 3;
43
43
  maxIntegrity = 3;
44
44
  pulsePhase = 0;
45
45
  organicSeed;
46
- constructor(t, i) {
47
- this.position = { x: t, y: i }, this.organicSeed = Math.random() * 100;
46
+ constructor(t, e) {
47
+ this.position = { x: t, y: e }, this.organicSeed = Math.random() * 100;
48
48
  }
49
49
  update(t) {
50
50
  this.pulsePhase += t * 2.8;
51
51
  }
52
52
  getMembraneRadius(t) {
53
- const i = Math.sin(t * 5 + this.pulsePhase * 1.5 + this.organicSeed) * 5, e = Math.cos(t * 3 - this.pulsePhase * 2.2) * 3, s = Math.sin(t * 7 + this.pulsePhase * 3.1) * 2;
54
- return this.radius + i + e + s;
53
+ const e = Math.sin(t * 5 + this.pulsePhase * 1.5 + this.organicSeed) * 4, i = Math.cos(t * 3 - this.pulsePhase * 2.2) * 2.5, s = Math.sin(t * 7 + this.pulsePhase * 3.1) * 1.5;
54
+ return this.radius + e + i + s;
55
55
  }
56
56
  takeDamage() {
57
57
  return this.integrity > 0 ? (this.integrity -= 1, !0) : !1;
58
58
  }
59
- reset(t, i) {
60
- this.position = { x: t, y: i }, this.integrity = this.maxIntegrity, this.pulsePhase = 0;
59
+ reset(t, e) {
60
+ this.position = { x: t, y: e }, this.integrity = this.maxIntegrity, this.pulsePhase = 0;
61
61
  }
62
62
  }
63
- class P {
63
+ class O {
64
64
  id;
65
65
  position = { x: 0, y: 0 };
66
66
  velocity = { x: 0, y: 0 };
@@ -73,7 +73,8 @@ class P {
73
73
  rotation = 0;
74
74
  color = "#ff2a5f";
75
75
  strategy = null;
76
- hitRadiusPadding = 0.5;
76
+ hitRadiusPadding = 1.2;
77
+ maxSpeed = 200;
77
78
  isDying = !1;
78
79
  deathType = "none";
79
80
  deathTimer = 0;
@@ -97,14 +98,23 @@ class P {
97
98
  this.deathTimer += t, this.deathTimer >= this.maxDeathTimer && (this.active = !1, this.isDying = !1);
98
99
  return;
99
100
  }
100
- this.isGrabbed || (this.position.x += this.velocity.x * t, this.position.y += this.velocity.y * t, (this.velocity.x !== 0 || this.velocity.y !== 0) && (this.rotation = Math.atan2(this.velocity.y, this.velocity.x)));
101
+ if (!this.isGrabbed) {
102
+ if (!this.isThrown && this.maxSpeed > 0) {
103
+ const e = Math.hypot(this.velocity.x, this.velocity.y);
104
+ if (e > this.maxSpeed) {
105
+ const i = this.maxSpeed / e;
106
+ this.velocity.x *= i, this.velocity.y *= i;
107
+ }
108
+ }
109
+ this.position.x += this.velocity.x * t, this.position.y += this.velocity.y * t, (this.velocity.x !== 0 || this.velocity.y !== 0) && (this.rotation = Math.atan2(this.velocity.y, this.velocity.x));
110
+ }
101
111
  }
102
112
  }
103
113
  reset() {
104
- this.active = !1, this.isGrabbed = !1, this.isThrown = !1, this.wasManipulated = !1, this.isDying = !1, this.deathType = "none", this.deathTimer = 0, this.sliceAngle = 0, this.position = { x: 0, y: 0 }, this.velocity = { x: 0, y: 0 }, this.rotation = 0, this.strategy = null;
114
+ this.active = !1, this.isGrabbed = !1, this.isThrown = !1, this.wasManipulated = !1, this.isDying = !1, this.deathType = "none", this.deathTimer = 0, this.sliceAngle = 0, this.position = { x: 0, y: 0 }, this.velocity = { x: 0, y: 0 }, this.rotation = 0, this.strategy = null, this.maxSpeed = 200;
105
115
  }
106
116
  }
107
- class H {
117
+ class W {
108
118
  pointerPosition = { x: 0, y: 0 };
109
119
  isPointerDown = !1;
110
120
  grabbedEnemy = null;
@@ -114,18 +124,18 @@ class H {
114
124
  constructor(t) {
115
125
  this.canvas = t, this.bindEvents();
116
126
  }
117
- updatePointerPos(t, i) {
118
- const e = this.canvas.getBoundingClientRect(), s = performance.now() / 1e3;
127
+ updatePointerPos(t, e) {
128
+ const i = this.canvas.getBoundingClientRect(), s = i.width > 0 ? this.canvas.width / i.width : 1, a = i.height > 0 ? this.canvas.height / i.height : 1, l = performance.now() / 1e3;
119
129
  this.pointerPosition = {
120
- x: t - e.left,
121
- y: i - e.top
130
+ x: (t - i.left) * s,
131
+ y: (e - i.top) * a
122
132
  }, this.pointerHistory.push({
123
133
  x: this.pointerPosition.x,
124
134
  y: this.pointerPosition.y,
125
- time: s
135
+ time: l
126
136
  });
127
- const a = s - 0.08;
128
- this.pointerHistory = this.pointerHistory.filter((c) => c.time >= a), this.grabbedEnemy && (this.grabbedEnemy.position = { ...this.pointerPosition });
137
+ const r = l - 0.08;
138
+ this.pointerHistory = this.pointerHistory.filter((n) => n.time >= r), this.grabbedEnemy && (this.grabbedEnemy.position = { ...this.pointerPosition });
129
139
  }
130
140
  bindEvents() {
131
141
  this.canvas.addEventListener("mousemove", (t) => {
@@ -134,17 +144,25 @@ class H {
134
144
  t.button === 0 && (this.isPointerDown = !0, this.pointerHistory = [], this.updatePointerPos(t.clientX, t.clientY));
135
145
  }), this.canvas.addEventListener("mouseup", (t) => {
136
146
  t.button === 0 && (this.isPointerDown = !1);
137
- }), this.canvas.addEventListener("touchstart", (t) => {
138
- if (t.touches.length > 0) {
139
- const i = t.touches[0];
140
- this.isPointerDown = !0, this.pointerHistory = [], this.updatePointerPos(i.clientX, i.clientY);
141
- }
142
- }, { passive: !0 }), this.canvas.addEventListener("touchmove", (t) => {
143
- if (t.touches.length > 0) {
144
- const i = t.touches[0];
145
- this.updatePointerPos(i.clientX, i.clientY);
146
- }
147
- }, { passive: !0 }), this.canvas.addEventListener("touchend", () => {
147
+ }), this.canvas.addEventListener(
148
+ "touchstart",
149
+ (t) => {
150
+ if (t.touches.length > 0) {
151
+ const e = t.touches[0];
152
+ this.isPointerDown = !0, this.pointerHistory = [], this.updatePointerPos(e.clientX, e.clientY);
153
+ }
154
+ },
155
+ { passive: !0 }
156
+ ), this.canvas.addEventListener(
157
+ "touchmove",
158
+ (t) => {
159
+ if (t.touches.length > 0) {
160
+ const e = t.touches[0];
161
+ this.updatePointerPos(e.clientX, e.clientY);
162
+ }
163
+ },
164
+ { passive: !0 }
165
+ ), this.canvas.addEventListener("touchend", () => {
148
166
  this.isPointerDown = !1;
149
167
  }), this.canvas.addEventListener("touchcancel", () => {
150
168
  this.isPointerDown = !1;
@@ -152,13 +170,14 @@ class H {
152
170
  t.preventDefault();
153
171
  });
154
172
  }
155
- tryGrab(t) {
173
+ tryGrab(t, e = !1) {
156
174
  if (this.grabbedEnemy) return this.grabbedEnemy;
157
- for (const i of t) {
158
- if (!i.active || i.isGrabbed || i.isThrown || i.wasManipulated) continue;
159
- const e = this.pointerPosition.x - i.position.x, s = this.pointerPosition.y - i.position.y;
160
- if (Math.hypot(e, s) <= i.getHitRadius())
161
- return i.isGrabbed = !0, this.grabbedEnemy = i, this.dragStart = { ...this.pointerPosition }, this.pointerHistory = [], i;
175
+ const i = e ? 50 : 20;
176
+ for (const s of t) {
177
+ if (!s.active || s.isGrabbed || s.isThrown || s.wasManipulated) continue;
178
+ const a = this.pointerPosition.x - s.position.x, l = this.pointerPosition.y - s.position.y;
179
+ if (Math.hypot(a, l) <= s.getHitRadius() + i)
180
+ return s.isGrabbed = !0, this.grabbedEnemy = s, this.dragStart = { ...this.pointerPosition }, this.pointerHistory = [], s;
162
181
  }
163
182
  return null;
164
183
  }
@@ -166,37 +185,40 @@ class H {
166
185
  if (!this.grabbedEnemy) return null;
167
186
  const t = this.grabbedEnemy;
168
187
  t.isGrabbed = !1, t.isThrown = !0, t.wasManipulated = !0;
169
- const e = performance.now() / 1e3 - 0.08, s = this.pointerHistory.filter((n) => n.time >= e);
170
- let a = 0, c = 0;
188
+ const i = performance.now() / 1e3 - 0.08, s = this.pointerHistory.filter((n) => n.time >= i);
189
+ let a = 0, l = 0;
171
190
  if (s.length >= 2) {
172
- const n = s[0], o = s[s.length - 1], r = Math.max(0.01, o.time - n.time);
173
- a = (o.x - n.x) / r, c = (o.y - n.y) / r;
191
+ const n = s[0], o = s[s.length - 1], h = Math.max(0.01, o.time - n.time);
192
+ a = (o.x - n.x) / h, l = (o.y - n.y) / h;
174
193
  }
175
- const h = Math.hypot(a, c);
176
- if (h > 30) {
177
- const o = Math.min(h * 1.15, 2500), r = Math.atan2(c, a);
194
+ const r = Math.hypot(a, l);
195
+ if (r > 30) {
196
+ const o = Math.min(r * 1.15, 2500), h = Math.atan2(l, a);
178
197
  t.velocity = {
179
- x: Math.cos(r) * o,
180
- y: Math.sin(r) * o
198
+ x: Math.cos(h) * o,
199
+ y: Math.sin(h) * o
181
200
  };
182
201
  } else if (this.dragStart) {
183
- const n = t.position.x - this.dragStart.x, o = t.position.y - this.dragStart.y, r = Math.hypot(n, o);
184
- if (r > 5) {
185
- const l = Math.atan2(o, n), p = Math.min(r * 4, 600);
202
+ const n = t.position.x - this.dragStart.x, o = t.position.y - this.dragStart.y, h = Math.hypot(n, o);
203
+ if (h > 5) {
204
+ const c = Math.atan2(o, n), u = Math.min(h * 4, 600);
186
205
  t.velocity = {
187
- x: Math.cos(l) * p,
188
- y: Math.sin(l) * p
206
+ x: Math.cos(c) * u,
207
+ y: Math.sin(c) * u
189
208
  };
190
209
  } else
191
210
  t.velocity = { x: 0, y: 0 }, t.isThrown = !1;
192
211
  }
193
212
  return this.grabbedEnemy = null, this.dragStart = null, this.pointerHistory = [], t;
194
213
  }
214
+ forceRelease() {
215
+ this.grabbedEnemy && (this.grabbedEnemy.isGrabbed = !1, this.grabbedEnemy.isThrown = !1, this.grabbedEnemy.wasManipulated = !1, this.grabbedEnemy = null), this.dragStart = null, this.pointerHistory = [];
216
+ }
195
217
  reset() {
196
218
  this.grabbedEnemy = null, this.dragStart = null, this.pointerHistory = [], this.isPointerDown = !1;
197
219
  }
198
220
  }
199
- class K {
221
+ class V {
200
222
  cellSize;
201
223
  grid = /* @__PURE__ */ new Map();
202
224
  constructor(t = 100) {
@@ -206,21 +228,21 @@ class K {
206
228
  this.grid.clear();
207
229
  }
208
230
  insert(t) {
209
- const i = Math.floor((t.position.x - t.radius) / this.cellSize), e = Math.floor((t.position.x + t.radius) / this.cellSize), s = Math.floor((t.position.y - t.radius) / this.cellSize), a = Math.floor((t.position.y + t.radius) / this.cellSize);
210
- for (let c = i; c <= e; c++)
211
- for (let h = s; h <= a; h++) {
212
- const n = `${c}:${h}`;
231
+ const e = Math.floor((t.position.x - t.radius) / this.cellSize), i = Math.floor((t.position.x + t.radius) / this.cellSize), s = Math.floor((t.position.y - t.radius) / this.cellSize), a = Math.floor((t.position.y + t.radius) / this.cellSize);
232
+ for (let l = e; l <= i; l++)
233
+ for (let r = s; r <= a; r++) {
234
+ const n = `${l}:${r}`;
213
235
  this.grid.has(n) || this.grid.set(n, /* @__PURE__ */ new Set()), this.grid.get(n).add(t);
214
236
  }
215
237
  }
216
- getNearby(t, i) {
217
- const e = /* @__PURE__ */ new Set(), s = Math.floor((t.x - i) / this.cellSize), a = Math.floor((t.x + i) / this.cellSize), c = Math.floor((t.y - i) / this.cellSize), h = Math.floor((t.y + i) / this.cellSize);
238
+ getNearby(t, e) {
239
+ const i = /* @__PURE__ */ new Set(), s = Math.floor((t.x - e) / this.cellSize), a = Math.floor((t.x + e) / this.cellSize), l = Math.floor((t.y - e) / this.cellSize), r = Math.floor((t.y + e) / this.cellSize);
218
240
  for (let n = s; n <= a; n++)
219
- for (let o = c; o <= h; o++) {
220
- const r = `${n}:${o}`, l = this.grid.get(r);
221
- l && l.forEach((p) => e.add(p));
241
+ for (let o = l; o <= r; o++) {
242
+ const h = `${n}:${o}`, c = this.grid.get(h);
243
+ c && c.forEach((u) => i.add(u));
222
244
  }
223
- return e;
245
+ return i;
224
246
  }
225
247
  }
226
248
  class F {
@@ -236,23 +258,23 @@ class F {
236
258
  triggerFlash(t = 0.4) {
237
259
  this.flashAlpha = t;
238
260
  }
239
- triggerScreenShake(t, i = 1) {
240
- const s = 10 + Math.min(i * 3, 30), a = Math.hypot(t.x, t.y) || 1;
261
+ triggerScreenShake(t, e = 1) {
262
+ const s = 10 + Math.min(e * 3, 30), a = Math.hypot(t.x, t.y) || 1;
241
263
  this.shakeVector = {
242
264
  x: t.x / a * s,
243
265
  y: t.y / a * s
244
266
  }, this.shakeIntensity = s, this.shakeTime = this.shakeDuration;
245
267
  }
246
- update(t, i, e) {
268
+ update(t, e, i) {
247
269
  this.hitstopTime > 0 && (this.hitstopTime -= t), this.shakeTime > 0 && (this.shakeTime -= t), this.flashAlpha > 0 && (this.flashAlpha = Math.max(0, this.flashAlpha - t * 4));
248
- for (let s = i.length - 1; s >= 0; s--) {
249
- const a = i[s];
250
- a && (a.lifetime += t, a.position.x += a.velocity.x * t, a.position.y += a.velocity.y * t, a.alpha = 1 - a.lifetime / a.maxLifetime, a.lifetime >= a.maxLifetime && i.splice(s, 1));
251
- }
252
270
  for (let s = e.length - 1; s >= 0; s--) {
253
271
  const a = e[s];
254
272
  a && (a.lifetime += t, a.position.x += a.velocity.x * t, a.position.y += a.velocity.y * t, a.alpha = 1 - a.lifetime / a.maxLifetime, a.lifetime >= a.maxLifetime && e.splice(s, 1));
255
273
  }
274
+ for (let s = i.length - 1; s >= 0; s--) {
275
+ const a = i[s];
276
+ a && (a.lifetime += t, a.position.x += a.velocity.x * t, a.position.y += a.velocity.y * t, a.alpha = 1 - a.lifetime / a.maxLifetime, a.lifetime >= a.maxLifetime && i.splice(s, 1));
277
+ }
256
278
  }
257
279
  getShakeOffset() {
258
280
  if (this.shakeTime <= 0) return { x: 0, y: 0 };
@@ -263,23 +285,29 @@ class F {
263
285
  };
264
286
  }
265
287
  }
266
- const I = {
288
+ const w = {
267
289
  es: {
268
290
  title: "AXON SURGE",
269
291
  startButton: "INICIAR ENLACE",
270
292
  waveLabel: "NIVEL",
271
293
  scoreLabel: "PUNTAJE",
272
- settingsTitle: "CONFIGURACION",
294
+ settingsTitle: "CONFIGURACIÓN",
273
295
  languageLabel: "IDIOMA",
274
296
  themeLabel: "TEMA VISUAL",
275
- hapticsLabel: "VIBRACION / HAPTICOS",
297
+ hapticsLabel: "VIBRACIÓN / HÁPTICOS",
276
298
  hapticsOn: "ACTIVADO",
277
299
  hapticsOff: "DESACTIVADO",
278
300
  creditsJam: "Desarrollado para Mini Jam 216: Axon Surge",
279
301
  closeButton: "CERRAR",
280
302
  grabInstruction: "MANTÉN PULSADO PARA AGARRAR UN ENEMIGO",
281
303
  throwInstruction: "ARRASTRA Y SUELTA PARA LANZARLO",
282
- comboText: "¡MULTIKILL x{combo}!"
304
+ comboText: "¡MULTIKILL x{combo}!",
305
+ tutorialInstruction: "¡LANZA UN ENEMIGO CONTRA OTRO PARA HACERLOS CHOCAR!",
306
+ dontShowTutorialLabel: "No volver a mostrar el tutorial",
307
+ tutorialSettingLabel: "MOSTRAR TUTORIAL AL INICIAR",
308
+ tutorialStep1Text: "PASO 1: MANTÉN PULSADO EL ENEMIGO SEÑALADO",
309
+ tutorialStep2Text: "PASO 2: LÁNZALO CON IMPULSO HACIA EL OBJETIVO",
310
+ tutorialDragWarning: "¡LA MEJOR ESTRATEGIA ES LANZARLOS! LÁNZALO CON IMPULSO"
283
311
  },
284
312
  en: {
285
313
  title: "AXON SURGE",
@@ -296,7 +324,13 @@ const I = {
296
324
  closeButton: "CLOSE",
297
325
  grabInstruction: "HOLD TO GRAB AN ENEMY",
298
326
  throwInstruction: "DRAG AND RELEASE TO THROW",
299
- comboText: "MULTIKILL x{combo}!"
327
+ comboText: "MULTIKILL x{combo}!",
328
+ tutorialInstruction: "FLICK ONE ENEMY INTO ANOTHER TO COLLIDE THEM!",
329
+ dontShowTutorialLabel: "Do not show tutorial again",
330
+ tutorialSettingLabel: "SHOW TUTORIAL AT START",
331
+ tutorialStep1Text: "STEP 1: PRESS AND HOLD THE INDICATED ENEMY",
332
+ tutorialStep2Text: "STEP 2: FLICK TOWARD TARGET WITH SWIPE SPEED",
333
+ tutorialDragWarning: "THE BEST STRATEGY IS TO FLICK THEM! THROW WITH SWIPE SPEED"
300
334
  },
301
335
  fr: {
302
336
  title: "AXON SURGE",
@@ -313,7 +347,13 @@ const I = {
313
347
  closeButton: "FERMER",
314
348
  grabInstruction: "MAINTENEZ POUR SAISIR UN ENNEMI",
315
349
  throwInstruction: "GLISSEZ ET RELACHEZ POUR LANCER",
316
- comboText: "MULTIKILL x{combo} !"
350
+ comboText: "MULTIKILL x{combo} !",
351
+ tutorialInstruction: "LANCEZ UN ENNEMI CONTRE UN AUTRE POUR LES FAIRE COLLISIONNER !",
352
+ dontShowTutorialLabel: "Ne plus afficher le tutoriel",
353
+ tutorialSettingLabel: "AFFICHER LE TUTORIEL AU DEMARRAGE",
354
+ tutorialStep1Text: "ETAPE 1: MAINTENEZ L'ENNEMI INDIQUE",
355
+ tutorialStep2Text: "ETAPE 2: LANCEZ AVEC VITESSE VERS LA CIBLE",
356
+ tutorialDragWarning: "LA MEILLEURE STRATEGIE EST DE LES LANCER !"
317
357
  },
318
358
  de: {
319
359
  title: "AXON SURGE",
@@ -330,7 +370,13 @@ const I = {
330
370
  closeButton: "SCHLIESSEN",
331
371
  grabInstruction: "GEDRÜCKT HALTEN ZUM GREIFEN",
332
372
  throwInstruction: "ZIEHEN UND LOSLASSEN ZUM WERFEN",
333
- comboText: "MULTIKILL x{combo}!"
373
+ comboText: "MULTIKILL x{combo}!",
374
+ tutorialInstruction: "SCHLEUDERE EINEN FEIND IN EINEN ANDEREN!",
375
+ dontShowTutorialLabel: "Tutorial nicht mehr anzeigen",
376
+ tutorialSettingLabel: "TUTORIAL BEIM START ANZEIGEN",
377
+ tutorialStep1Text: "SCHRITT 1: HALTE DEN FEIND GEDRUECKT",
378
+ tutorialStep2Text: "SCHRITT 2: SCHLEUDERE MIT SCHWUNG AUF DAS ZIEL",
379
+ tutorialDragWarning: "DIE BESTE STRATEGIE IST ES SIE ZU SCHLEUDERN!"
334
380
  },
335
381
  it: {
336
382
  title: "AXON SURGE",
@@ -347,7 +393,13 @@ const I = {
347
393
  closeButton: "CHIUDI",
348
394
  grabInstruction: "TIENI PREMUTO PER AFFERRARE UN NEMICO",
349
395
  throwInstruction: "TRASCINA E RILASCIA PER LANCIARE",
350
- comboText: "MULTIKILL x{combo}!"
396
+ comboText: "MULTIKILL x{combo}!",
397
+ tutorialInstruction: "LANCIA UN NEMICO CONTRO UN ALTRO PER FARLI SCONTRARE!",
398
+ dontShowTutorialLabel: "Non mostrare più il tutorial",
399
+ tutorialSettingLabel: "MOSTRA TUTORIAL ALL'AVVIO",
400
+ tutorialStep1Text: "PASSO 1: TIENI PREMUTO IL NEMICO INDICATO",
401
+ tutorialStep2Text: "PASSO 2: LANCIA CON VELOCITA VERSO IL BERSAGLIO",
402
+ tutorialDragWarning: "LA STRATEGIA MIGLIORE E LANCIARLI!"
351
403
  },
352
404
  pt: {
353
405
  title: "AXON SURGE",
@@ -359,12 +411,18 @@ const I = {
359
411
  themeLabel: "TEMA VISUAL",
360
412
  hapticsLabel: "RESPOSTA TÁTIL",
361
413
  hapticsOn: "ATIVADO",
362
- hapticsOff: "DESATIVADO",
414
+ hapticsOff: "DESACTIVADO",
363
415
  creditsJam: "Desenvolvido para Mini Jam 216: Axon Surge",
364
416
  closeButton: "FECHAR",
365
417
  grabInstruction: "SEGURE PARA AGARRAR UM INIMIGO",
366
418
  throwInstruction: "ARRASTE E SOLTE PARA LANÇAR",
367
- comboText: "MULTIKILL x{combo}!"
419
+ comboText: "MULTIKILL x{combo}!",
420
+ tutorialInstruction: "LANCE UM INIMIGO CONTRA OUTRO PARA FAZÊ-LOS COLIDIR!",
421
+ dontShowTutorialLabel: "Não mostrar o tutorial novamente",
422
+ tutorialSettingLabel: "MOSTRAR TUTORIAL AO INICIAR",
423
+ tutorialStep1Text: "PASSO 1: SEGURE O INIMIGO INDICADO",
424
+ tutorialStep2Text: "PASSO 2: LANCE COM IMPULSO EM DIRECAO AO ALVO",
425
+ tutorialDragWarning: "A MELHOR ESTRATEGIA E LANCA-LOS!"
368
426
  },
369
427
  nl: {
370
428
  title: "AXON SURGE",
@@ -381,7 +439,13 @@ const I = {
381
439
  closeButton: "SLUITEN",
382
440
  grabInstruction: "HOUD INGEDRUKT OM EEN VIJAND TE PAKKEN",
383
441
  throwInstruction: "SLEEP EN LAAT LOS OM TE GOOIEN",
384
- comboText: "MULTIKILL x{combo}!"
442
+ comboText: "MULTIKILL x{combo}!",
443
+ tutorialInstruction: "GOOI EEN VIJAND TEGEN EEN ANDERE OM ZE TE LATEN BOTSINGEN!",
444
+ dontShowTutorialLabel: "Tutorial niet meer tonen",
445
+ tutorialSettingLabel: "TUTORIAL TONEN BIJ START",
446
+ tutorialStep1Text: "STAP 1: HOUD DE AANGEGEVEN VIJAND INGEDRUKT",
447
+ tutorialStep2Text: "STAP 2: GOOI MET SNELHEID NAAR HET DOEL",
448
+ tutorialDragWarning: "DE BESTE STRATEGIE IS OM ZE TE GOOIEN!"
385
449
  },
386
450
  sv: {
387
451
  title: "AXON SURGE",
@@ -398,7 +462,13 @@ const I = {
398
462
  closeButton: "STÄNG",
399
463
  grabInstruction: "HÅLL INNE FÖR ATT GREPPA EN FIENDE",
400
464
  throwInstruction: "DRA OCH SLÄPP FÖR ATT KASTA",
401
- comboText: "MULTIKILL x{combo}!"
465
+ comboText: "MULTIKILL x{combo}!",
466
+ tutorialInstruction: "KASTA EN FIENDE PÅ EN ANNAN FÖR ATT FÅ DEM ATT KOLLIDERA!",
467
+ dontShowTutorialLabel: "Visa inte självstudiekursen igen",
468
+ tutorialSettingLabel: "VISA TUTORIAL VID START",
469
+ tutorialStep1Text: "STEG 1: HÅLL INNE DEN ANGVIVNA FIENDEN",
470
+ tutorialStep2Text: "STEG 2: KASTA MED HASTIGHET MOT MÅLET",
471
+ tutorialDragWarning: "DEN BÄSTA STRATEGIN ÄR ATT KASTA DEM!"
402
472
  },
403
473
  pl: {
404
474
  title: "AXON SURGE",
@@ -415,7 +485,13 @@ const I = {
415
485
  closeButton: "ZAMKNIJ",
416
486
  grabInstruction: "PRZYTRZYMAJ, ABY CHWYCIĆ WROGA",
417
487
  throwInstruction: "PRZECIĄGNIJ I PUŚĆ, ABY RZUCIĆ",
418
- comboText: "MULTIKILL x{combo}!"
488
+ comboText: "MULTIKILL x{combo}!",
489
+ tutorialInstruction: "RZUĆ JEDNYM WROGIEM W DRUGIEGO, ABY JE ZDERZYĆ!",
490
+ dontShowTutorialLabel: "Nie pokazuj więcej samouczka",
491
+ tutorialSettingLabel: "POKAZUJ SAMOUCZEK PRZY STARTOWIE",
492
+ tutorialStep1Text: "KROK 1: PRZYTRZYMAJ WSKAZANEGO WROGA",
493
+ tutorialStep2Text: "KROK 2: RZUĆ Z PRĘDKOŚCIĄ W STRONĘ CELU",
494
+ tutorialDragWarning: "NAJLEPSZA STRATEGIA TO RZUCANIE NIMI!"
419
495
  },
420
496
  id: {
421
497
  title: "AXON SURGE",
@@ -432,7 +508,13 @@ const I = {
432
508
  closeButton: "TUTUP",
433
509
  grabInstruction: "TAHAN UNTUK MEMEGANG MUSUH",
434
510
  throwInstruction: "GESER DAN LEPAS UNTUK MELEMPAR",
435
- comboText: "MULTIKILL x{combo}!"
511
+ comboText: "MULTIKILL x{combo}!",
512
+ tutorialInstruction: "LEMPAR MUSUH KE MUSUH LAIN UNTUK MEMBENTURKAN MEREKA!",
513
+ dontShowTutorialLabel: "Jangan tampilkan tutorial lagi",
514
+ tutorialSettingLabel: "TAMPILKAN TUTORIAL SAAT MULA",
515
+ tutorialStep1Text: "LANGKAH 1: TAHAN MUSUH YANG DITUNJUK",
516
+ tutorialStep2Text: "LANGKAH 2: LEMPAR DENGAN KECEPATAN KE TARGET",
517
+ tutorialDragWarning: "STRATEGI TERBAIK ADALAH MELEMPAR MEREKA!"
436
518
  },
437
519
  tr: {
438
520
  title: "AXON SURGE",
@@ -449,7 +531,13 @@ const I = {
449
531
  closeButton: "KAPAT",
450
532
  grabInstruction: "DÜŞMANI YAKALAMAK İÇİN BASILI TUTUN",
451
533
  throwInstruction: "FIRLATMAK İÇİN SÜRÜKLEYİP BIRAKIN",
452
- comboText: "MULTIKILL x{combo}!"
534
+ comboText: "MULTIKILL x{combo}!",
535
+ tutorialInstruction: "ÇARPIŞTIRMAK İÇİN BİR DÜŞMANI DİĞERİNE FIRLATIN!",
536
+ dontShowTutorialLabel: "Eğitimi bir daha gösterme",
537
+ tutorialSettingLabel: "BAŞLANGIÇTA EĞİTİMİ GÖSTER",
538
+ tutorialStep1Text: "ADIM 1: GÖSTERİLEN DÜŞMANI BASILI TUTUN",
539
+ tutorialStep2Text: "ADIM 2: HEDEFE HIZLA FIRLATIN",
540
+ tutorialDragWarning: "EN İYİ STRATEJİ ONLARI FIRLATMAKTIR!"
453
541
  },
454
542
  ru: {
455
543
  title: "AXON SURGE",
@@ -466,7 +554,13 @@ const I = {
466
554
  closeButton: "ЗАКРЫТЬ",
467
555
  grabInstruction: "УДЕРЖИВАЙТЕ, ЧТОБЫ СХВАТИТЬ ВРАГА",
468
556
  throwInstruction: "ПЕРЕТАЩИТЕ И ОТПУСТИТЕ ДЛЯ БРОСКА",
469
- comboText: "МУЛЬТИКИЛЛ x{combo}!"
557
+ comboText: "МУЛЬТИКИЛЛ x{combo}!",
558
+ tutorialInstruction: "БРОСЬТЕ ОДНОГО ВРАГА В ДРУГОГО ДЛЯ СТОЛКНОВЕНИЯ!",
559
+ dontShowTutorialLabel: "Больше не показывать обучение",
560
+ tutorialSettingLabel: "ПОКАЗЫВАТЬ ОБУЧЕНИЕ ПРИ СТАРТЕ",
561
+ tutorialStep1Text: "ШАГ 1: УДЕРЖИВАЙТЕ УКАЗАННОГО ВРАГА",
562
+ tutorialStep2Text: "ШАГ 2: БРОСАЙТЕ С ИМПУЛЬСОМ В ЦЕЛЬ",
563
+ tutorialDragWarning: "ЛУЧШАЯ СТРАТЕГИЯ - БРОСАТЬ ИХ С ИМПУЛЬСОМ!"
470
564
  },
471
565
  ja: {
472
566
  title: "AXON SURGE",
@@ -483,7 +577,13 @@ const I = {
483
577
  closeButton: "閉じる",
484
578
  grabInstruction: "長押しで敵をキャッチ",
485
579
  throwInstruction: "ドラッグ&リリースで投げる",
486
- comboText: "マルチキル x{combo}!"
580
+ comboText: "マルチキル x{combo}!",
581
+ tutorialInstruction: "敵を弾いて別の敵にぶつけよう!",
582
+ dontShowTutorialLabel: "チュートリアルを再表示しない",
583
+ tutorialSettingLabel: "起動時にチュートリアルを表示",
584
+ tutorialStep1Text: "ステップ1: 指定された敵を長押し",
585
+ tutorialStep2Text: "ステップ2: ターゲットに向けて勢いよくフリック",
586
+ tutorialDragWarning: "最高の戦略は勢いよく投げることです!"
487
587
  },
488
588
  ko: {
489
589
  title: "AXON SURGE",
@@ -500,7 +600,13 @@ const I = {
500
600
  closeButton: "닫기",
501
601
  grabInstruction: "길게 눌러 적 잡기",
502
602
  throwInstruction: "드래그 후 놓아서 던지기",
503
- comboText: "멀티킬 x{combo}!"
603
+ comboText: "멀티킬 x{combo}!",
604
+ tutorialInstruction: "적을 튕겨 다른 적과 충돌시키세요!",
605
+ dontShowTutorialLabel: "튜토리얼 다시 보지 않기",
606
+ tutorialSettingLabel: "시작 시 튜토리얼 표시",
607
+ tutorialStep1Text: "1단계: 표시된 적을 길게 누르세요",
608
+ tutorialStep2Text: "2단계: 표적을 향해 빠르게 튕기세요",
609
+ tutorialDragWarning: "최선의 전략은 적을 튕겨 던지는 것입니다!"
504
610
  },
505
611
  zh: {
506
612
  title: "AXON SURGE",
@@ -517,7 +623,13 @@ const I = {
517
623
  closeButton: "关闭",
518
624
  grabInstruction: "按住以抓住敌人",
519
625
  throwInstruction: "拖动并释放以抛投",
520
- comboText: "多重击杀 x{combo}!"
626
+ comboText: "多重击杀 x{combo}!",
627
+ tutorialInstruction: "弹射敌人撞击另一个敌人!",
628
+ dontShowTutorialLabel: "不再显示教程",
629
+ tutorialSettingLabel: "启动时显示教程",
630
+ tutorialStep1Text: "步骤 1: 按住指定的敌人",
631
+ tutorialStep2Text: "步骤 2: 朝目标快速挥动抛投",
632
+ tutorialDragWarning: "最佳策略是快速挥动抛投!"
521
633
  }
522
634
  }, k = [
523
635
  "es",
@@ -536,30 +648,49 @@ const I = {
536
648
  "ko",
537
649
  "zh"
538
650
  ];
539
- function V(x) {
540
- return k.includes(x);
651
+ function R(E) {
652
+ return k.includes(E);
541
653
  }
542
- const N = "axon_surge_language";
543
- class J {
654
+ const G = "axon_surge_language";
655
+ class Y {
544
656
  currentLanguage;
545
657
  constructor(t) {
546
- if (t && I[t])
547
- this.currentLanguage = t;
548
- else {
549
- let i = "es";
550
- try {
551
- const e = localStorage.getItem(N);
552
- e && V(e) && (i = e);
553
- } catch {
658
+ this.currentLanguage = this.detectLanguage(t);
659
+ }
660
+ detectLanguage(t) {
661
+ try {
662
+ const e = localStorage.getItem(G);
663
+ if (e && R(e))
664
+ return e;
665
+ } catch {
666
+ }
667
+ if (t && R(t))
668
+ return t;
669
+ try {
670
+ const e = (document.documentElement.lang || document.body?.getAttribute("lang") || "").toLowerCase();
671
+ if (e) {
672
+ const i = e.split("-")[0];
673
+ if (i && R(i))
674
+ return i;
675
+ }
676
+ } catch {
677
+ }
678
+ try {
679
+ const e = (navigator.language || navigator.languages && navigator.languages[0] || "").toLowerCase();
680
+ if (e) {
681
+ const i = e.split("-")[0];
682
+ if (i && R(i))
683
+ return i;
554
684
  }
555
- this.currentLanguage = i;
685
+ } catch {
556
686
  }
687
+ return "en";
557
688
  }
558
689
  setLanguage(t) {
559
- if (I[t]) {
690
+ if (w[t]) {
560
691
  this.currentLanguage = t;
561
692
  try {
562
- localStorage.setItem(N, t);
693
+ localStorage.setItem(G, t);
563
694
  } catch {
564
695
  }
565
696
  }
@@ -567,19 +698,19 @@ class J {
567
698
  getLanguage() {
568
699
  return this.currentLanguage;
569
700
  }
570
- translate(t, i) {
571
- let s = (I[this.currentLanguage] || I.es)[t] || I.es[t] || String(t);
572
- return i && Object.entries(i).forEach(([a, c]) => {
573
- s = s.replace(`{${a}}`, String(c));
701
+ translate(t, e) {
702
+ let s = (w[this.currentLanguage] || w.en)[t] || w.en[t] || String(t);
703
+ return e && Object.entries(e).forEach(([a, l]) => {
704
+ s = s.replace(`{${a}}`, String(l));
574
705
  }), s;
575
706
  }
576
707
  }
577
- class Y {
708
+ class J {
578
709
  execute(t) {
579
- const { thrownEnemy: i, targetEnemy: e, shockwaves: s, particles: a, floatingTexts: c } = t;
580
- e.active = !1, s.push({
710
+ const { thrownEnemy: e, targetEnemy: i, shockwaves: s, particles: a, floatingTexts: l } = t;
711
+ i.active = !1, s.push({
581
712
  id: Math.random().toString(),
582
- position: { ...e.position },
713
+ position: { ...i.position },
583
714
  radius: 10,
584
715
  maxRadius: 180,
585
716
  color: "#ff2a5f",
@@ -587,11 +718,11 @@ class Y {
587
718
  lifetime: 0,
588
719
  maxLifetime: 0.5
589
720
  });
590
- for (let h = 0; h < 30; h++) {
721
+ for (let r = 0; r < 30; r++) {
591
722
  const n = Math.random() * Math.PI * 2, o = 180 + Math.random() * 320;
592
723
  a.push({
593
724
  id: Math.random().toString(),
594
- position: { ...e.position },
725
+ position: { ...i.position },
595
726
  velocity: { x: Math.cos(n) * o, y: Math.sin(n) * o },
596
727
  color: "#ff2a5f",
597
728
  radius: 3 + Math.random() * 4,
@@ -600,10 +731,10 @@ class Y {
600
731
  maxLifetime: 0.5
601
732
  });
602
733
  }
603
- c.push({
734
+ l.push({
604
735
  id: Math.random().toString(),
605
736
  text: "PIERCING SLICE",
606
- position: { ...e.position },
737
+ position: { ...i.position },
607
738
  velocity: { x: 0, y: -50 },
608
739
  color: "#ff2a5f",
609
740
  alpha: 1,
@@ -613,10 +744,10 @@ class Y {
613
744
  });
614
745
  }
615
746
  }
616
- class W {
747
+ class Z {
617
748
  execute(t) {
618
- const { thrownEnemy: i, pools: e, shockwaves: s, particles: a, floatingTexts: c, eventBus: h } = t, n = i.position;
619
- e.push({
749
+ const { thrownEnemy: e, pools: i, shockwaves: s, particles: a, floatingTexts: l, eventBus: r } = t, n = e.position;
750
+ i.push({
620
751
  id: Math.random().toString(),
621
752
  position: { ...n },
622
753
  radius: 220,
@@ -634,11 +765,11 @@ class W {
634
765
  maxLifetime: 0.6
635
766
  });
636
767
  for (let o = 0; o < 45; o++) {
637
- const r = Math.random() * Math.PI * 2, l = 120 + Math.random() * 260;
768
+ const h = Math.random() * Math.PI * 2, c = 120 + Math.random() * 260;
638
769
  a.push({
639
770
  id: Math.random().toString(),
640
771
  position: { ...n },
641
- velocity: { x: Math.cos(r) * l, y: Math.sin(r) * l },
772
+ velocity: { x: Math.cos(h) * c, y: Math.sin(h) * c },
642
773
  color: "#39ff14",
643
774
  radius: 4 + Math.random() * 5,
644
775
  alpha: 1,
@@ -646,7 +777,7 @@ class W {
646
777
  maxLifetime: 0.9
647
778
  });
648
779
  }
649
- c.push({
780
+ l.push({
650
781
  id: Math.random().toString(),
651
782
  text: "MASSIVE SPORE NEBULA",
652
783
  position: { ...n },
@@ -656,13 +787,13 @@ class W {
656
787
  lifetime: 0,
657
788
  maxLifetime: 1.2,
658
789
  size: 26
659
- }), i.active = !1, h.emit("onPoolCreated", { position: n });
790
+ }), e.active = !1, r.emit("onPoolCreated", { position: n });
660
791
  }
661
792
  }
662
793
  class X {
663
794
  execute(t) {
664
- const { thrownEnemy: i, targetEnemy: e, allEnemies: s, shockwaves: a, particles: c, floatingTexts: h } = t, n = e.position;
665
- i.active = !1, e.active = !1, a.push({
795
+ const { thrownEnemy: e, targetEnemy: i, allEnemies: s, shockwaves: a, particles: l, floatingTexts: r } = t, n = i.position;
796
+ e.active = !1, i.active = !1, a.push({
666
797
  id: Math.random().toString(),
667
798
  position: { ...n },
668
799
  radius: 15,
@@ -673,21 +804,21 @@ class X {
673
804
  maxLifetime: 0.6
674
805
  });
675
806
  for (let o = 0; o < 6; o++) {
676
- const r = o * Math.PI * 2 / 6, l = {
677
- x: n.x + Math.cos(r) * 15,
678
- y: n.y + Math.sin(r) * 15
679
- }, p = L.createEnemy("micro", l, {
680
- x: l.x + Math.cos(r) * 200,
681
- y: l.y + Math.sin(r) * 200
807
+ const h = o * Math.PI * 2 / 6, c = {
808
+ x: n.x + Math.cos(h) * 15,
809
+ y: n.y + Math.sin(h) * 15
810
+ }, u = S.createEnemy("micro", c, {
811
+ x: c.x + Math.cos(h) * 200,
812
+ y: c.y + Math.sin(h) * 200
682
813
  });
683
- p.isThrown = !0, s.push(p);
814
+ u.isThrown = !0, s.push(u);
684
815
  }
685
816
  for (let o = 0; o < 35; o++) {
686
- const r = Math.random() * Math.PI * 2, l = 200 + Math.random() * 300;
687
- c.push({
817
+ const h = Math.random() * Math.PI * 2, c = 200 + Math.random() * 300;
818
+ l.push({
688
819
  id: Math.random().toString(),
689
820
  position: { ...n },
690
- velocity: { x: Math.cos(r) * l, y: Math.sin(r) * l },
821
+ velocity: { x: Math.cos(h) * c, y: Math.sin(h) * c },
691
822
  color: "#ffd700",
692
823
  radius: 4 + Math.random() * 4,
693
824
  alpha: 1,
@@ -695,7 +826,7 @@ class X {
695
826
  maxLifetime: 0.6
696
827
  });
697
828
  }
698
- h.push({
829
+ r.push({
699
830
  id: Math.random().toString(),
700
831
  text: "CLUSTER DETONATION",
701
832
  position: { ...n },
@@ -710,41 +841,41 @@ class X {
710
841
  }
711
842
  class $ {
712
843
  execute(t) {
713
- const { thrownEnemy: i, targetEnemy: e, vortices: s, shockwaves: a } = t, c = {
714
- x: (i.position.x + e.position.x) / 2,
715
- y: (i.position.y + e.position.y) / 2
844
+ const { thrownEnemy: e, targetEnemy: i, vortices: s, shockwaves: a } = t, l = {
845
+ x: (e.position.x + i.position.x) / 2,
846
+ y: (e.position.y + i.position.y) / 2
716
847
  };
717
848
  s.push({
718
849
  id: Math.random().toString(),
719
- position: c,
850
+ position: l,
720
851
  radius: 480,
721
852
  duration: 0,
722
853
  maxDuration: 6,
723
854
  pullForce: 3500
724
855
  }), a.push({
725
856
  id: Math.random().toString(),
726
- position: c,
857
+ position: l,
727
858
  radius: 20,
728
859
  maxRadius: 480,
729
860
  color: "#9d4edd",
730
861
  alpha: 1,
731
862
  lifetime: 0,
732
863
  maxLifetime: 0.65
733
- }), i.triggerDissolveDeath(), e.triggerDissolveDeath();
864
+ }), e.triggerDissolveDeath(), i.triggerDissolveDeath();
734
865
  }
735
866
  }
736
- class L {
737
- static createEnemy(t, i, e) {
738
- const s = `enemy_${Date.now()}_${Math.random()}`, a = new P(s);
739
- return this.configureEnemy(a, t, i, e), a;
740
- }
741
- static configureEnemy(t, i, e, s) {
742
- t.type = i, t.position = { ...e }, t.active = !0, t.isGrabbed = !1, t.isThrown = !1;
743
- const a = s.x - e.x, c = s.y - e.y, h = Math.atan2(c, a);
744
- let n = 70, o = 20, r = "#ff2a5f", l = null;
745
- i === "piercer" ? (n = 95, o = 18, r = "#ff2a5f", l = new Y()) : i === "spore" ? (n = 65, o = 24, r = "#39ff14", l = new W()) : i === "cluster" ? (n = 50, o = 26, r = "#ffd700", l = new X()) : i === "parasite" ? (n = 80, o = 22, r = "#9d4edd", l = new $()) : i === "micro" && (n = 130, o = 12, r = "#ffd700"), t.radius = o, t.color = r, t.strategy = l, t.velocity = {
746
- x: Math.cos(h) * n,
747
- y: Math.sin(h) * n
867
+ class S {
868
+ static createEnemy(t, e, i) {
869
+ const s = `enemy_${Date.now()}_${Math.random()}`, a = new O(s);
870
+ return this.configureEnemy(a, t, e, i), a;
871
+ }
872
+ static configureEnemy(t, e, i, s) {
873
+ t.type = e, t.position = { ...i }, t.active = !0, t.isGrabbed = !1, t.isThrown = !1;
874
+ const a = s.x - i.x, l = s.y - i.y, r = Math.atan2(l, a);
875
+ let n = 70, o = 100, h = 20, c = "#ff2a5f", u = null;
876
+ e === "piercer" ? (n = 95, o = 140, h = 18, c = "#ff2a5f", u = new J()) : e === "spore" ? (n = 65, o = 90, h = 24, c = "#39ff14", u = new Z()) : e === "cluster" ? (n = 50, o = 75, h = 26, c = "#ffd700", u = new X()) : e === "parasite" ? (n = 80, o = 110, h = 22, c = "#9d4edd", u = new $()) : e === "micro" && (n = 130, o = 160, h = 12, c = "#ffd700"), t.radius = h, t.color = c, t.strategy = u, t.maxSpeed = o, t.velocity = {
877
+ x: Math.cos(r) * n,
878
+ y: Math.sin(r) * n
748
879
  };
749
880
  }
750
881
  }
@@ -754,60 +885,60 @@ class z {
754
885
  i18n;
755
886
  currentThrowKills = 0;
756
887
  currentThrowPos = null;
757
- constructor(t, i) {
758
- this.spatialHash = new K(100), this.eventBus = t, this.i18n = i;
888
+ constructor(t, e) {
889
+ this.spatialHash = new V(100), this.eventBus = t, this.i18n = e;
759
890
  }
760
- update(t, i, e, s, a, c, h, n, o, r, l, p, f, g) {
891
+ update(t, e, i, s, a, l, r, n, o, h, c, u, p, f) {
761
892
  this.spatialHash.clear();
762
- for (const d of e)
893
+ for (const d of i)
763
894
  d.active && !d.isDying ? (d.update(t), this.spatialHash.insert(d)) : d.active && d.isDying && d.update(t);
764
- for (let d = c.length - 1; d >= 0; d--) {
765
- const m = c[d];
895
+ for (let d = l.length - 1; d >= 0; d--) {
896
+ const m = l[d];
766
897
  if (!m) continue;
767
898
  m.lifetime += t;
768
- const u = m.lifetime / m.maxLifetime;
769
- m.radius = m.maxRadius * u, m.alpha = Math.max(0, 1 - u), m.lifetime >= m.maxLifetime && c.splice(d, 1);
899
+ const x = m.lifetime / m.maxLifetime;
900
+ m.radius = m.maxRadius * x, m.alpha = Math.max(0, 1 - x), m.lifetime >= m.maxLifetime && l.splice(d, 1);
770
901
  }
771
902
  for (let d = a.length - 1; d >= 0; d--) {
772
903
  const m = a[d];
773
904
  if (m) {
774
905
  m.duration += t;
775
- for (const u of e) {
776
- if (!u.active || u.isGrabbed || u.isDying || u.isThrown && u.type === "piercer") continue;
777
- const y = m.position.x - u.position.x, v = m.position.y - u.position.y, S = Math.hypot(y, v);
778
- if (S > 2 && S <= m.radius) {
779
- const T = Math.pow(1 - S / m.radius, 0.7), M = m.pullForce * T, E = Math.atan2(v, y);
780
- u.velocity.x += Math.cos(E) * M * t, u.velocity.y += Math.sin(E) * M * t, u.position.x += Math.cos(E) * M * t * 0.8, u.position.y += Math.sin(E) * M * t * 0.8;
906
+ for (const x of i) {
907
+ if (!x.active || x.isGrabbed || x.isDying || x.isThrown && x.type === "piercer") continue;
908
+ const L = m.position.x - x.position.x, A = m.position.y - x.position.y, b = Math.hypot(L, A);
909
+ if (b > 2 && b <= m.radius) {
910
+ const M = Math.pow(1 - b / m.radius, 0.7), y = m.pullForce * M, g = Math.atan2(A, L);
911
+ x.velocity.x += Math.cos(g) * y * t, x.velocity.y += Math.sin(g) * y * t, x.position.x += Math.cos(g) * y * t * 0.8, x.position.y += Math.sin(g) * y * t * 0.8;
781
912
  }
782
913
  }
783
914
  m.duration >= m.maxDuration && a.splice(d, 1);
784
915
  }
785
916
  }
786
- for (const d of e) {
917
+ for (const d of i) {
787
918
  if (!d.active || d.isGrabbed || d.isDying) continue;
788
- const m = i.position.x - d.position.x, u = i.position.y - d.position.y;
789
- if (Math.hypot(m, u) <= i.radius + d.radius) {
919
+ const m = e.position.x - d.position.x, x = e.position.y - d.position.y;
920
+ if (Math.hypot(m, x) <= e.radius + d.radius) {
790
921
  d.active = !1;
791
- const v = i.takeDamage();
792
- this.eventBus.emit("onCoreDamaged", { currentIntegrity: i.integrity }), c.push({
922
+ const A = e.takeDamage();
923
+ this.eventBus.emit("onCoreDamaged", { currentIntegrity: e.integrity }), l.push({
793
924
  id: Math.random().toString(),
794
- position: { ...i.position },
925
+ position: { ...e.position },
795
926
  radius: 20,
796
- maxRadius: Math.max(p, f) * 1.3,
927
+ maxRadius: Math.max(u, p) * 1.3,
797
928
  color: "#00f0ff",
798
929
  alpha: 1,
799
930
  lifetime: 0,
800
931
  maxLifetime: 0.8
801
- }), o.triggerScreenShake({ x: m, y: u }, 25), o.triggerHitstop(0.15), o.triggerFlash(0.6);
802
- for (const S of e)
803
- if (S.active && !S.isGrabbed) {
804
- S.triggerDissolveDeath();
805
- for (let T = 0; T < 8; T++) {
806
- const M = Math.random() * Math.PI * 2, E = 100 + Math.random() * 200;
807
- h.push({
932
+ }), o.triggerScreenShake({ x: m, y: x }, 25), o.triggerHitstop(0.15), o.triggerFlash(0.6);
933
+ for (const b of i)
934
+ if (b.active && !b.isGrabbed) {
935
+ b.triggerDissolveDeath();
936
+ for (let M = 0; M < 8; M++) {
937
+ const y = Math.random() * Math.PI * 2, g = 100 + Math.random() * 200;
938
+ r.push({
808
939
  id: Math.random().toString(),
809
- position: { ...S.position },
810
- velocity: { x: Math.cos(M) * E, y: Math.sin(M) * E },
940
+ position: { ...b.position },
941
+ velocity: { x: Math.cos(y) * g, y: Math.sin(y) * g },
811
942
  color: "#00f0ff",
812
943
  radius: 3 + Math.random() * 3,
813
944
  alpha: 1,
@@ -819,112 +950,135 @@ class z {
819
950
  n.push({
820
951
  id: Math.random().toString(),
821
952
  text: "CORE OVERLOAD PULSE!",
822
- position: { ...i.position },
953
+ position: { ...e.position },
823
954
  velocity: { x: 0, y: -90 },
824
955
  color: "#00f0ff",
825
956
  alpha: 1,
826
957
  lifetime: 0,
827
958
  maxLifetime: 1.5,
828
959
  size: 32
829
- }), (!v || i.integrity <= 0) && this.eventBus.emit("onGameOver", { score: l.value, wave: 1 });
960
+ }), (!A || e.integrity <= 0) && this.eventBus.emit("onGameOver", { score: c.value, wave: 1 });
830
961
  break;
831
962
  }
832
963
  }
833
- let b = !1;
834
- for (const d of e) {
835
- if (!d.active || !d.isThrown || d.isDying) continue;
836
- if (b = !0, d.position.x < -120 || d.position.x > p + 120 || d.position.y < -120 || d.position.y > f + 120) {
837
- d.active = !1, d.isThrown = !1;
838
- continue;
839
- }
840
- const m = this.spatialHash.getNearby(d.position, d.getHitRadius() * 2);
841
- for (const u of m) {
842
- if (u === d || !u.active || u.isGrabbed || u.isDying) continue;
843
- const y = u.position.x - d.position.x, v = u.position.y - d.position.y;
844
- if (Math.hypot(y, v) <= d.getHitRadius() + u.getHitRadius()) {
845
- this.currentThrowPos = { x: d.position.x, y: d.position.y };
846
- const T = Math.atan2(d.velocity.y, d.velocity.x);
847
- if (d.type === "piercer") {
848
- this.currentThrowKills++, this.killEnemyWithChainReaction(u, T, s, a, c, h, e), o.triggerHitstop(0.05), o.triggerScreenShake({ x: y, y: v }, 7), c.push({
849
- id: Math.random().toString(),
850
- position: { ...u.position },
851
- radius: 10,
852
- maxRadius: 180,
853
- color: "#ff2a5f",
854
- alpha: 1,
855
- lifetime: 0,
856
- maxLifetime: 0.45
857
- });
858
- for (let M = 0; M < 16; M++) {
859
- const E = Math.random() * Math.PI * 2, w = 150 + Math.random() * 300;
860
- h.push({
964
+ let T = !1;
965
+ for (const d of i)
966
+ if (!(!d.active || !d.isThrown || d.isDying)) {
967
+ if (T = !0, d.position.x < -120 || d.position.x > u + 120 || d.position.y < -120 || d.position.y > p + 120) {
968
+ d.active = !1, d.isThrown = !1;
969
+ continue;
970
+ }
971
+ for (const m of i) {
972
+ if (m === d || !m.active || m.isGrabbed || m.isDying) continue;
973
+ const x = m.position.x - d.position.x, L = m.position.y - d.position.y;
974
+ if (Math.hypot(x, L) <= d.getHitRadius() + m.getHitRadius()) {
975
+ this.currentThrowPos = { x: d.position.x, y: d.position.y };
976
+ const b = Math.atan2(d.velocity.y, d.velocity.x);
977
+ if (d.type === "piercer") {
978
+ this.currentThrowKills++, this.killEnemyWithChainReaction(m, b, s, a, l, r, i), o.triggerHitstop(0.05), o.triggerScreenShake({ x, y: L }, 7), l.push({
861
979
  id: Math.random().toString(),
862
- position: { ...u.position },
863
- velocity: { x: Math.cos(E) * w, y: Math.sin(E) * w },
980
+ position: { ...m.position },
981
+ radius: 10,
982
+ maxRadius: 180,
864
983
  color: "#ff2a5f",
865
- radius: 3 + Math.random() * 3,
866
984
  alpha: 1,
867
985
  lifetime: 0,
868
- maxLifetime: 0.4
986
+ maxLifetime: 0.45
869
987
  });
870
- }
871
- g && g();
872
- } else {
873
- const M = d.type === u.type;
874
- c.push({
875
- id: Math.random().toString(),
876
- position: { ...this.currentThrowPos },
877
- radius: 15,
878
- maxRadius: M ? 350 : 220,
879
- color: d.color,
880
- alpha: 1,
881
- lifetime: 0,
882
- maxLifetime: 0.55
883
- });
884
- for (let E = 0; E < 36; E++) {
885
- const w = Math.random() * Math.PI * 2, R = 180 + Math.random() * 400;
886
- h.push({
988
+ for (let M = 0; M < 16; M++) {
989
+ const y = Math.random() * Math.PI * 2, g = 150 + Math.random() * 300;
990
+ r.push({
991
+ id: Math.random().toString(),
992
+ position: { ...m.position },
993
+ velocity: { x: Math.cos(y) * g, y: Math.sin(y) * g },
994
+ color: "#ff2a5f",
995
+ radius: 3 + Math.random() * 3,
996
+ alpha: 1,
997
+ lifetime: 0,
998
+ maxLifetime: 0.4
999
+ });
1000
+ }
1001
+ f && f();
1002
+ } else {
1003
+ const M = d.type === m.type, y = M ? 360 : 250;
1004
+ l.push({
887
1005
  id: Math.random().toString(),
888
1006
  position: { ...this.currentThrowPos },
889
- velocity: { x: Math.cos(w) * R, y: Math.sin(w) * R },
1007
+ radius: 15,
1008
+ maxRadius: y,
890
1009
  color: d.color,
891
- radius: 4 + Math.random() * 5,
892
1010
  alpha: 1,
893
1011
  lifetime: 0,
894
- maxLifetime: 0.65
1012
+ maxLifetime: 0.55
895
1013
  });
1014
+ for (let g = 0; g < 45; g++) {
1015
+ const I = Math.random() * Math.PI * 2, v = 200 + Math.random() * 450;
1016
+ r.push({
1017
+ id: Math.random().toString(),
1018
+ position: { ...this.currentThrowPos },
1019
+ velocity: { x: Math.cos(I) * v, y: Math.sin(I) * v },
1020
+ color: d.color,
1021
+ radius: 4 + Math.random() * 6,
1022
+ alpha: 1,
1023
+ lifetime: 0,
1024
+ maxLifetime: 0.7
1025
+ });
1026
+ }
1027
+ if (M) {
1028
+ if (this.currentThrowKills += 2, o.triggerHitstop(0.14), o.triggerFlash(0.5), o.triggerScreenShake({ x, y: L }, 16), n.push({
1029
+ id: Math.random().toString(),
1030
+ text: "COLOR SYNERGY!",
1031
+ position: { ...this.currentThrowPos },
1032
+ velocity: { x: 0, y: -80 },
1033
+ color: d.color,
1034
+ alpha: 1,
1035
+ lifetime: 0,
1036
+ maxLifetime: 1.2,
1037
+ size: 26
1038
+ }), d.type === "spore")
1039
+ s.push({
1040
+ id: Math.random().toString(),
1041
+ position: { ...this.currentThrowPos },
1042
+ radius: 340,
1043
+ duration: 0,
1044
+ maxDuration: 10,
1045
+ damage: 100
1046
+ });
1047
+ else if (d.type === "parasite")
1048
+ a.push({
1049
+ id: Math.random().toString(),
1050
+ position: { ...this.currentThrowPos },
1051
+ radius: 600,
1052
+ duration: 0,
1053
+ maxDuration: 7,
1054
+ pullForce: 5e3
1055
+ });
1056
+ else if (d.type === "cluster")
1057
+ for (let g = 0; g < 8; g++) {
1058
+ const I = g * Math.PI * 2 / 8, v = {
1059
+ x: this.currentThrowPos.x + Math.cos(I) * 15,
1060
+ y: this.currentThrowPos.y + Math.sin(I) * 15
1061
+ }, D = S.createEnemy("micro", v, {
1062
+ x: v.x + Math.cos(I) * 220,
1063
+ y: v.y + Math.sin(I) * 220
1064
+ });
1065
+ D.isThrown = !0, i.push(D);
1066
+ }
1067
+ this.killEnemyWithChainReaction(d, b, s, a, l, r, i), this.killEnemyWithChainReaction(m, b, s, a, l, r, i);
1068
+ } else
1069
+ this.currentThrowKills += 2, o.triggerHitstop(0.08), o.triggerFlash(0.35), o.triggerScreenShake({ x, y: L }, 10), this.killEnemyWithChainReaction(d, b, s, a, l, r, i), this.killEnemyWithChainReaction(m, b, s, a, l, r, i);
1070
+ for (const g of i) {
1071
+ if (g === d || g === m || !g.active || g.isGrabbed || g.isDying) continue;
1072
+ const I = g.position.x - this.currentThrowPos.x, v = g.position.y - this.currentThrowPos.y;
1073
+ Math.hypot(I, v) <= y && (this.killEnemyWithChainReaction(g, b, s, a, l, r, i), this.currentThrowKills++);
1074
+ }
1075
+ f && f();
1076
+ break;
896
1077
  }
897
- M ? (this.currentThrowKills += 3, o.triggerHitstop(0.12), o.triggerFlash(0.5), o.triggerScreenShake({ x: y, y: v }, 14), n.push({
898
- id: Math.random().toString(),
899
- text: "COLOR SYNERGY!",
900
- position: { ...this.currentThrowPos },
901
- velocity: { x: 0, y: -80 },
902
- color: d.color,
903
- alpha: 1,
904
- lifetime: 0,
905
- maxLifetime: 1.2,
906
- size: 26
907
- }), d.type === "spore" ? (s.push({
908
- id: Math.random().toString(),
909
- position: { ...this.currentThrowPos },
910
- radius: 320,
911
- duration: 0,
912
- maxDuration: 10,
913
- damage: 100
914
- }), d.triggerDissolveDeath(), u.triggerDissolveDeath()) : d.type === "parasite" ? (a.push({
915
- id: Math.random().toString(),
916
- position: { ...this.currentThrowPos },
917
- radius: 580,
918
- duration: 0,
919
- maxDuration: 7,
920
- pullForce: 4500
921
- }), d.triggerDissolveDeath(), u.triggerDissolveDeath()) : (d.triggerDissolveDeath(), u.triggerDissolveDeath())) : (this.currentThrowKills += 2, o.triggerHitstop(0.08), o.triggerFlash(0.35), o.triggerScreenShake({ x: y, y: v }, 8), this.killEnemyWithChainReaction(d, T, s, a, c, h, e), this.killEnemyWithChainReaction(u, T, s, a, c, h, e)), g && g();
922
- break;
923
1078
  }
924
1079
  }
925
1080
  }
926
- }
927
- r.value = this.currentThrowKills, !b && this.currentThrowKills > 0 && (this.currentThrowKills >= 2 && this.currentThrowPos && n.push({
1081
+ h.value = this.currentThrowKills, !T && this.currentThrowKills > 0 && (this.currentThrowKills >= 2 && this.currentThrowPos && n.push({
928
1082
  id: Math.random().toString(),
929
1083
  text: `MULTIKILL x${this.currentThrowKills}!`,
930
1084
  position: { ...this.currentThrowPos },
@@ -934,21 +1088,21 @@ class z {
934
1088
  lifetime: 0,
935
1089
  maxLifetime: 1.4,
936
1090
  size: 32
937
- }), this.eventBus.emit("onComboUpdated", { combo: r.value }), this.currentThrowKills = 0, this.currentThrowPos = null);
1091
+ }), this.eventBus.emit("onComboUpdated", { combo: h.value }), this.currentThrowKills = 0, this.currentThrowPos = null);
938
1092
  for (let d = s.length - 1; d >= 0; d--) {
939
1093
  const m = s[d];
940
1094
  if (m) {
941
1095
  m.duration += t;
942
- for (const u of e) {
943
- if (!u.active || u.isGrabbed || u.isDying || u.isThrown && u.type === "piercer") continue;
944
- const y = u.position.x - m.position.x, v = u.position.y - m.position.y;
945
- Math.hypot(y, v) <= m.radius && (this.killEnemyWithChainReaction(u, 0, s, a, c, h, e), this.currentThrowKills++, g && g());
1096
+ for (const x of i) {
1097
+ if (!x.active || x.isGrabbed || x.isDying || x.isThrown && x.type === "piercer") continue;
1098
+ const L = x.position.x - m.position.x, A = x.position.y - m.position.y;
1099
+ Math.hypot(L, A) <= m.radius && (this.killEnemyWithChainReaction(x, 0, s, a, l, r, i), this.currentThrowKills++, f && f());
946
1100
  }
947
1101
  m.duration >= m.maxDuration && s.splice(d, 1);
948
1102
  }
949
1103
  }
950
1104
  }
951
- killEnemyWithChainReaction(t, i, e, s, a, c, h) {
1105
+ killEnemyWithChainReaction(t, e, i, s, a, l, r) {
952
1106
  if (!(!t.active || t.isDying))
953
1107
  if (a.push({
954
1108
  id: Math.random().toString(),
@@ -960,7 +1114,7 @@ class z {
960
1114
  lifetime: 0,
961
1115
  maxLifetime: 0.5
962
1116
  }), t.type === "spore")
963
- t.triggerDissolveDeath(), e.push({
1117
+ t.triggerDissolveDeath(), i.push({
964
1118
  id: Math.random().toString(),
965
1119
  position: { ...t.position },
966
1120
  radius: 200,
@@ -971,14 +1125,14 @@ class z {
971
1125
  else if (t.type === "cluster") {
972
1126
  t.triggerDissolveDeath();
973
1127
  for (let n = 0; n < 6; n++) {
974
- const o = n * Math.PI * 2 / 6, r = {
1128
+ const o = n * Math.PI * 2 / 6, h = {
975
1129
  x: t.position.x + Math.cos(o) * 15,
976
1130
  y: t.position.y + Math.sin(o) * 15
977
- }, l = L.createEnemy("micro", r, {
978
- x: r.x + Math.cos(o) * 200,
979
- y: r.y + Math.sin(o) * 200
1131
+ }, c = S.createEnemy("micro", h, {
1132
+ x: h.x + Math.cos(o) * 200,
1133
+ y: h.y + Math.sin(o) * 200
980
1134
  });
981
- l.isThrown = !0, h.push(l);
1135
+ c.isThrown = !0, r.push(c);
982
1136
  }
983
1137
  } else t.type === "parasite" ? (t.triggerDissolveDeath(), s.push({
984
1138
  id: Math.random().toString(),
@@ -987,22 +1141,22 @@ class z {
987
1141
  duration: 0,
988
1142
  maxDuration: 5,
989
1143
  pullForce: 3e3
990
- })) : t.type === "piercer" ? t.triggerSliceDeath(i) : t.triggerDissolveDeath();
1144
+ })) : t.type === "piercer" ? t.triggerSliceDeath(e) : t.triggerDissolveDeath();
991
1145
  }
992
1146
  }
993
- class Z {
1147
+ class _ {
994
1148
  pool = [];
995
1149
  constructor(t = 500) {
996
- for (let i = 0; i < t; i++) {
997
- const e = new P(`pool_enemy_${i}`);
998
- this.pool.push(e);
1150
+ for (let e = 0; e < t; e++) {
1151
+ const i = new O(`pool_enemy_${e}`);
1152
+ this.pool.push(i);
999
1153
  }
1000
1154
  }
1001
1155
  get() {
1002
- for (const i of this.pool)
1003
- if (!i.active)
1004
- return i.reset(), i;
1005
- const t = new P(`fallback_enemy_${Date.now()}_${Math.random()}`);
1156
+ for (const e of this.pool)
1157
+ if (!e.active)
1158
+ return e.reset(), e;
1159
+ const t = new O(`fallback_enemy_${Date.now()}_${Math.random()}`);
1006
1160
  return this.pool.push(t), t;
1007
1161
  }
1008
1162
  resetAll() {
@@ -1010,148 +1164,155 @@ class Z {
1010
1164
  t.reset();
1011
1165
  }
1012
1166
  }
1013
- class A {
1014
- static getOffscreenPosition(t, i) {
1015
- const e = Math.floor(Math.random() * 4), s = 70;
1016
- return e === 0 ? { x: Math.random() * t, y: -s } : e === 1 ? { x: t + s, y: Math.random() * i } : e === 2 ? { x: Math.random() * t, y: i + s } : { x: -s, y: Math.random() * i };
1167
+ class C {
1168
+ static getOffscreenPosition(t, e) {
1169
+ const i = Math.floor(Math.random() * 4), s = 70;
1170
+ return i === 0 ? { x: Math.random() * t, y: -s } : i === 1 ? { x: t + s, y: Math.random() * e } : i === 2 ? { x: Math.random() * t, y: e + s } : { x: -s, y: Math.random() * e };
1017
1171
  }
1018
- static spawnCircleOfDeath(t, i, e, s) {
1019
- const a = [], h = Math.max(e, s) * 0.55 + 80;
1172
+ static spawnCircleOfDeath(t, e, i, s) {
1173
+ const a = [], r = Math.max(i, s) * 0.55 + 80;
1020
1174
  for (let n = 0; n < 18; n++) {
1021
- const o = n * Math.PI * 2 / 18, r = {
1022
- x: i.x + Math.cos(o) * h,
1023
- y: i.y + Math.sin(o) * h
1024
- }, l = t.get(), p = ["piercer", "spore", "cluster", "parasite"], f = p[n % p.length];
1025
- L.configureEnemy(l, f, r, i), l.velocity = {
1175
+ const o = n * Math.PI * 2 / 18, h = {
1176
+ x: e.x + Math.cos(o) * r,
1177
+ y: e.y + Math.sin(o) * r
1178
+ }, c = t.get(), u = ["piercer", "spore", "cluster", "parasite"], p = u[n % u.length];
1179
+ S.configureEnemy(c, p, h, e), c.velocity = {
1026
1180
  x: Math.cos(o + Math.PI) * 55,
1027
1181
  y: Math.sin(o + Math.PI) * 55
1028
- }, a.push(l);
1182
+ }, a.push(c);
1029
1183
  }
1030
1184
  return a;
1031
1185
  }
1032
- static spawnDenseCluster(t, i, e, s) {
1033
- const a = [], h = Math.floor(Math.random() * 4);
1186
+ static spawnDenseCluster(t, e, i, s) {
1187
+ const a = [], r = Math.floor(Math.random() * 4);
1034
1188
  let n = { x: -60, y: -60 };
1035
- h === 0 ? n = { x: Math.random() * i, y: -80 } : h === 1 ? n = { x: i + 80, y: Math.random() * e } : h === 2 ? n = { x: Math.random() * i, y: e + 80 } : n = { x: -80, y: Math.random() * e };
1189
+ r === 0 ? n = { x: Math.random() * e, y: -80 } : r === 1 ? n = { x: e + 80, y: Math.random() * i } : r === 2 ? n = { x: Math.random() * e, y: i + 80 } : n = { x: -80, y: Math.random() * i };
1036
1190
  for (let o = 0; o < 14; o++) {
1037
- const r = {
1191
+ const h = {
1038
1192
  x: (Math.random() - 0.5) * 60,
1039
1193
  y: (Math.random() - 0.5) * 60
1040
- }, l = { x: n.x + r.x, y: n.y + r.y }, p = t.get();
1041
- L.configureEnemy(p, "spore", l, s);
1042
- const f = s.x - l.x, g = s.y - l.y, b = Math.atan2(g, f);
1043
- p.velocity = {
1044
- x: Math.cos(b) * (50 + Math.random() * 20),
1045
- y: Math.sin(b) * (50 + Math.random() * 20)
1046
- }, a.push(p);
1194
+ }, c = { x: n.x + h.x, y: n.y + h.y }, u = t.get();
1195
+ S.configureEnemy(u, "spore", c, s);
1196
+ const p = s.x - c.x, f = s.y - c.y, T = Math.atan2(f, p);
1197
+ u.velocity = {
1198
+ x: Math.cos(T) * (50 + Math.random() * 20),
1199
+ y: Math.sin(T) * (50 + Math.random() * 20)
1200
+ }, a.push(u);
1047
1201
  }
1048
1202
  return a;
1049
1203
  }
1050
- static spawnSineSnake(t, i, e, s) {
1051
- const a = [], h = e * 0.2 + Math.random() * e * 0.6;
1204
+ static spawnSineSnake(t, e, i, s) {
1205
+ const a = [], r = i * 0.2 + Math.random() * i * 0.6;
1052
1206
  for (let n = 0; n < 12; n++) {
1053
1207
  const o = {
1054
1208
  x: -60 - n * 40,
1055
- y: h + Math.sin(n * 0.45) * 70
1056
- }, r = t.get();
1057
- L.configureEnemy(r, "cluster", o, s), r.velocity = { x: 75, y: Math.cos(n * 0.45) * 30 }, a.push(r);
1209
+ y: r + Math.sin(n * 0.45) * 70
1210
+ }, h = t.get();
1211
+ S.configureEnemy(h, "cluster", o, s), h.velocity = { x: 75, y: Math.cos(n * 0.45) * 30 }, a.push(h);
1058
1212
  }
1059
1213
  return a;
1060
1214
  }
1061
- static spawnDoubleSpiral(t, i, e, s) {
1215
+ static spawnDoubleSpiral(t, e, i, s) {
1062
1216
  const a = [];
1063
- for (let h = 0; h < 14; h++) {
1064
- const n = h / 14, o = n * Math.PI * 4, r = 120 + n * 450, l = {
1065
- x: i + Math.cos(o) * r,
1066
- y: -60 + Math.sin(o) * r
1067
- }, p = t.get();
1068
- L.configureEnemy(p, "parasite", l, s), a.push(p);
1217
+ for (let r = 0; r < 14; r++) {
1218
+ const n = r / 14, o = n * Math.PI * 4, h = 120 + n * 450, c = {
1219
+ x: e + Math.cos(o) * h,
1220
+ y: -60 + Math.sin(o) * h
1221
+ }, u = t.get();
1222
+ S.configureEnemy(u, "parasite", c, s), a.push(u);
1069
1223
  }
1070
1224
  return a;
1071
1225
  }
1072
- static spawnMarchingWall(t, i, e, s) {
1073
- const a = [], h = Math.random() > 0.5;
1226
+ static spawnMarchingWall(t, e, i, s) {
1227
+ const a = [], r = Math.random() > 0.5;
1074
1228
  for (let n = 0; n < 12; n++) {
1075
- const o = n / 11 * e, r = {
1076
- x: h ? -60 : i + 60,
1229
+ const o = n / 11 * i, h = {
1230
+ x: r ? -60 : e + 60,
1077
1231
  y: o
1078
- }, l = t.get();
1079
- L.configureEnemy(l, "piercer", r, s), l.velocity = {
1080
- x: h ? 70 : -70,
1232
+ }, c = t.get();
1233
+ S.configureEnemy(c, "piercer", h, s), c.velocity = {
1234
+ x: r ? 70 : -70,
1081
1235
  y: 0
1082
- }, a.push(l);
1236
+ }, a.push(c);
1083
1237
  }
1084
1238
  return a;
1085
1239
  }
1086
- static spawnCrossfireStreams(t, i, e, s) {
1240
+ static spawnCrossfireStreams(t, e, i, s) {
1087
1241
  const a = [];
1088
- for (let h = 0; h < 10; h++) {
1089
- const n = { x: -50 - h * 35, y: -50 - h * 35 }, o = t.get();
1090
- L.configureEnemy(o, "spore", n, s), a.push(o);
1091
- const r = { x: i + 50 + h * 35, y: e + 50 + h * 35 }, l = t.get();
1092
- L.configureEnemy(l, "cluster", r, s), a.push(l);
1242
+ for (let r = 0; r < 10; r++) {
1243
+ const n = { x: -50 - r * 35, y: -50 - r * 35 }, o = t.get();
1244
+ S.configureEnemy(o, "spore", n, s), a.push(o);
1245
+ const h = { x: e + 50 + r * 35, y: i + 50 + r * 35 }, c = t.get();
1246
+ S.configureEnemy(c, "cluster", h, s), a.push(c);
1093
1247
  }
1094
1248
  return a;
1095
1249
  }
1096
1250
  }
1097
- class _ {
1251
+ class q {
1098
1252
  wave = 1;
1099
1253
  pool;
1100
1254
  spawnTimer = 0;
1101
1255
  waveTimer = 0;
1102
1256
  patternCooldown = 0;
1103
- initialGracePeriod = 25;
1257
+ initialGracePeriod = 6;
1104
1258
  constructor() {
1105
- this.pool = new Z(500);
1259
+ this.pool = new _(500);
1106
1260
  }
1107
1261
  reset() {
1108
1262
  this.wave = 1, this.spawnTimer = 0, this.waveTimer = 0, this.patternCooldown = 0;
1109
1263
  }
1110
- update(t, i, e, s, a) {
1111
- this.waveTimer += t, this.spawnTimer += t, this.patternCooldown += t, this.applyFlockingBehaviors(i, t, a);
1112
- const c = Math.max(1.1, 4.2 - (this.wave - 1) * 0.25);
1113
- if (this.waveTimer > this.initialGracePeriod && this.patternCooldown > Math.max(16 - this.wave, 8) && i.length < 35) {
1264
+ update(t, e, i, s, a) {
1265
+ this.waveTimer += t, this.spawnTimer += t, this.patternCooldown += t, this.applyFlockingBehaviors(e, t, a);
1266
+ const l = e.filter((o) => o.active).length, r = Math.max(0.9, 2.2 - (this.wave - 1) * 0.18);
1267
+ if (this.waveTimer > this.initialGracePeriod && this.patternCooldown > Math.max(12 - this.wave, 6) && l < 35) {
1114
1268
  this.patternCooldown = 0;
1115
- const n = this.spawnPatternFormation(e, s, a);
1116
- for (const o of n)
1117
- i.push(o);
1269
+ const o = this.spawnPatternFormation(i, s, a);
1270
+ for (const h of o)
1271
+ e.push(h);
1118
1272
  }
1119
- const h = Math.min(18 + this.wave * 4, 80);
1120
- return this.spawnTimer >= c && i.length < h ? (this.spawnTimer = 0, this.spawnSingleEnemy(e, s, a)) : null;
1273
+ const n = Math.min(18 + this.wave * 4, 80);
1274
+ return this.spawnTimer >= r && l < n ? (this.spawnTimer = 0, this.spawnSingleEnemy(i, s, a)) : null;
1121
1275
  }
1122
- spawnSingleEnemy(t, i, e) {
1123
- const s = A.getOffscreenPosition(t, i), a = Math.random();
1124
- let c = "piercer";
1125
- a > 0.75 ? c = "parasite" : a > 0.5 ? c = "cluster" : a > 0.25 && (c = "spore");
1126
- const h = this.pool.get();
1127
- return L.configureEnemy(h, c, s, e), h;
1276
+ spawnSingleEnemy(t, e, i) {
1277
+ const s = C.getOffscreenPosition(t, e), a = Math.random();
1278
+ let l = "piercer";
1279
+ a > 0.75 ? l = "parasite" : a > 0.5 ? l = "cluster" : a > 0.25 && (l = "spore");
1280
+ const r = this.pool.get();
1281
+ return S.configureEnemy(r, l, s, i), r;
1128
1282
  }
1129
- spawnPatternFormation(t, i, e) {
1283
+ spawnPatternFormation(t, e, i) {
1130
1284
  const s = Math.random();
1131
- return s < 0.25 ? A.spawnCircleOfDeath(this.pool, e, t, i) : s < 0.5 ? A.spawnDenseCluster(this.pool, t, i, e) : s < 0.75 ? A.spawnSineSnake(this.pool, t, i, e) : A.spawnMarchingWall(this.pool, t, i, e);
1285
+ return s < 0.25 ? C.spawnCircleOfDeath(this.pool, i, t, e) : s < 0.5 ? C.spawnDenseCluster(this.pool, t, e, i) : s < 0.75 ? C.spawnSineSnake(this.pool, t, e, i) : C.spawnMarchingWall(this.pool, t, e, i);
1132
1286
  }
1133
- applyFlockingBehaviors(t, i, e) {
1287
+ applyFlockingBehaviors(t, e, i) {
1134
1288
  for (let a = 0; a < t.length; a++) {
1135
- const c = t[a];
1136
- if (!c.active || c.isGrabbed || c.isThrown || c.isDying) continue;
1137
- let h = 0, n = 0, o = 0;
1138
- for (let f = 0; f < t.length; f++) {
1139
- if (a === f) continue;
1140
- const g = t[f];
1141
- if (!g.active || g.isGrabbed || g.isDying) continue;
1142
- const b = c.position.x - g.position.x, d = c.position.y - g.position.y, m = Math.hypot(b, d);
1143
- m > 0 && m < 70 && (h += b / m, n += d / m, o++);
1289
+ const l = t[a];
1290
+ if (!l.active || l.isGrabbed || l.isThrown || l.isDying) continue;
1291
+ let r = 0, n = 0, o = 0;
1292
+ for (let p = 0; p < t.length; p++) {
1293
+ if (a === p) continue;
1294
+ const f = t[p];
1295
+ if (!f.active || f.isGrabbed || f.isDying) continue;
1296
+ const T = l.position.x - f.position.x, d = l.position.y - f.position.y, m = Math.hypot(T, d);
1297
+ m > 0 && m < 70 && (r += T / m, n += d / m, o++);
1144
1298
  }
1145
- o > 0 && (h /= o, n /= o, c.velocity.x += h * 60 * i, c.velocity.y += n * 60 * i);
1146
- const r = e.x - c.position.x, l = e.y - c.position.y, p = Math.hypot(r, l);
1147
- if (p > 0) {
1148
- const f = 80 + Math.min(this.wave * 4, 40);
1149
- c.velocity.x += r / p * f * i, c.velocity.y += l / p * f * i;
1299
+ o > 0 && (r /= o, n /= o, l.velocity.x += r * 60 * e, l.velocity.y += n * 60 * e);
1300
+ const h = i.x - l.position.x, c = i.y - l.position.y, u = Math.hypot(h, c);
1301
+ if (u > 0) {
1302
+ const p = 80 + Math.min(this.wave * 4, 40);
1303
+ l.velocity.x += h / u * p * e, l.velocity.y += c / u * p * e;
1304
+ }
1305
+ if (l.maxSpeed > 0) {
1306
+ const p = Math.hypot(l.velocity.x, l.velocity.y);
1307
+ if (p > l.maxSpeed) {
1308
+ const f = l.maxSpeed / p;
1309
+ l.velocity.x *= f, l.velocity.y *= f;
1310
+ }
1150
1311
  }
1151
1312
  }
1152
1313
  }
1153
1314
  }
1154
- const C = {
1315
+ const N = {
1155
1316
  bioluminescent: {
1156
1317
  bgInner: "#081220",
1157
1318
  bgMid: "#050b16",
@@ -1200,197 +1361,279 @@ const C = {
1200
1361
  tendrilMagenta: "#b5008c",
1201
1362
  tendrilCyan: "#0077b6"
1202
1363
  }
1203
- }, D = "axon_surge_theme";
1204
- class q {
1364
+ }, P = "axon_surge_theme";
1365
+ class j {
1205
1366
  currentTheme = "bioluminescent";
1206
- constructor(t) {
1207
- if (t)
1208
- this.setTheme(t);
1367
+ isExplicit = !1;
1368
+ targetElement;
1369
+ constructor(t, e) {
1370
+ if (e !== void 0 && (this.targetElement = e), t)
1371
+ this.isExplicit = !0, this.setTheme(t);
1209
1372
  else {
1210
1373
  try {
1211
- const i = localStorage.getItem(D);
1212
- i && C[i] && (this.currentTheme = i);
1374
+ const i = localStorage.getItem(P);
1375
+ i && N[i] && (this.currentTheme = i, this.isExplicit = !0);
1213
1376
  } catch {
1214
1377
  }
1215
- this.applyThemeToDOM();
1378
+ this.isExplicit && this.applyThemeToDOM();
1216
1379
  }
1217
1380
  }
1381
+ setTargetElement(t) {
1382
+ this.targetElement = t, this.isExplicit && this.applyThemeToDOM();
1383
+ }
1218
1384
  setTheme(t) {
1219
- if (C[t]) {
1220
- this.currentTheme = t, this.applyThemeToDOM();
1385
+ if (N[t]) {
1386
+ this.currentTheme = t, this.isExplicit = !0, this.applyThemeToDOM();
1221
1387
  try {
1222
- localStorage.setItem(D, t);
1388
+ localStorage.setItem(P, t);
1223
1389
  } catch {
1224
1390
  }
1225
1391
  }
1226
1392
  }
1393
+ clearExplicitTheme() {
1394
+ this.isExplicit = !1;
1395
+ try {
1396
+ localStorage.removeItem(P);
1397
+ } catch {
1398
+ }
1399
+ this.removeThemeClasses();
1400
+ }
1227
1401
  getTheme() {
1228
1402
  return this.currentTheme;
1229
1403
  }
1230
1404
  getPalette() {
1231
- return C[this.currentTheme] || C.bioluminescent;
1405
+ return N[this.currentTheme] || N.bioluminescent;
1406
+ }
1407
+ removeThemeClasses() {
1408
+ const t = ["theme-bioluminescent", "theme-dark", "theme-light"];
1409
+ this.targetElement && this.targetElement.classList.remove(...t), document.documentElement.classList.remove(...t), document.documentElement.removeAttribute("data-theme");
1232
1410
  }
1233
1411
  applyThemeToDOM() {
1234
- document.documentElement.setAttribute("data-theme", this.currentTheme);
1412
+ if (this.removeThemeClasses(), !this.isExplicit) return;
1413
+ const t = `theme-${this.currentTheme}`;
1414
+ this.targetElement && this.targetElement.classList.add(t), document.documentElement.classList.add(t);
1235
1415
  }
1236
1416
  }
1237
1417
  class Q {
1418
+ maxDistance = 450;
1419
+ maxThickness = 28;
1420
+ minThickness = 4;
1421
+ maxLength = 140;
1422
+ minLength = 40;
1423
+ render(t, e, i, s) {
1424
+ for (const a of e) {
1425
+ if (!a.active || a.isGrabbed || a.isDying) continue;
1426
+ const l = a.position.x, r = a.position.y;
1427
+ if (l >= 0 && l <= i && r >= 0 && r <= s) continue;
1428
+ const n = Math.min(i, Math.max(0, l)), o = Math.min(s, Math.max(0, r)), h = Math.hypot(l - n, r - o);
1429
+ if (h <= 0 || h > this.maxDistance) continue;
1430
+ const c = Math.min(1, Math.max(0, h / this.maxDistance)), u = this.minThickness + (this.maxThickness - this.minThickness) * c, p = this.minLength + (this.maxLength - this.minLength) * c, f = 0.35 + (1 - c) * 0.55;
1431
+ if (t.save(), t.globalAlpha = f, t.shadowColor = a.color, t.shadowBlur = 12 + (1 - c) * 16, t.strokeStyle = a.color, t.lineWidth = u, t.lineCap = "round", t.beginPath(), n === 0 || n === i) {
1432
+ const T = Math.max(0, o - p / 2), d = Math.min(s, o + p / 2);
1433
+ t.moveTo(n, T), t.lineTo(n, d);
1434
+ } else {
1435
+ const T = Math.max(0, n - p / 2), d = Math.min(i, n + p / 2);
1436
+ t.moveTo(T, o), t.lineTo(d, o);
1437
+ }
1438
+ t.stroke(), t.strokeStyle = "#ffffff", t.lineWidth = Math.max(1.5, u * 0.25), t.globalAlpha = f * 0.8, t.stroke(), t.restore();
1439
+ }
1440
+ }
1441
+ }
1442
+ class tt {
1443
+ render(t, e, i, s, a) {
1444
+ const l = (210 + (a - 1) * 38 + Math.sin(s * 0.12) * 15) % 360, r = `hsl(${l}, 45%, 8%)`, n = `hsl(${(l + 30) % 360}, 40%, 4%)`, o = `hsl(${(l + 60) % 360}, 50%, 2%)`, h = t.createRadialGradient(e / 2, i / 2, 40, e / 2, i / 2, Math.max(e, i));
1445
+ h.addColorStop(0, r), h.addColorStop(0.55, n), h.addColorStop(1, o), t.fillStyle = h, t.fillRect(0, 0, e, i);
1446
+ const c = (l + 75) % 360, u = e * 0.35 + Math.sin(s * 0.25) * 70, p = i * 0.45 + Math.cos(s * 0.2) * 60, f = t.createRadialGradient(u, p, 20, u, p, 400);
1447
+ f.addColorStop(0, `hsla(${c}, 65%, 12%, 0.35)`), f.addColorStop(1, "rgba(0, 0, 0, 0)"), t.fillStyle = f, t.beginPath(), t.arc(u, p, 400, 0, Math.PI * 2), t.fill();
1448
+ const T = (l + 160) % 360, d = e * 0.68 + Math.cos(s * 0.28) * 60, m = i * 0.55 + Math.sin(s * 0.22) * 55, x = t.createRadialGradient(d, m, 20, d, m, 440);
1449
+ x.addColorStop(0, `hsla(${T}, 60%, 10%, 0.3)`), x.addColorStop(1, "rgba(0, 0, 0, 0)"), t.fillStyle = x, t.beginPath(), t.arc(d, m, 440, 0, Math.PI * 2), t.fill();
1450
+ }
1451
+ }
1452
+ class et {
1453
+ render(t, e, i) {
1454
+ if (!e.isActive) return;
1455
+ const s = e.getLauncher(), a = e.getTarget();
1456
+ if (!s || !a || !s.active || !a.active) return;
1457
+ const l = e.getStep();
1458
+ if (t.save(), l === 1) {
1459
+ const r = Math.sin(i * 6) * 10, n = s.position.x, o = s.position.y - 65 + r;
1460
+ t.shadowColor = "#00f0ff", t.shadowBlur = 20, t.fillStyle = "#00f0ff", t.beginPath(), t.moveTo(n, o + 20), t.lineTo(n - 16, o - 12), t.lineTo(n - 6, o - 12), t.lineTo(n - 6, o - 32), t.lineTo(n + 6, o - 32), t.lineTo(n + 6, o - 12), t.lineTo(n + 16, o - 12), t.closePath(), t.fill();
1461
+ const h = s.radius * (1.6 + Math.sin(i * 8) * 0.3);
1462
+ t.strokeStyle = "rgba(0, 240, 255, 0.8)", t.lineWidth = 3, t.beginPath(), t.arc(s.position.x, s.position.y, h, 0, Math.PI * 2), t.stroke();
1463
+ } else if (l === 2) {
1464
+ const r = a.position.x - s.position.x, n = a.position.y - s.position.y;
1465
+ if (Math.hypot(r, n) > 10) {
1466
+ const h = Math.atan2(n, r);
1467
+ t.shadowColor = "#ff00dd", t.shadowBlur = 22, t.strokeStyle = "#ff00dd", t.lineWidth = 4, t.setLineDash([12, 8]), t.beginPath(), t.moveTo(s.position.x, s.position.y), t.lineTo(a.position.x, a.position.y), t.stroke(), t.setLineDash([]);
1468
+ const c = a.position.x - Math.cos(h) * (a.radius + 10), u = a.position.y - Math.sin(h) * (a.radius + 10);
1469
+ t.fillStyle = "#ff00dd", t.beginPath(), t.moveTo(c, u), t.lineTo(c - Math.cos(h - 0.4) * 24, u - Math.sin(h - 0.4) * 24), t.lineTo(c - Math.cos(h + 0.4) * 24, u - Math.sin(h + 0.4) * 24), t.closePath(), t.fill();
1470
+ const p = a.radius * (1.8 + Math.cos(i * 10) * 0.3);
1471
+ t.strokeStyle = "rgba(255, 0, 221, 0.9)", t.lineWidth = 3.5, t.beginPath(), t.arc(a.position.x, a.position.y, p, 0, Math.PI * 2), t.stroke();
1472
+ }
1473
+ }
1474
+ t.restore();
1475
+ }
1476
+ }
1477
+ class it {
1238
1478
  canvas;
1239
1479
  ctx;
1240
1480
  themeManager;
1241
- constructor(t, i) {
1242
- this.canvas = t, this.ctx = t.getContext("2d"), this.themeManager = i;
1481
+ indicatorRenderer;
1482
+ bgRenderer;
1483
+ tutorialArrowRenderer;
1484
+ constructor(t, e) {
1485
+ this.canvas = t, this.ctx = t.getContext("2d"), this.themeManager = e, this.indicatorRenderer = new Q(), this.bgRenderer = new tt(), this.tutorialArrowRenderer = new et();
1243
1486
  }
1244
- render(t, i, e, s, a, c, h, n, o, r) {
1487
+ render(t, e, i, s, a, l, r, n, o, h, c = 1, u) {
1245
1488
  if (!this.ctx) return;
1246
- const l = this.themeManager.getPalette(), { width: p, height: f } = this.canvas, g = n.getShakeOffset();
1247
- this.ctx.save(), this.ctx.translate(g.x, g.y), this.drawFluidCosmosBackground(p, f, t.pulsePhase, l), this.drawToxicPools(e, t.pulsePhase), this.drawGravityVortices(s, t.pulsePhase), this.drawShockwaves(a), this.drawCoreFilaments(t, l), this.drawParticles(c), this.drawOrganicEnemies(i, t.pulsePhase, l), o ? this.drawPsionicTendril(t.position, o.position, l) : t && this.drawHoverTendril(t.position, r, i, l), this.drawOrganicConsciousnessCore(t, l), this.drawFloatingTexts(h), n.flashAlpha > 0 && (this.ctx.fillStyle = `rgba(255, 255, 255, ${n.flashAlpha})`, this.ctx.fillRect(0, 0, p, f)), this.ctx.restore();
1489
+ const p = this.themeManager.getPalette(), { width: f, height: T } = this.canvas, d = n.getShakeOffset();
1490
+ this.ctx.save(), this.ctx.translate(d.x, d.y), this.bgRenderer.render(this.ctx, f, T, t.pulsePhase, c), this.drawToxicPools(i, t.pulsePhase), this.drawGravityVortices(s, t.pulsePhase), this.drawShockwaves(a), this.drawCoreFilaments(t, p), this.drawParticles(l), this.indicatorRenderer.render(this.ctx, e, f, T), this.drawOrganicEnemies(e, t.pulsePhase, p), u && this.tutorialArrowRenderer.render(this.ctx, u, t.pulsePhase), o ? this.drawPsionicTendril(t.position, o.position, p) : t && this.drawHoverTendril(t.position, h, e, p), this.drawOrganicConsciousnessCore(t, p), this.drawFloatingTexts(r), n.flashAlpha > 0 && (this.ctx.fillStyle = `rgba(255, 255, 255, ${n.flashAlpha})`, this.ctx.fillRect(0, 0, f, T)), this.ctx.restore();
1248
1491
  }
1249
- drawToxicPools(t, i) {
1492
+ drawToxicPools(t, e) {
1250
1493
  if (this.ctx)
1251
- for (const e of t) {
1252
- const s = e.duration / e.maxDuration, a = Math.min(0.7, (1 - s) * 0.7), { x: c, y: h } = e.position;
1494
+ for (const i of t) {
1495
+ const s = i.duration / i.maxDuration, a = Math.min(0.7, (1 - s) * 0.7), { x: l, y: r } = i.position;
1253
1496
  this.ctx.save();
1254
- const n = this.ctx.createRadialGradient(c, h, 10, c, h, e.radius * 1.2);
1497
+ const n = this.ctx.createRadialGradient(l, r, 10, l, r, i.radius * 1.2);
1255
1498
  n.addColorStop(0, `rgba(57, 255, 20, ${a * 0.9})`), n.addColorStop(0.4, `rgba(16, 185, 129, ${a * 0.65})`), n.addColorStop(0.8, `rgba(5, 80, 45, ${a * 0.35})`), n.addColorStop(1, "rgba(2, 35, 15, 0)"), this.ctx.fillStyle = n, this.ctx.shadowColor = "#39ff14", this.ctx.shadowBlur = 30, this.ctx.beginPath();
1256
1499
  const o = 70;
1257
- for (let r = 0; r <= o; r++) {
1258
- const l = r * Math.PI * 2 / o, p = Math.sin(l * 5 + i * 3) * 14, f = Math.cos(l * 3 - i * 2) * 9, g = e.radius + p + f, b = c + Math.cos(l) * g, d = h + Math.sin(l) * g;
1259
- r === 0 ? this.ctx.moveTo(b, d) : this.ctx.lineTo(b, d);
1500
+ for (let h = 0; h <= o; h++) {
1501
+ const c = h * Math.PI * 2 / o, u = Math.sin(c * 5 + e * 3) * 14, p = Math.cos(c * 3 - e * 2) * 9, f = i.radius + u + p, T = l + Math.cos(c) * f, d = r + Math.sin(c) * f;
1502
+ h === 0 ? this.ctx.moveTo(T, d) : this.ctx.lineTo(T, d);
1260
1503
  }
1261
1504
  this.ctx.closePath(), this.ctx.fill(), this.ctx.strokeStyle = `rgba(57, 255, 20, ${a * 0.8})`, this.ctx.lineWidth = 2.5, this.ctx.beginPath();
1262
- for (let r = 0; r <= o; r++) {
1263
- const l = r * Math.PI * 2 / o, p = Math.sin(l * 6 + i * 4) * 8, f = e.radius * 0.75 + p, g = c + Math.cos(l) * f, b = h + Math.sin(l) * f;
1264
- r === 0 ? this.ctx.moveTo(g, b) : this.ctx.lineTo(g, b);
1505
+ for (let h = 0; h <= o; h++) {
1506
+ const c = h * Math.PI * 2 / o, u = Math.sin(c * 6 + e * 4) * 8, p = i.radius * 0.75 + u, f = l + Math.cos(c) * p, T = r + Math.sin(c) * p;
1507
+ h === 0 ? this.ctx.moveTo(f, T) : this.ctx.lineTo(f, T);
1265
1508
  }
1266
1509
  this.ctx.closePath(), this.ctx.stroke();
1267
- for (let r = 0; r < 6; r++) {
1268
- const l = r * Math.PI * 0.33 + i * 1.5, p = e.radius * 0.5 * (0.3 + Math.sin(i * 2 + r) * 0.3), f = c + Math.cos(l) * p, g = h + Math.sin(l) * p, b = 3 + Math.sin(i * 3 + r) * 2;
1269
- this.ctx.fillStyle = `rgba(255, 255, 255, ${a * 0.8})`, this.ctx.beginPath(), this.ctx.arc(f, g, Math.max(1, b), 0, Math.PI * 2), this.ctx.fill();
1510
+ for (let h = 0; h < 6; h++) {
1511
+ const c = h * Math.PI * 0.33 + e * 1.5, u = i.radius * 0.5 * (0.3 + Math.sin(e * 2 + h) * 0.3), p = l + Math.cos(c) * u, f = r + Math.sin(c) * u, T = 3 + Math.sin(e * 3 + h) * 2;
1512
+ this.ctx.fillStyle = `rgba(255, 255, 255, ${a * 0.8})`, this.ctx.beginPath(), this.ctx.arc(p, f, Math.max(1, T), 0, Math.PI * 2), this.ctx.fill();
1270
1513
  }
1271
1514
  this.ctx.restore();
1272
1515
  }
1273
1516
  }
1274
1517
  drawShockwaves(t) {
1275
1518
  if (this.ctx)
1276
- for (const i of t) {
1277
- this.ctx.save(), this.ctx.globalAlpha = i.alpha;
1278
- const e = this.ctx.createRadialGradient(
1279
- i.position.x,
1280
- i.position.y,
1519
+ for (const e of t) {
1520
+ this.ctx.save(), this.ctx.globalAlpha = e.alpha;
1521
+ const i = this.ctx.createRadialGradient(
1522
+ e.position.x,
1523
+ e.position.y,
1281
1524
  0,
1282
- i.position.x,
1283
- i.position.y,
1284
- i.radius
1525
+ e.position.x,
1526
+ e.position.y,
1527
+ e.radius
1285
1528
  );
1286
- e.addColorStop(0, "rgba(255, 255, 255, 0.4)"), e.addColorStop(0.7, i.color), e.addColorStop(1, "rgba(0, 0, 0, 0)"), this.ctx.fillStyle = e, this.ctx.beginPath(), this.ctx.arc(i.position.x, i.position.y, i.radius, 0, Math.PI * 2), this.ctx.fill(), this.ctx.strokeStyle = "#ffffff", this.ctx.lineWidth = 4, this.ctx.shadowColor = i.color, this.ctx.shadowBlur = 24, this.ctx.beginPath(), this.ctx.arc(i.position.x, i.position.y, i.radius, 0, Math.PI * 2), this.ctx.stroke(), this.ctx.restore();
1529
+ i.addColorStop(0, "rgba(255, 255, 255, 0.4)"), i.addColorStop(0.7, e.color), i.addColorStop(1, "rgba(0, 0, 0, 0)"), this.ctx.fillStyle = i, this.ctx.beginPath(), this.ctx.arc(e.position.x, e.position.y, e.radius, 0, Math.PI * 2), this.ctx.fill(), this.ctx.strokeStyle = "#ffffff", this.ctx.lineWidth = 4, this.ctx.shadowColor = e.color, this.ctx.shadowBlur = 24, this.ctx.beginPath(), this.ctx.arc(e.position.x, e.position.y, e.radius, 0, Math.PI * 2), this.ctx.stroke(), this.ctx.restore();
1287
1530
  }
1288
1531
  }
1289
- drawGravityVortices(t, i) {
1532
+ drawGravityVortices(t, e) {
1290
1533
  if (this.ctx)
1291
- for (const e of t) {
1292
- const s = Math.min(0.85, (1 - e.duration / e.maxDuration) * 0.85), a = e.radius * (1 - e.duration / e.maxDuration * 0.1), { x: c, y: h } = e.position;
1534
+ for (const i of t) {
1535
+ const s = Math.min(0.85, (1 - i.duration / i.maxDuration) * 0.85), a = i.radius * (1 - i.duration / i.maxDuration * 0.1), { x: l, y: r } = i.position;
1293
1536
  this.ctx.save();
1294
- const n = this.ctx.createRadialGradient(c, h, 0, c, h, 60);
1295
- n.addColorStop(0, `rgba(0, 0, 0, ${s})`), n.addColorStop(0.7, `rgba(20, 0, 40, ${s})`), n.addColorStop(1, `rgba(157, 78, 221, ${s * 0.5})`), this.ctx.fillStyle = n, this.ctx.beginPath(), this.ctx.arc(c, h, 60, 0, Math.PI * 2), this.ctx.fill(), this.ctx.strokeStyle = `rgba(157, 78, 221, ${s})`, this.ctx.lineWidth = 5, this.ctx.shadowColor = "#9d4edd", this.ctx.shadowBlur = 32;
1537
+ const n = this.ctx.createRadialGradient(l, r, 0, l, r, 60);
1538
+ n.addColorStop(0, `rgba(0, 0, 0, ${s})`), n.addColorStop(0.7, `rgba(20, 0, 40, ${s})`), n.addColorStop(1, `rgba(157, 78, 221, ${s * 0.5})`), this.ctx.fillStyle = n, this.ctx.beginPath(), this.ctx.arc(l, r, 60, 0, Math.PI * 2), this.ctx.fill(), this.ctx.strokeStyle = `rgba(157, 78, 221, ${s})`, this.ctx.lineWidth = 5, this.ctx.shadowColor = "#9d4edd", this.ctx.shadowBlur = 32;
1296
1539
  for (let o = 1; o <= 5; o++) {
1297
- const r = a * o / 5, l = i * o * 2.2;
1298
- this.ctx.beginPath(), this.ctx.arc(c, h, r, l, l + Math.PI * 1.5), this.ctx.stroke();
1540
+ const h = a * o / 5, c = e * o * 2.2;
1541
+ this.ctx.beginPath(), this.ctx.arc(l, r, h, c, c + Math.PI * 1.5), this.ctx.stroke();
1299
1542
  }
1300
1543
  this.ctx.restore();
1301
1544
  }
1302
1545
  }
1303
- drawFluidCosmosBackground(t, i, e, s) {
1546
+ drawFluidCosmosBackground(t, e, i, s) {
1304
1547
  if (!this.ctx) return;
1305
- const a = this.ctx.createRadialGradient(t / 2, i / 2, 40, t / 2, i / 2, Math.max(t, i));
1306
- a.addColorStop(0, s.bgInner), a.addColorStop(0.5, s.bgMid), a.addColorStop(1, s.bgOuter), this.ctx.fillStyle = a, this.ctx.fillRect(0, 0, t, i);
1307
- const c = t * 0.35 + Math.sin(e * 0.3) * 60, h = i * 0.45 + Math.cos(e * 0.25) * 50, n = this.ctx.createRadialGradient(c, h, 20, c, h, 380);
1308
- n.addColorStop(0, s.nebulaCyan), n.addColorStop(1, "rgba(0, 0, 0, 0)"), this.ctx.fillStyle = n, this.ctx.beginPath(), this.ctx.arc(c, h, 380, 0, Math.PI * 2), this.ctx.fill();
1309
- const o = t * 0.68 + Math.cos(e * 0.35) * 50, r = i * 0.55 + Math.sin(e * 0.3) * 45, l = this.ctx.createRadialGradient(o, r, 20, o, r, 420);
1310
- l.addColorStop(0, s.nebulaMagenta), l.addColorStop(1, "rgba(0, 0, 0, 0)"), this.ctx.fillStyle = l, this.ctx.beginPath(), this.ctx.arc(o, r, 420, 0, Math.PI * 2), this.ctx.fill();
1311
- }
1312
- drawCoreFilaments(t, i) {
1548
+ const a = this.ctx.createRadialGradient(t / 2, e / 2, 40, t / 2, e / 2, Math.max(t, e));
1549
+ a.addColorStop(0, s.bgInner), a.addColorStop(0.5, s.bgMid), a.addColorStop(1, s.bgOuter), this.ctx.fillStyle = a, this.ctx.fillRect(0, 0, t, e);
1550
+ const l = t * 0.35 + Math.sin(i * 0.3) * 60, r = e * 0.45 + Math.cos(i * 0.25) * 50, n = this.ctx.createRadialGradient(l, r, 20, l, r, 380);
1551
+ n.addColorStop(0, s.nebulaCyan), n.addColorStop(1, "rgba(0, 0, 0, 0)"), this.ctx.fillStyle = n, this.ctx.beginPath(), this.ctx.arc(l, r, 380, 0, Math.PI * 2), this.ctx.fill();
1552
+ const o = t * 0.68 + Math.cos(i * 0.35) * 50, h = e * 0.55 + Math.sin(i * 0.3) * 45, c = this.ctx.createRadialGradient(o, h, 20, o, h, 420);
1553
+ c.addColorStop(0, s.nebulaMagenta), c.addColorStop(1, "rgba(0, 0, 0, 0)"), this.ctx.fillStyle = c, this.ctx.beginPath(), this.ctx.arc(o, h, 420, 0, Math.PI * 2), this.ctx.fill();
1554
+ }
1555
+ drawCoreFilaments(t, e) {
1313
1556
  if (!this.ctx) return;
1314
- const e = 12;
1315
- this.ctx.lineWidth = 1.5, this.ctx.strokeStyle = i.nebulaCyan;
1316
- for (let s = 0; s < e; s++) {
1317
- const a = s * Math.PI * 2 / e + t.pulsePhase * 0.12, c = 85 + Math.sin(t.pulsePhase * 1.5 + s) * 25, h = t.position.x + Math.cos(a) * c, n = t.position.y + Math.sin(a) * c, o = t.position.x + Math.cos(a + 0.4) * 48, r = t.position.y + Math.sin(a + 0.4) * 48;
1318
- this.ctx.beginPath(), this.ctx.moveTo(t.position.x, t.position.y), this.ctx.quadraticCurveTo(o, r, h, n), this.ctx.stroke(), this.ctx.fillStyle = i.sporeColor, this.ctx.beginPath(), this.ctx.arc(h, n, 3.5, 0, Math.PI * 2), this.ctx.fill();
1557
+ const i = 12;
1558
+ this.ctx.lineWidth = 1.5, this.ctx.strokeStyle = e.nebulaCyan;
1559
+ for (let s = 0; s < i; s++) {
1560
+ const a = s * Math.PI * 2 / i + t.pulsePhase * 0.12, l = 85 + Math.sin(t.pulsePhase * 1.5 + s) * 25, r = t.position.x + Math.cos(a) * l, n = t.position.y + Math.sin(a) * l, o = t.position.x + Math.cos(a + 0.4) * 48, h = t.position.y + Math.sin(a + 0.4) * 48;
1561
+ this.ctx.beginPath(), this.ctx.moveTo(t.position.x, t.position.y), this.ctx.quadraticCurveTo(o, h, r, n), this.ctx.stroke(), this.ctx.fillStyle = e.sporeColor, this.ctx.beginPath(), this.ctx.arc(r, n, 3.5, 0, Math.PI * 2), this.ctx.fill();
1319
1562
  }
1320
1563
  }
1321
- drawOrganicConsciousnessCore(t, i) {
1564
+ drawOrganicConsciousnessCore(t, e) {
1322
1565
  if (!this.ctx) return;
1323
- const { x: e, y: s } = t.position;
1324
- for (let h = 0; h < t.integrity; h++) {
1325
- const n = t.radius + 16 + h * 12;
1326
- this.ctx.strokeStyle = i.corePrimary, this.ctx.lineWidth = 2.2, this.ctx.shadowColor = i.corePrimary, this.ctx.shadowBlur = 12, this.ctx.beginPath();
1566
+ const { x: i, y: s } = t.position;
1567
+ for (let r = 0; r < t.integrity; r++) {
1568
+ const n = t.radius + 16 + r * 12;
1569
+ this.ctx.strokeStyle = e.corePrimary, this.ctx.lineWidth = 2.2, this.ctx.shadowColor = e.corePrimary, this.ctx.shadowBlur = 12, this.ctx.beginPath();
1327
1570
  const o = 60;
1328
- for (let r = 0; r <= o; r++) {
1329
- const l = r * Math.PI * 2 / o, p = n + Math.sin(l * 4 + t.pulsePhase * 2 + h) * 3, f = e + Math.cos(l) * p, g = s + Math.sin(l) * p;
1330
- r === 0 ? this.ctx.moveTo(f, g) : this.ctx.lineTo(f, g);
1571
+ for (let h = 0; h <= o; h++) {
1572
+ const c = h * Math.PI * 2 / o, u = n + Math.sin(c * 4 + t.pulsePhase * 2 + r) * 3, p = i + Math.cos(c) * u, f = s + Math.sin(c) * u;
1573
+ h === 0 ? this.ctx.moveTo(p, f) : this.ctx.lineTo(p, f);
1331
1574
  }
1332
1575
  this.ctx.closePath(), this.ctx.stroke();
1333
1576
  }
1334
- const a = this.ctx.createRadialGradient(e, s, 5, e, s, t.radius * 2.2);
1335
- a.addColorStop(0, i.coreGlow), a.addColorStop(0.5, i.nebulaMagenta), a.addColorStop(1, "rgba(0, 0, 0, 0)"), this.ctx.fillStyle = a, this.ctx.beginPath(), this.ctx.arc(e, s, t.radius * 2.2, 0, Math.PI * 2), this.ctx.fill(), this.ctx.save(), this.ctx.translate(e, s), this.ctx.strokeStyle = i.corePrimary, this.ctx.lineWidth = 3, this.ctx.fillStyle = i.nebulaCyan, this.ctx.shadowColor = i.corePrimary, this.ctx.shadowBlur = 20, this.ctx.beginPath();
1336
- const c = 80;
1337
- for (let h = 0; h <= c; h++) {
1338
- const n = h * Math.PI * 2 / c, o = t.getMembraneRadius(n), r = Math.cos(n) * o, l = Math.sin(n) * o;
1339
- h === 0 ? this.ctx.moveTo(r, l) : this.ctx.lineTo(r, l);
1577
+ const a = this.ctx.createRadialGradient(i, s, 5, i, s, t.radius * 2.2);
1578
+ a.addColorStop(0, e.coreGlow), a.addColorStop(0.5, e.nebulaMagenta), a.addColorStop(1, "rgba(0, 0, 0, 0)"), this.ctx.fillStyle = a, this.ctx.beginPath(), this.ctx.arc(i, s, t.radius * 2.2, 0, Math.PI * 2), this.ctx.fill(), this.ctx.save(), this.ctx.translate(i, s), this.ctx.strokeStyle = e.corePrimary, this.ctx.lineWidth = 3, this.ctx.fillStyle = e.nebulaCyan, this.ctx.shadowColor = e.corePrimary, this.ctx.shadowBlur = 20, this.ctx.beginPath();
1579
+ const l = 80;
1580
+ for (let r = 0; r <= l; r++) {
1581
+ const n = r * Math.PI * 2 / l, o = t.getMembraneRadius(n), h = Math.cos(n) * o, c = Math.sin(n) * o;
1582
+ r === 0 ? this.ctx.moveTo(h, c) : this.ctx.lineTo(h, c);
1340
1583
  }
1341
1584
  this.ctx.closePath(), this.ctx.fill(), this.ctx.stroke(), this.ctx.fillStyle = "#ffffff", this.ctx.beginPath(), this.ctx.arc(0, 0, t.radius * 0.3, 0, Math.PI * 2), this.ctx.fill(), this.ctx.restore();
1342
1585
  }
1343
- drawPsionicTendril(t, i, e) {
1586
+ drawPsionicTendril(t, e, i) {
1344
1587
  if (!this.ctx) return;
1345
1588
  this.ctx.save();
1346
- const s = i.x - t.x, a = i.y - t.y;
1347
- this.ctx.strokeStyle = e.tendrilMagenta, this.ctx.lineWidth = 9, this.ctx.shadowColor = e.tendrilMagenta, this.ctx.shadowBlur = 20, this.ctx.beginPath(), this.ctx.moveTo(t.x, t.y);
1348
- const c = (t.x + i.x) / 2 + Math.sin(Date.now() * 0.02) * 16, h = (t.y + i.y) / 2 + Math.cos(Date.now() * 0.02) * 16;
1349
- this.ctx.quadraticCurveTo(c, h, i.x, i.y), this.ctx.stroke(), this.ctx.strokeStyle = e.tendrilCyan, this.ctx.lineWidth = 3.5, this.ctx.shadowColor = e.tendrilCyan, this.ctx.shadowBlur = 12, this.ctx.beginPath(), this.ctx.moveTo(t.x, t.y), this.ctx.lineTo(i.x, i.y), this.ctx.stroke();
1589
+ const s = e.x - t.x, a = e.y - t.y;
1590
+ this.ctx.strokeStyle = i.tendrilMagenta, this.ctx.lineWidth = 9, this.ctx.shadowColor = i.tendrilMagenta, this.ctx.shadowBlur = 20, this.ctx.beginPath(), this.ctx.moveTo(t.x, t.y);
1591
+ const l = (t.x + e.x) / 2 + Math.sin(Date.now() * 0.02) * 16, r = (t.y + e.y) / 2 + Math.cos(Date.now() * 0.02) * 16;
1592
+ this.ctx.quadraticCurveTo(l, r, e.x, e.y), this.ctx.stroke(), this.ctx.strokeStyle = i.tendrilCyan, this.ctx.lineWidth = 3.5, this.ctx.shadowColor = i.tendrilCyan, this.ctx.shadowBlur = 12, this.ctx.beginPath(), this.ctx.moveTo(t.x, t.y), this.ctx.lineTo(e.x, e.y), this.ctx.stroke();
1350
1593
  for (let n = 0; n < 6; n++) {
1351
- const o = Math.random(), r = t.x + s * o + (Math.random() - 0.5) * 24, l = t.y + a * o + (Math.random() - 0.5) * 24;
1352
- this.ctx.fillStyle = "#ffffff", this.ctx.beginPath(), this.ctx.arc(r, l, 2.5 + Math.random() * 2.5, 0, Math.PI * 2), this.ctx.fill();
1594
+ const o = Math.random(), h = t.x + s * o + (Math.random() - 0.5) * 24, c = t.y + a * o + (Math.random() - 0.5) * 24;
1595
+ this.ctx.fillStyle = "#ffffff", this.ctx.beginPath(), this.ctx.arc(h, c, 2.5 + Math.random() * 2.5, 0, Math.PI * 2), this.ctx.fill();
1353
1596
  }
1354
1597
  this.ctx.restore();
1355
1598
  }
1356
- drawHoverTendril(t, i, e, s) {
1599
+ drawHoverTendril(t, e, i, s) {
1357
1600
  if (this.ctx)
1358
- for (const a of e) {
1601
+ for (const a of i) {
1359
1602
  if (!a.active || a.isGrabbed || a.isThrown || a.wasManipulated || a.isDying) continue;
1360
- const c = i.x - a.position.x, h = i.y - a.position.y;
1361
- if (Math.hypot(c, h) <= a.getHitRadius()) {
1603
+ const l = e.x - a.position.x, r = e.y - a.position.y;
1604
+ if (Math.hypot(l, r) <= a.getHitRadius()) {
1362
1605
  this.ctx.strokeStyle = s.tendrilMagenta, this.ctx.lineWidth = 2.5, this.ctx.beginPath(), this.ctx.moveTo(t.x, t.y), this.ctx.lineTo(a.position.x, a.position.y), this.ctx.stroke();
1363
1606
  break;
1364
1607
  }
1365
1608
  }
1366
1609
  }
1367
- drawOrganicEnemies(t, i, e) {
1610
+ drawOrganicEnemies(t, e, i) {
1368
1611
  if (this.ctx)
1369
1612
  for (const s of t) {
1370
1613
  if (!s.active) continue;
1371
1614
  let a = s.color;
1372
- s.type === "piercer" ? a = e.piercerColor : s.type === "spore" ? a = e.sporeColor : s.type === "cluster" ? a = e.clusterColor : s.type === "parasite" ? a = e.parasiteColor : s.type === "micro" && (a = e.microColor);
1373
- const { x: c, y: h } = s.position;
1374
- if (this.ctx.save(), this.ctx.translate(c, h), s.wasManipulated && !s.isDying) {
1375
- const n = s.radius * 1.5 + Math.sin(i * 6) * 4;
1376
- this.ctx.strokeStyle = e.tendrilMagenta, this.ctx.lineWidth = 2.5, this.ctx.shadowColor = e.tendrilMagenta, this.ctx.shadowBlur = 18, this.ctx.beginPath(), this.ctx.arc(0, 0, n, 0, Math.PI * 2), this.ctx.stroke();
1377
- const o = s.radius * 1.8 + Math.cos(i * 8) * 3;
1378
- this.ctx.strokeStyle = e.tendrilCyan, this.ctx.lineWidth = 1.5, this.ctx.beginPath(), this.ctx.arc(0, 0, o, 0, Math.PI * 2), this.ctx.stroke();
1615
+ s.type === "piercer" ? a = i.piercerColor : s.type === "spore" ? a = i.sporeColor : s.type === "cluster" ? a = i.clusterColor : s.type === "parasite" ? a = i.parasiteColor : s.type === "micro" && (a = i.microColor);
1616
+ const { x: l, y: r } = s.position;
1617
+ if (this.ctx.save(), this.ctx.translate(l, r), s.wasManipulated && !s.isDying) {
1618
+ const n = s.radius * 1.5 + Math.sin(e * 6) * 4;
1619
+ this.ctx.strokeStyle = i.tendrilMagenta, this.ctx.lineWidth = 2.5, this.ctx.shadowColor = i.tendrilMagenta, this.ctx.shadowBlur = 18, this.ctx.beginPath(), this.ctx.arc(0, 0, n, 0, Math.PI * 2), this.ctx.stroke();
1620
+ const o = s.radius * 1.8 + Math.cos(e * 8) * 3;
1621
+ this.ctx.strokeStyle = i.tendrilCyan, this.ctx.lineWidth = 1.5, this.ctx.beginPath(), this.ctx.arc(0, 0, o, 0, Math.PI * 2), this.ctx.stroke();
1379
1622
  }
1380
1623
  if (s.isDying) {
1381
1624
  const n = s.deathTimer / s.maxDeathTimer, o = Math.max(0, 1 - n);
1382
1625
  if (this.ctx.globalAlpha = o, s.deathType === "dissolve") {
1383
- const r = s.radius * (1 - n * 0.7);
1384
- this.ctx.fillStyle = e.sporeColor, this.ctx.shadowColor = e.sporeColor, this.ctx.shadowBlur = 20, this.ctx.beginPath(), this.ctx.arc(0, 0, r, 0, Math.PI * 2), this.ctx.fill();
1385
- for (let l = 0; l < 4; l++) {
1386
- const p = l * Math.PI * 0.5 + n * 4, f = r * 0.8 * n;
1387
- this.ctx.fillStyle = "#ffffff", this.ctx.beginPath(), this.ctx.arc(Math.cos(p) * f, Math.sin(p) * f, 3, 0, Math.PI * 2), this.ctx.fill();
1626
+ const h = s.radius * (1 - n * 0.7);
1627
+ this.ctx.fillStyle = i.sporeColor, this.ctx.shadowColor = i.sporeColor, this.ctx.shadowBlur = 20, this.ctx.beginPath(), this.ctx.arc(0, 0, h, 0, Math.PI * 2), this.ctx.fill();
1628
+ for (let c = 0; c < 4; c++) {
1629
+ const u = c * Math.PI * 0.5 + n * 4, p = h * 0.8 * n;
1630
+ this.ctx.fillStyle = "#ffffff", this.ctx.beginPath(), this.ctx.arc(Math.cos(u) * p, Math.sin(u) * p, 3, 0, Math.PI * 2), this.ctx.fill();
1388
1631
  }
1389
1632
  this.ctx.restore();
1390
1633
  continue;
1391
1634
  } else if (s.deathType === "sliced") {
1392
- const r = n * 24, l = s.sliceAngle + Math.PI / 2, p = Math.cos(l) * r, f = Math.sin(l) * r;
1393
- this.ctx.shadowColor = "#ff2a5f", this.ctx.shadowBlur = 22, this.ctx.fillStyle = a, this.ctx.save(), this.ctx.translate(p, f), this.ctx.beginPath(), this.ctx.arc(0, 0, s.radius * 0.8, 0, Math.PI), this.ctx.fill(), this.ctx.restore(), this.ctx.save(), this.ctx.translate(-p, -f), this.ctx.beginPath(), this.ctx.arc(0, 0, s.radius * 0.8, Math.PI, Math.PI * 2), this.ctx.fill(), this.ctx.restore(), this.ctx.restore();
1635
+ const h = n * 24, c = s.sliceAngle + Math.PI / 2, u = Math.cos(c) * h, p = Math.sin(c) * h;
1636
+ this.ctx.shadowColor = "#ff2a5f", this.ctx.shadowBlur = 22, this.ctx.fillStyle = a, this.ctx.save(), this.ctx.translate(u, p), this.ctx.beginPath(), this.ctx.arc(0, 0, s.radius * 0.8, 0, Math.PI), this.ctx.fill(), this.ctx.restore(), this.ctx.save(), this.ctx.translate(-u, -p), this.ctx.beginPath(), this.ctx.arc(0, 0, s.radius * 0.8, Math.PI, Math.PI * 2), this.ctx.fill(), this.ctx.restore(), this.ctx.restore();
1394
1637
  continue;
1395
1638
  }
1396
1639
  }
@@ -1398,30 +1641,30 @@ class Q {
1398
1641
  this.ctx.rotate(s.rotation), this.ctx.beginPath();
1399
1642
  const n = 12;
1400
1643
  for (let o = 0; o <= n; o++) {
1401
- const r = o * Math.PI * 2 / n, l = s.radius * 1.6 + Math.sin(r * 3 + i * 4) * 3, p = s.radius * 0.6 + Math.cos(r * 2 + i * 3) * 2, f = Math.cos(r) * l, g = Math.sin(r) * p;
1402
- o === 0 ? this.ctx.moveTo(f, g) : this.ctx.lineTo(f, g);
1644
+ const h = o * Math.PI * 2 / n, c = s.radius * 1.6 + Math.sin(h * 3 + e * 4) * 3, u = s.radius * 0.6 + Math.cos(h * 2 + e * 3) * 2, p = Math.cos(h) * c, f = Math.sin(h) * u;
1645
+ o === 0 ? this.ctx.moveTo(p, f) : this.ctx.lineTo(p, f);
1403
1646
  }
1404
1647
  this.ctx.closePath(), this.ctx.fill(), this.ctx.fillStyle = "#ffffff", this.ctx.beginPath(), this.ctx.arc(4, 0, 4, 0, Math.PI * 2), this.ctx.fill();
1405
1648
  } else if (s.type === "spore") {
1406
1649
  this.ctx.beginPath();
1407
1650
  const n = 8;
1408
1651
  for (let o = 0; o < n; o++) {
1409
- const r = o * Math.PI * 2 / n, l = s.radius + Math.sin(r * 4 + i * 3 + s.position.x) * 4, p = Math.cos(r) * l, f = Math.sin(r) * l;
1410
- o === 0 ? this.ctx.moveTo(p, f) : this.ctx.lineTo(p, f);
1652
+ const h = o * Math.PI * 2 / n, c = s.radius + Math.sin(h * 4 + e * 3 + s.position.x) * 4, u = Math.cos(h) * c, p = Math.sin(h) * c;
1653
+ o === 0 ? this.ctx.moveTo(u, p) : this.ctx.lineTo(u, p);
1411
1654
  }
1412
1655
  this.ctx.closePath(), this.ctx.fill(), this.ctx.fillStyle = "rgba(255, 255, 255, 0.7)", this.ctx.beginPath(), this.ctx.arc(-4, -4, 5, 0, Math.PI * 2), this.ctx.arc(5, 3, 4, 0, Math.PI * 2), this.ctx.fill();
1413
1656
  } else if (s.type === "cluster") {
1414
1657
  this.ctx.beginPath();
1415
- const n = Math.sin(i * 3) * 2;
1658
+ const n = Math.sin(e * 3) * 2;
1416
1659
  this.ctx.arc(0, 0, s.radius * 0.55, 0, Math.PI * 2), this.ctx.arc(-9 + n, -7, s.radius * 0.42, 0, Math.PI * 2), this.ctx.arc(9 - n, -7, s.radius * 0.42, 0, Math.PI * 2), this.ctx.arc(0, 9 + n, s.radius * 0.45, 0, Math.PI * 2), this.ctx.fill();
1417
1660
  } else if (s.type === "parasite") {
1418
1661
  this.ctx.beginPath();
1419
1662
  const n = 14;
1420
1663
  for (let o = 0; o <= n; o++) {
1421
- const r = o * Math.PI * 2 / n, l = s.radius + Math.sin(r * 5 - i * 5) * 3, p = Math.cos(r) * l, f = Math.sin(r) * l;
1422
- o === 0 ? this.ctx.moveTo(p, f) : this.ctx.lineTo(p, f);
1664
+ const h = o * Math.PI * 2 / n, c = s.radius + Math.sin(h * 5 - e * 5) * 3, u = Math.cos(h) * c, p = Math.sin(h) * c;
1665
+ o === 0 ? this.ctx.moveTo(u, p) : this.ctx.lineTo(u, p);
1423
1666
  }
1424
- this.ctx.closePath(), this.ctx.fill(), this.ctx.fillStyle = e.bgOuter, this.ctx.beginPath(), this.ctx.arc(0, 0, s.radius * 0.45, 0, Math.PI * 2), this.ctx.fill();
1667
+ this.ctx.closePath(), this.ctx.fill(), this.ctx.fillStyle = i.bgOuter, this.ctx.beginPath(), this.ctx.arc(0, 0, s.radius * 0.45, 0, Math.PI * 2), this.ctx.fill();
1425
1668
  } else
1426
1669
  this.ctx.beginPath(), this.ctx.arc(0, 0, s.radius, 0, Math.PI * 2), this.ctx.fill();
1427
1670
  this.ctx.restore();
@@ -1429,39 +1672,39 @@ class Q {
1429
1672
  }
1430
1673
  drawParticles(t) {
1431
1674
  if (this.ctx)
1432
- for (const i of t)
1433
- this.ctx.save(), this.ctx.globalAlpha = i.alpha, this.ctx.fillStyle = i.color, this.ctx.beginPath(), this.ctx.arc(i.position.x, i.position.y, i.radius, 0, Math.PI * 2), this.ctx.fill(), this.ctx.restore();
1675
+ for (const e of t)
1676
+ this.ctx.save(), this.ctx.globalAlpha = e.alpha, this.ctx.fillStyle = e.color, this.ctx.beginPath(), this.ctx.arc(e.position.x, e.position.y, e.radius, 0, Math.PI * 2), this.ctx.fill(), this.ctx.restore();
1434
1677
  }
1435
1678
  drawFloatingTexts(t) {
1436
1679
  if (this.ctx)
1437
- for (const i of t)
1438
- this.ctx.save(), this.ctx.globalAlpha = i.alpha, this.ctx.fillStyle = i.color, this.ctx.font = `900 ${i.size}px Orbitron, sans-serif`, this.ctx.textAlign = "center", this.ctx.shadowColor = i.color, this.ctx.shadowBlur = 12, this.ctx.fillText(i.text, i.position.x, i.position.y), this.ctx.restore();
1680
+ for (const e of t)
1681
+ this.ctx.save(), this.ctx.globalAlpha = e.alpha, this.ctx.fillStyle = e.color, this.ctx.font = `900 ${e.size}px Orbitron, sans-serif`, this.ctx.textAlign = "center", this.ctx.shadowColor = e.color, this.ctx.shadowBlur = 12, this.ctx.fillText(e.text, e.position.x, e.position.y), this.ctx.restore();
1439
1682
  }
1440
1683
  }
1441
- class j {
1684
+ class st {
1442
1685
  container;
1443
1686
  i18n;
1444
1687
  waveLabelElement;
1445
1688
  progressSlot;
1446
1689
  comboElement;
1447
1690
  settingsButton;
1448
- constructor(t, i, e) {
1449
- this.i18n = i, this.container = document.createElement("div"), this.container.className = "axon-hud", this.waveLabelElement = document.createElement("div"), this.waveLabelElement.className = "axon-hud-wave", this.progressSlot = document.createElement("div"), this.progressSlot.className = "axon-hud-level-slot", this.waveLabelElement.appendChild(this.progressSlot), this.comboElement = document.createElement("div"), this.comboElement.className = "axon-hud-combo", this.settingsButton = document.createElement("button"), this.settingsButton.className = "axon-hud-settings-btn", this.settingsButton.setAttribute("aria-label", "Settings"), this.settingsButton.innerHTML = `
1691
+ constructor(t, e, i) {
1692
+ this.i18n = e, this.container = document.createElement("div"), this.container.className = "axon-hud", this.waveLabelElement = document.createElement("div"), this.waveLabelElement.className = "axon-hud-wave", this.progressSlot = document.createElement("div"), this.progressSlot.className = "axon-hud-level-slot", this.waveLabelElement.appendChild(this.progressSlot), this.comboElement = document.createElement("div"), this.comboElement.className = "axon-hud-combo", this.settingsButton = document.createElement("button"), this.settingsButton.className = "axon-hud-settings-btn", this.settingsButton.setAttribute("aria-label", "Settings"), this.settingsButton.innerHTML = `
1450
1693
  <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
1451
1694
  <circle cx="12" cy="12" r="3"></circle>
1452
1695
  <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>
1453
1696
  </svg>
1454
- `, this.settingsButton.addEventListener("click", e), this.renderLabels(), this.container.appendChild(this.waveLabelElement), this.container.appendChild(this.comboElement), this.container.appendChild(this.settingsButton), t.appendChild(this.container);
1697
+ `, this.settingsButton.addEventListener("click", i), this.renderLabels(), this.container.appendChild(this.waveLabelElement), this.container.appendChild(this.comboElement), this.container.appendChild(this.settingsButton), t.appendChild(this.container);
1455
1698
  }
1456
1699
  renderLabels() {
1457
1700
  let t = this.waveLabelElement.querySelector(".axon-level-title");
1458
1701
  t ? t.textContent = this.i18n.translate("waveLabel") : (t = document.createElement("div"), t.className = "axon-level-title", t.textContent = this.i18n.translate("waveLabel"), this.waveLabelElement.insertBefore(t, this.waveLabelElement.firstChild));
1459
- let i = this.waveLabelElement.querySelector("#axon-wave-val");
1460
- i || (i = document.createElement("span"), i.id = "axon-wave-val", i.textContent = "1", this.waveLabelElement.insertBefore(i, this.progressSlot)), this.comboElement.innerHTML = '<span id="axon-combo-val"></span>';
1702
+ let e = this.waveLabelElement.querySelector("#axon-wave-val");
1703
+ e || (e = document.createElement("span"), e.id = "axon-wave-val", e.textContent = "1", this.waveLabelElement.insertBefore(e, this.progressSlot)), this.comboElement.innerHTML = '<span id="axon-combo-val"></span>';
1461
1704
  }
1462
- update(t, i) {
1463
- const e = this.container.querySelector("#axon-wave-val"), s = this.container.querySelector("#axon-combo-val");
1464
- e && (e.textContent = t.toString()), s && (i >= 2 ? (s.textContent = `x${i}`, s.style.display = "block") : s.style.display = "none");
1705
+ update(t, e) {
1706
+ const i = this.container.querySelector("#axon-wave-val"), s = this.container.querySelector("#axon-combo-val");
1707
+ i && (i.textContent = t.toString()), s && (e >= 2 ? (s.textContent = `x${e}`, s.style.display = "block") : s.style.display = "none");
1465
1708
  }
1466
1709
  show() {
1467
1710
  this.renderLabels(), this.container.style.display = "flex";
@@ -1470,12 +1713,12 @@ class j {
1470
1713
  this.container.style.display = "none";
1471
1714
  }
1472
1715
  }
1473
- class tt {
1716
+ class at {
1474
1717
  container;
1475
1718
  i18n;
1476
1719
  onStartCallback;
1477
- constructor(t, i, e) {
1478
- this.i18n = i, this.onStartCallback = e, this.container = document.createElement("div"), this.container.className = "axon-start-menu", this.renderContent(), t.appendChild(this.container);
1720
+ constructor(t, e, i) {
1721
+ this.i18n = e, this.onStartCallback = i, this.container = document.createElement("div"), this.container.className = "axon-start-menu", this.renderContent(), t.appendChild(this.container);
1479
1722
  }
1480
1723
  renderContent() {
1481
1724
  this.container.innerHTML = `
@@ -1496,7 +1739,7 @@ class tt {
1496
1739
  this.container.style.display = "none";
1497
1740
  }
1498
1741
  }
1499
- class it {
1742
+ class nt {
1500
1743
  modal;
1501
1744
  card;
1502
1745
  i18n;
@@ -1505,10 +1748,10 @@ class it {
1505
1748
  onLanguageChangedCallback;
1506
1749
  onCloseCallback;
1507
1750
  hapticsEnabled = !0;
1508
- constructor(t, i, e, s, a, c) {
1509
- this.i18n = i, this.themeManager = e, this.platform = s, this.onLanguageChangedCallback = a, this.onCloseCallback = c;
1510
- const h = localStorage.getItem("axon_surge_haptics");
1511
- h !== null && (this.hapticsEnabled = h === "true"), this.modal = document.createElement("dialog"), this.modal.className = "axon-settings-modal", this.card = document.createElement("div"), this.card.className = "axon-settings-card", this.modal.appendChild(this.card), t.appendChild(this.modal), this.modal.addEventListener("close", () => {
1751
+ constructor(t, e, i, s, a, l) {
1752
+ this.i18n = e, this.themeManager = i, this.platform = s, this.onLanguageChangedCallback = a, this.onCloseCallback = l;
1753
+ const r = localStorage.getItem("axon_surge_haptics");
1754
+ r !== null && (this.hapticsEnabled = r === "true"), this.modal = document.createElement("dialog"), this.modal.className = "axon-settings-modal", this.card = document.createElement("div"), this.card.className = "axon-settings-card", this.modal.appendChild(this.card), t.appendChild(this.modal), this.modal.addEventListener("close", () => {
1512
1755
  this.onCloseCallback && this.onCloseCallback();
1513
1756
  }), this.renderContent();
1514
1757
  }
@@ -1516,15 +1759,15 @@ class it {
1516
1759
  this.card.innerHTML = "";
1517
1760
  const t = document.createElement("h2");
1518
1761
  t.textContent = this.i18n.translate("settingsTitle");
1519
- const i = document.createElement("div");
1520
- i.className = "axon-setting-row";
1521
- const e = document.createElement("span");
1522
- e.textContent = this.i18n.translate("languageLabel");
1762
+ const e = document.createElement("div");
1763
+ e.className = "axon-setting-row";
1764
+ const i = document.createElement("span");
1765
+ i.textContent = this.i18n.translate("languageLabel");
1523
1766
  const s = document.createElement("div");
1524
1767
  s.className = "axon-select-wrapper";
1525
1768
  const a = document.createElement("select");
1526
1769
  a.className = "axon-select";
1527
- const c = {
1770
+ const l = {
1528
1771
  es: "ESPAÑOL (ES)",
1529
1772
  en: "ENGLISH (EN)",
1530
1773
  fr: "FRANÇAIS (FR)",
@@ -1541,57 +1784,74 @@ class it {
1541
1784
  ko: "한국어 (KO)",
1542
1785
  zh: "中文 (ZH)"
1543
1786
  };
1544
- for (const u of k) {
1545
- const y = document.createElement("option");
1546
- y.value = u, y.textContent = c[u], this.i18n.getLanguage() === u && (y.selected = !0), a.appendChild(y);
1787
+ for (const y of k) {
1788
+ const g = document.createElement("option");
1789
+ g.value = y, g.textContent = l[y], this.i18n.getLanguage() === y && (g.selected = !0), a.appendChild(g);
1547
1790
  }
1548
1791
  a.addEventListener("change", () => {
1549
- const u = a.value;
1550
- this.i18n.setLanguage(u), this.onLanguageChangedCallback && this.onLanguageChangedCallback(u), this.renderContent();
1792
+ const y = a.value;
1793
+ this.i18n.setLanguage(y), this.onLanguageChangedCallback && this.onLanguageChangedCallback(y), this.renderContent();
1551
1794
  });
1552
- const h = document.createElement("span");
1553
- h.className = "axon-select-arrow", h.textContent = "▼", s.appendChild(a), s.appendChild(h), i.appendChild(e), i.appendChild(s);
1795
+ const r = document.createElement("span");
1796
+ r.className = "axon-select-arrow", r.textContent = "▼", s.appendChild(a), s.appendChild(r), e.appendChild(i), e.appendChild(s);
1554
1797
  const n = document.createElement("div");
1555
1798
  n.className = "axon-setting-row";
1556
1799
  const o = document.createElement("span");
1557
1800
  o.textContent = this.i18n.translate("themeLabel");
1558
- const r = document.createElement("div");
1559
- r.className = "axon-toggle-group";
1560
- const l = [
1801
+ const h = document.createElement("div");
1802
+ h.className = "axon-toggle-group";
1803
+ const c = [
1561
1804
  { id: "bioluminescent", label: "BIO" },
1562
1805
  { id: "dark", label: "DARK" },
1563
1806
  { id: "light", label: "LIGHT" }
1564
1807
  ];
1565
- for (const u of l) {
1566
- const y = document.createElement("button");
1567
- y.type = "button", y.className = `axon-toggle-btn ${this.themeManager.getTheme() === u.id ? "active" : ""}`, y.textContent = u.label, y.addEventListener("click", () => {
1568
- this.themeManager.setTheme(u.id), this.renderContent();
1569
- }), r.appendChild(y);
1808
+ for (const y of c) {
1809
+ const g = document.createElement("button");
1810
+ g.type = "button", g.className = `axon-toggle-btn ${this.themeManager.getTheme() === y.id ? "active" : ""}`, g.textContent = y.label, g.addEventListener("click", () => {
1811
+ this.themeManager.setTheme(y.id), this.renderContent();
1812
+ }), h.appendChild(g);
1570
1813
  }
1571
- n.appendChild(o), n.appendChild(r);
1572
- const p = document.createElement("div");
1573
- p.className = "axon-setting-row";
1574
- const f = document.createElement("span");
1575
- f.textContent = this.i18n.translate("hapticsLabel");
1576
- const g = document.createElement("div");
1577
- g.className = "axon-toggle-group";
1578
- const b = [
1814
+ n.appendChild(o), n.appendChild(h);
1815
+ const u = document.createElement("div");
1816
+ u.className = "axon-setting-row";
1817
+ const p = document.createElement("span");
1818
+ p.textContent = this.i18n.translate("hapticsLabel");
1819
+ const f = document.createElement("div");
1820
+ f.className = "axon-toggle-group";
1821
+ const T = [
1579
1822
  { enabled: !0, label: this.i18n.translate("hapticsOn") },
1580
1823
  { enabled: !1, label: this.i18n.translate("hapticsOff") }
1581
1824
  ];
1582
- for (const u of b) {
1583
- const y = document.createElement("button");
1584
- y.type = "button", y.className = `axon-toggle-btn ${this.hapticsEnabled === u.enabled ? "active" : ""}`, y.textContent = u.label, y.addEventListener("click", () => {
1585
- this.hapticsEnabled = u.enabled, localStorage.setItem("axon_surge_haptics", String(u.enabled)), this.hapticsEnabled && this.platform.haptics.selectionChanged(), this.renderContent();
1586
- }), g.appendChild(y);
1825
+ for (const y of T) {
1826
+ const g = document.createElement("button");
1827
+ g.type = "button", g.className = `axon-toggle-btn ${this.hapticsEnabled === y.enabled ? "active" : ""}`, g.textContent = y.label, g.addEventListener("click", () => {
1828
+ this.hapticsEnabled = y.enabled, localStorage.setItem("axon_surge_haptics", String(y.enabled)), this.hapticsEnabled && this.platform.haptics.selectionChanged(), this.renderContent();
1829
+ }), f.appendChild(g);
1587
1830
  }
1588
- p.appendChild(f), p.appendChild(g);
1831
+ u.appendChild(p), u.appendChild(f);
1589
1832
  const d = document.createElement("div");
1590
- d.className = "axon-settings-credits", d.textContent = this.i18n.translate("creditsJam");
1591
- const m = document.createElement("button");
1592
- m.type = "button", m.className = "axon-start-button", m.style.padding = "12px 36px", m.style.fontSize = "14px", m.textContent = this.i18n.translate("closeButton"), m.addEventListener("click", () => {
1833
+ d.className = "axon-setting-row";
1834
+ const m = document.createElement("span");
1835
+ m.textContent = this.i18n.translate("tutorialSettingLabel");
1836
+ const x = document.createElement("div");
1837
+ x.className = "axon-toggle-group";
1838
+ const L = localStorage.getItem("axon_surge_show_tutorial") !== "false", A = [
1839
+ { enabled: !0, label: this.i18n.translate("hapticsOn") },
1840
+ { enabled: !1, label: this.i18n.translate("hapticsOff") }
1841
+ ];
1842
+ for (const y of A) {
1843
+ const g = document.createElement("button");
1844
+ g.type = "button", g.className = `axon-toggle-btn ${L === y.enabled ? "active" : ""}`, g.textContent = y.label, g.addEventListener("click", () => {
1845
+ localStorage.setItem("axon_surge_show_tutorial", String(y.enabled)), this.renderContent();
1846
+ }), x.appendChild(g);
1847
+ }
1848
+ d.appendChild(m), d.appendChild(x);
1849
+ const b = document.createElement("div");
1850
+ b.className = "axon-settings-credits", b.textContent = this.i18n.translate("creditsJam");
1851
+ const M = document.createElement("button");
1852
+ M.type = "button", M.className = "axon-start-button", M.style.padding = "12px 36px", M.style.fontSize = "14px", M.textContent = this.i18n.translate("closeButton"), M.addEventListener("click", () => {
1593
1853
  this.modal.close();
1594
- }), this.card.appendChild(t), this.card.appendChild(i), this.card.appendChild(n), this.card.appendChild(p), this.card.appendChild(d), this.card.appendChild(m);
1854
+ }), this.card.appendChild(t), this.card.appendChild(e), this.card.appendChild(n), this.card.appendChild(u), this.card.appendChild(d), this.card.appendChild(b), this.card.appendChild(M);
1595
1855
  }
1596
1856
  isHapticsEnabled() {
1597
1857
  return this.hapticsEnabled;
@@ -1603,64 +1863,136 @@ class it {
1603
1863
  this.modal.close();
1604
1864
  }
1605
1865
  }
1606
- const O = "axon-surge-onboarding-completed";
1607
- class et {
1608
- container;
1609
- i18n;
1610
- hasCompleted = !1;
1611
- isStep1Done = !1;
1612
- constructor(t, i) {
1613
- this.i18n = i, this.container = document.createElement("div"), this.container.className = "axon-onboarding", this.container.style.display = "none", t.appendChild(this.container);
1866
+ const U = "axon_surge_show_tutorial";
1867
+ class ot {
1868
+ isActive = !1;
1869
+ showWarning = !1;
1870
+ dummyLauncher = null;
1871
+ dummyTarget = null;
1872
+ initialLauncherPos = { x: 0, y: 0 };
1873
+ initialTargetPos = { x: 0, y: 0 };
1874
+ isTutorialEnabled() {
1614
1875
  try {
1615
- localStorage.getItem(O) === "true" && (this.hasCompleted = !0);
1876
+ return localStorage.getItem(U) !== "false";
1616
1877
  } catch {
1878
+ return !0;
1617
1879
  }
1618
1880
  }
1619
- isCompleted() {
1620
- return this.hasCompleted;
1881
+ setTutorialEnabled(t) {
1882
+ try {
1883
+ localStorage.setItem(U, String(t));
1884
+ } catch {
1885
+ }
1621
1886
  }
1622
- showStep1() {
1623
- this.hasCompleted || this.isStep1Done || (this.container.innerHTML = `
1624
- <div class="axon-onboarding-hint">
1625
- <div class="axon-onboarding-text">${this.i18n.translate("grabInstruction")}</div>
1626
- </div>
1627
- `, this.container.style.display = "flex");
1887
+ getLauncher() {
1888
+ return this.dummyLauncher;
1628
1889
  }
1629
- showStep2() {
1630
- this.hasCompleted || (this.isStep1Done = !0, this.container.innerHTML = `
1631
- <div class="axon-onboarding-hint">
1632
- <div class="axon-onboarding-text">${this.i18n.translate("throwInstruction")}</div>
1633
- </div>
1634
- `, this.container.style.display = "flex");
1890
+ getTarget() {
1891
+ return this.dummyTarget;
1635
1892
  }
1636
- complete() {
1637
- this.hasCompleted = !0, this.container.style.display = "none";
1638
- try {
1639
- localStorage.setItem(O, "true");
1640
- } catch {
1893
+ getStep() {
1894
+ return this.dummyLauncher && (this.dummyLauncher.isGrabbed || this.dummyLauncher.wasManipulated) ? 2 : 1;
1895
+ }
1896
+ start(t, e, i) {
1897
+ if (!this.isTutorialEnabled()) {
1898
+ this.isActive = !1;
1899
+ return;
1900
+ }
1901
+ this.isActive = !0, this.showWarning = !1, i.length = 0, this.initialLauncherPos = { x: t * 0.28, y: e * 0.28 }, this.initialTargetPos = { x: t * 0.72, y: e * 0.28 }, this.dummyLauncher = S.createEnemy(
1902
+ "piercer",
1903
+ this.initialLauncherPos,
1904
+ this.initialTargetPos
1905
+ ), this.dummyLauncher.velocity = { x: 0, y: 0 }, this.dummyTarget = S.createEnemy(
1906
+ "spore",
1907
+ this.initialTargetPos,
1908
+ this.initialLauncherPos
1909
+ ), this.dummyTarget.velocity = { x: 0, y: 0 }, i.push(this.dummyLauncher), i.push(this.dummyTarget);
1910
+ }
1911
+ update(t, e, i, s, a, l) {
1912
+ if (!this.isActive || !this.dummyLauncher || !this.dummyTarget) return;
1913
+ const r = this.dummyLauncher, n = this.dummyTarget;
1914
+ e.includes(r) || e.push(r), e.includes(n) || e.push(n);
1915
+ const o = n.position.x - r.position.x, h = n.position.y - r.position.y, c = Math.hypot(o, h);
1916
+ if (r.isGrabbed) {
1917
+ if (this.showWarning = !1, c <= r.radius + n.radius + 60) {
1918
+ l && l(), r.isGrabbed = !1, this.showWarning = !0, this.resetDummies(r, n);
1919
+ return;
1920
+ }
1921
+ return;
1922
+ }
1923
+ if (r.wasManipulated) {
1924
+ const u = Math.hypot(r.velocity.x, r.velocity.y);
1925
+ if (!r.isThrown || u < 70) {
1926
+ l && l(), this.showWarning = !0, this.resetDummies(r, n);
1927
+ return;
1928
+ }
1929
+ if (c <= r.getHitRadius() + n.getHitRadius()) {
1930
+ r.triggerDissolveDeath(), n.triggerDissolveDeath(), this.showWarning = !1, this.isActive = !1, a();
1931
+ return;
1932
+ }
1933
+ (r.position.x < -60 || r.position.x > i + 60 || r.position.y < -60 || r.position.y > s + 60 || u < 40) && (l && l(), this.showWarning = !0, this.resetDummies(r, n));
1641
1934
  }
1642
1935
  }
1643
- reset() {
1644
- this.hasCompleted || (this.isStep1Done = !1, this.container.style.display = "none");
1936
+ resetDummies(t, e) {
1937
+ t.reset(), e.reset(), t.position = { ...this.initialLauncherPos }, t.velocity = { x: 0, y: 0 }, t.active = !0, e.position = { ...this.initialTargetPos }, e.velocity = { x: 0, y: 0 }, e.active = !0;
1938
+ }
1939
+ complete() {
1940
+ this.isActive = !1, this.showWarning = !1;
1645
1941
  }
1646
1942
  }
1647
- class st {
1943
+ class rt {
1944
+ container;
1945
+ i18n;
1946
+ tutorialManager;
1947
+ bannerElement;
1948
+ textElement;
1949
+ checkboxElement;
1950
+ currentStep = 1;
1951
+ constructor(t, e, i) {
1952
+ this.i18n = e, this.tutorialManager = i, this.container = document.createElement("div"), this.container.className = "axon-tutorial-overlay", this.container.style.display = "none", t.appendChild(this.container), this.render();
1953
+ }
1954
+ render() {
1955
+ this.container.innerHTML = "", this.bannerElement = document.createElement("div"), this.bannerElement.className = "axon-tutorial-banner", this.textElement = document.createElement("div"), this.textElement.className = "axon-tutorial-text", this.updateBannerContent(), this.bannerElement.appendChild(this.textElement);
1956
+ const t = document.createElement("label");
1957
+ t.className = "axon-tutorial-checkbox-label", this.checkboxElement = document.createElement("input"), this.checkboxElement.type = "checkbox", this.checkboxElement.className = "axon-tutorial-checkbox", this.checkboxElement.checked = !this.tutorialManager.isTutorialEnabled(), this.checkboxElement.addEventListener("change", () => {
1958
+ this.tutorialManager.setTutorialEnabled(!this.checkboxElement.checked);
1959
+ });
1960
+ const e = document.createElement("span");
1961
+ e.textContent = this.i18n.translate("dontShowTutorialLabel"), t.appendChild(this.checkboxElement), t.appendChild(e), this.container.appendChild(this.bannerElement), this.container.appendChild(t);
1962
+ }
1963
+ updateBannerContent() {
1964
+ !this.bannerElement || !this.textElement || (this.tutorialManager.showWarning ? (this.bannerElement.classList.add("axon-tutorial-banner-warning"), this.textElement.textContent = this.i18n.translate("tutorialDragWarning")) : (this.bannerElement.classList.remove("axon-tutorial-banner-warning"), this.textElement.textContent = this.currentStep === 1 ? this.i18n.translate("tutorialStep1Text") : this.i18n.translate("tutorialStep2Text")));
1965
+ }
1966
+ updateStep(t) {
1967
+ this.currentStep = t, this.updateBannerContent();
1968
+ }
1969
+ updateLanguage() {
1970
+ this.render();
1971
+ }
1972
+ show() {
1973
+ this.currentStep = 1, this.render(), this.container.style.display = "flex";
1974
+ }
1975
+ hide() {
1976
+ this.container.style.display = "none";
1977
+ }
1978
+ }
1979
+ class ht {
1648
1980
  fillElement;
1649
1981
  killsCount = 0;
1650
1982
  currentLevel = 1;
1651
1983
  onLevelUpCallback;
1652
- constructor(t, i) {
1653
- this.onLevelUpCallback = i;
1654
- const e = document.createElement("div");
1655
- e.className = "axon-hud-level-track", this.fillElement = document.createElement("div"), this.fillElement.className = "axon-hud-level-fill", e.appendChild(this.fillElement), t.appendChild(e);
1984
+ constructor(t, e) {
1985
+ this.onLevelUpCallback = e;
1986
+ const i = document.createElement("div");
1987
+ i.className = "axon-hud-level-track", this.fillElement = document.createElement("div"), this.fillElement.className = "axon-hud-level-fill", i.appendChild(this.fillElement), t.appendChild(i);
1656
1988
  }
1657
1989
  getKillsRequiredForLevel(t) {
1658
1990
  return 16 + (t - 1) * 6;
1659
1991
  }
1660
1992
  addKill() {
1661
1993
  this.killsCount++;
1662
- const t = this.getKillsRequiredForLevel(this.currentLevel), i = Math.min(100, this.killsCount / t * 100);
1663
- this.fillElement.style.width = `${i}%`, this.killsCount >= t && (this.currentLevel++, this.killsCount = 0, this.fillElement.style.width = "0%", this.onLevelUpCallback && this.onLevelUpCallback(this.currentLevel));
1994
+ const t = this.getKillsRequiredForLevel(this.currentLevel), e = Math.min(100, this.killsCount / t * 100);
1995
+ this.fillElement.style.width = `${e}%`, this.killsCount >= t && (this.currentLevel++, this.killsCount = 0, this.fillElement.style.width = "0%", this.onLevelUpCallback && this.onLevelUpCallback(this.currentLevel));
1664
1996
  }
1665
1997
  getLevel() {
1666
1998
  return this.currentLevel;
@@ -1675,18 +2007,18 @@ class st {
1675
2007
  this.fillElement && this.fillElement.parentElement && (this.fillElement.parentElement.style.display = "none");
1676
2008
  }
1677
2009
  }
1678
- class at {
2010
+ class lt {
1679
2011
  haptics = {
1680
2012
  impact: async (t) => {
1681
2013
  if ("vibrate" in navigator) {
1682
- const i = t === "light" ? 10 : t === "medium" ? 25 : 40;
1683
- navigator.vibrate(i);
2014
+ const e = t === "light" ? 10 : t === "medium" ? 25 : 40;
2015
+ navigator.vibrate(e);
1684
2016
  }
1685
2017
  },
1686
2018
  notification: async (t) => {
1687
2019
  if ("vibrate" in navigator) {
1688
- const i = t === "error" ? [30, 40, 30] : [20, 20];
1689
- navigator.vibrate(i);
2020
+ const e = t === "error" ? [30, 40, 30] : [20, 20];
2021
+ navigator.vibrate(e);
1690
2022
  }
1691
2023
  },
1692
2024
  selectionChanged: async () => {
@@ -1715,7 +2047,7 @@ class at {
1715
2047
  }
1716
2048
  };
1717
2049
  }
1718
- class nt {
2050
+ class ct {
1719
2051
  container;
1720
2052
  canvas;
1721
2053
  i18n;
@@ -1731,7 +2063,8 @@ class nt {
1731
2063
  hud;
1732
2064
  startMenu;
1733
2065
  settingsModal;
1734
- onboarding;
2066
+ interactiveTutorial;
2067
+ tutorialOverlay;
1735
2068
  progressBar;
1736
2069
  core;
1737
2070
  enemies = [];
@@ -1745,23 +2078,22 @@ class nt {
1745
2078
  combo = { value: 0 };
1746
2079
  isRunning = !1;
1747
2080
  isPaused = !1;
1748
- firstPlay = !0;
1749
2081
  constructor(t) {
1750
- this.container = t.root, this.container.classList.add("axon-game-root"), this.i18n = new J(t.language), this.themeManager = new q(t.theme), this.platform = t.platform || new at(), this.canvas = document.createElement("canvas"), this.canvas.className = "axon-canvas", this.container.appendChild(this.canvas), this.resizeCanvas(), window.addEventListener("resize", () => this.resizeCanvas()), this.eventBus = new G(), this.core = new U(this.canvas.width / 2, this.canvas.height / 2), this.inputManager = new H(this.canvas), this.physicsEngine = new z(this.eventBus, this.i18n), this.waveDirector = new _(), this.renderer = new Q(this.canvas, this.themeManager), this.juice = new F(), this.settingsModal = new it(
2082
+ this.container = t.root, this.container.classList.add("axon-game-root"), this.i18n = new Y(t.language), this.themeManager = new j(t.theme, this.container), this.platform = t.platform || new lt(), this.canvas = document.createElement("canvas"), this.canvas.className = "axon-canvas", this.container.appendChild(this.canvas), this.resizeCanvas(), window.addEventListener("resize", () => this.resizeCanvas()), this.eventBus = new B(), this.core = new K(this.canvas.width / 2, this.canvas.height / 2), this.inputManager = new W(this.canvas), this.physicsEngine = new z(this.eventBus, this.i18n), this.waveDirector = new q(), this.renderer = new it(this.canvas, this.themeManager), this.juice = new F(), this.settingsModal = new nt(
1751
2083
  this.container,
1752
2084
  this.i18n,
1753
2085
  this.themeManager,
1754
2086
  this.platform,
1755
- (i) => this.onLanguageChanged(i),
2087
+ (e) => this.onLanguageChanged(e),
1756
2088
  () => {
1757
2089
  this.isPaused = !1;
1758
2090
  }
1759
- ), this.onboarding = new et(this.container, this.i18n), this.hud = new j(this.container, this.i18n, () => {
2091
+ ), this.interactiveTutorial = new ot(), this.tutorialOverlay = new rt(this.container, this.i18n, this.interactiveTutorial), this.hud = new st(this.container, this.i18n, () => {
1760
2092
  this.isPaused = !0, this.settingsModal.show();
1761
- }), this.hud.show(), this.progressBar = new st(this.hud.progressSlot, (i) => {
1762
- this.waveDirector.wave = i;
1763
- }), this.startMenu = new tt(this.container, this.i18n, () => this.startGame()), this.initAmbientArena(), this.gameLoop = new B(
1764
- (i) => this.update(i),
2093
+ }), this.hud.show(), this.progressBar = new ht(this.hud.progressSlot, (e) => {
2094
+ this.waveDirector.wave = e;
2095
+ }), this.startMenu = new at(this.container, this.i18n, () => this.startGame()), this.initAmbientArena(), this.gameLoop = new H(
2096
+ (e) => this.update(e),
1765
2097
  () => this.render()
1766
2098
  ), this.setupEvents(), this.gameLoop.start();
1767
2099
  }
@@ -1772,46 +2104,47 @@ class nt {
1772
2104
  this.themeManager.setTheme(t);
1773
2105
  }
1774
2106
  onLanguageChanged(t) {
1775
- this.startMenu.renderContent(), this.hud.renderLabels();
2107
+ this.startMenu.renderContent(), this.hud.renderLabels(), this.tutorialOverlay.updateLanguage();
1776
2108
  }
1777
2109
  initAmbientArena() {
1778
2110
  this.ambientEnemies = [];
1779
2111
  const t = ["piercer", "spore", "cluster", "parasite"];
1780
- for (let i = 0; i < 16; i++) {
1781
- const e = t[i % t.length], s = i * Math.PI * 2 / 16, a = 180 + Math.random() * 220, c = {
2112
+ for (let e = 0; e < 16; e++) {
2113
+ const i = t[e % t.length], s = e * Math.PI * 2 / 16, a = 180 + Math.random() * 220, l = {
1782
2114
  x: this.canvas.width / 2 + Math.cos(s) * a,
1783
2115
  y: this.canvas.height / 2 + Math.sin(s) * a
1784
- }, h = L.createEnemy(e, c, {
1785
- x: c.x + Math.sin(s) * 100,
1786
- y: c.y - Math.cos(s) * 100
2116
+ }, r = S.createEnemy(i, l, {
2117
+ x: l.x + Math.sin(s) * 100,
2118
+ y: l.y - Math.cos(s) * 100
1787
2119
  });
1788
- this.ambientEnemies.push(h);
2120
+ this.ambientEnemies.push(r);
1789
2121
  }
1790
2122
  }
1791
2123
  resizeCanvas() {
1792
- this.canvas.width = this.container.clientWidth || window.innerWidth, this.canvas.height = this.container.clientHeight || window.innerHeight, this.core && (this.core.position = { x: this.canvas.width / 2, y: this.canvas.height / 2 });
2124
+ const t = this.container.clientWidth || window.innerWidth, e = this.container.clientHeight || window.innerHeight, i = 1100, s = 750, a = t / Math.max(1, e);
2125
+ a < 1 ? (this.canvas.width = i, this.canvas.height = Math.round(i / a)) : t < 1e3 || e < s ? (this.canvas.height = s, this.canvas.width = Math.round(s * a)) : (this.canvas.width = t, this.canvas.height = e), this.core && (this.core.position = { x: this.canvas.width / 2, y: this.canvas.height / 2 });
1793
2126
  }
1794
2127
  setupEvents() {
1795
2128
  this.eventBus.on("onCoreDamaged", () => {
1796
2129
  this.settingsModal.isHapticsEnabled() && this.platform.haptics.notification("error");
1797
2130
  }), this.eventBus.on("onGameOver", () => {
1798
- this.isRunning = !1, this.onboarding.complete(), this.progressBar.hide(), this.initAmbientArena(), this.startMenu.show();
2131
+ this.isRunning = !1, this.tutorialOverlay.hide(), this.progressBar.hide(), this.initAmbientArena(), this.startMenu.show();
1799
2132
  });
1800
- const t = () => {
2133
+ const t = (i = !1) => {
1801
2134
  if (!this.isRunning || this.isPaused) return;
1802
- this.inputManager.tryGrab(this.enemies) && (this.firstPlay && !this.onboarding.isCompleted() && this.onboarding.showStep2(), this.settingsModal.isHapticsEnabled() && this.platform.haptics.impact("light"));
1803
- }, i = () => {
2135
+ this.inputManager.tryGrab(this.enemies, i) && this.settingsModal.isHapticsEnabled() && this.platform.haptics.impact("light");
2136
+ }, e = () => {
1804
2137
  if (!this.isRunning || this.isPaused) return;
1805
- this.inputManager.releaseAndThrow() && (this.firstPlay && (this.onboarding.complete(), this.firstPlay = !1), this.settingsModal.isHapticsEnabled() && this.platform.haptics.impact("medium"));
2138
+ this.inputManager.releaseAndThrow() && this.settingsModal.isHapticsEnabled() && this.platform.haptics.impact("medium");
1806
2139
  };
1807
- this.canvas.addEventListener("mousedown", (e) => {
1808
- e.button === 0 && t();
1809
- }), this.canvas.addEventListener("mouseup", (e) => {
1810
- e.button === 0 && i();
1811
- }), this.canvas.addEventListener("touchstart", t, { passive: !0 }), this.canvas.addEventListener("touchend", i, { passive: !0 }), this.canvas.addEventListener("touchcancel", i, { passive: !0 });
2140
+ this.canvas.addEventListener("mousedown", (i) => {
2141
+ i.button === 0 && t(!1);
2142
+ }), this.canvas.addEventListener("mouseup", (i) => {
2143
+ i.button === 0 && e();
2144
+ }), this.canvas.addEventListener("touchstart", () => t(!0), { passive: !0 }), this.canvas.addEventListener("touchend", e, { passive: !0 }), this.canvas.addEventListener("touchcancel", e, { passive: !0 });
1812
2145
  }
1813
2146
  startGame() {
1814
- this.score.value = 0, this.combo.value = 0, this.enemies = [], this.ambientEnemies = [], this.pools = [], this.vortices = [], this.shockwaves = [], this.particles = [], this.floatingTexts = [], this.core.reset(this.canvas.width / 2, this.canvas.height / 2), this.waveDirector.reset(), this.inputManager.reset(), this.hud.show(), this.hud.update(1, 0), this.progressBar.reset(), this.progressBar.show(), this.isPaused = !1, this.isRunning = !0, this.firstPlay && this.onboarding.showStep1();
2147
+ this.score.value = 0, this.combo.value = 0, this.enemies = [], this.ambientEnemies = [], this.pools = [], this.vortices = [], this.shockwaves = [], this.particles = [], this.floatingTexts = [], this.core.reset(this.canvas.width / 2, this.canvas.height / 2), this.waveDirector.reset(), this.inputManager.reset(), this.hud.show(), this.hud.update(1, 0), this.progressBar.reset(), this.progressBar.show(), this.isPaused = !1, this.isRunning = !0, this.interactiveTutorial.isTutorialEnabled() ? (this.interactiveTutorial.start(this.canvas.width, this.canvas.height, this.enemies), this.tutorialOverlay.show()) : (this.interactiveTutorial.isActive = !1, this.tutorialOverlay.hide());
1815
2148
  }
1816
2149
  update(t) {
1817
2150
  if (this.core.update(t), !this.isRunning || this.isPaused) {
@@ -1819,14 +2152,28 @@ class nt {
1819
2152
  e.update(t), e.position.x < -40 && (e.position.x = this.canvas.width + 40), e.position.x > this.canvas.width + 40 && (e.position.x = -40), e.position.y < -40 && (e.position.y = this.canvas.height + 40), e.position.y > this.canvas.height + 40 && (e.position.y = -40);
1820
2153
  return;
1821
2154
  }
1822
- const i = this.waveDirector.update(
1823
- t,
1824
- this.enemies,
1825
- this.canvas.width,
1826
- this.canvas.height,
1827
- this.core.position
1828
- );
1829
- i && this.enemies.push(i), this.juice.hitstopTime <= 0 && this.physicsEngine.update(
2155
+ if (this.interactiveTutorial.isActive)
2156
+ this.interactiveTutorial.update(
2157
+ t,
2158
+ this.enemies,
2159
+ this.canvas.width,
2160
+ this.canvas.height,
2161
+ () => {
2162
+ this.tutorialOverlay.hide();
2163
+ },
2164
+ () => this.inputManager.forceRelease()
2165
+ ), this.tutorialOverlay.updateStep(this.interactiveTutorial.getStep());
2166
+ else {
2167
+ const e = this.waveDirector.update(
2168
+ t,
2169
+ this.enemies,
2170
+ this.canvas.width,
2171
+ this.canvas.height,
2172
+ this.core.position
2173
+ );
2174
+ e && this.enemies.push(e);
2175
+ }
2176
+ this.juice.hitstopTime <= 0 && this.physicsEngine.update(
1830
2177
  t,
1831
2178
  this.core,
1832
2179
  this.enemies,
@@ -1841,7 +2188,7 @@ class nt {
1841
2188
  this.canvas.width,
1842
2189
  this.canvas.height,
1843
2190
  () => this.progressBar.addKill()
1844
- ), this.hud.update(this.progressBar.getLevel(), this.combo.value), this.juice.update(t, this.floatingTexts, this.particles);
2191
+ ), this.hud.update(this.progressBar.getLevel(), this.combo.value), this.juice.update(t, this.floatingTexts, this.particles), this.enemies = this.enemies.filter((e) => e.active);
1845
2192
  }
1846
2193
  render() {
1847
2194
  const t = this.isRunning ? this.enemies : this.ambientEnemies;
@@ -1855,18 +2202,20 @@ class nt {
1855
2202
  this.floatingTexts,
1856
2203
  this.juice,
1857
2204
  this.inputManager.grabbedEnemy,
1858
- this.inputManager.pointerPosition
2205
+ this.inputManager.pointerPosition,
2206
+ this.progressBar.getLevel(),
2207
+ this.interactiveTutorial.isActive ? this.interactiveTutorial : void 0
1859
2208
  );
1860
2209
  }
1861
2210
  }
1862
- function ot(x) {
1863
- return new nt(x);
2211
+ function dt(E) {
2212
+ return new ct(E);
1864
2213
  }
1865
2214
  export {
1866
- at as BrowserPlatform,
1867
- nt as GameEngine,
2215
+ lt as BrowserPlatform,
2216
+ ct as GameEngine,
1868
2217
  k as LANGUAGES,
1869
- q as ThemeManager,
1870
- ot as createAxonSurge,
1871
- V as isLanguage
2218
+ j as ThemeManager,
2219
+ dt as createAxonSurge,
2220
+ R as isLanguage
1872
2221
  };