@gamebob/axon-surge 0.5.0 → 0.6.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,15 +1,15 @@
1
- class G {
1
+ class k {
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();
@@ -21,8 +21,8 @@ class B {
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 H {
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 N {
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 K {
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 W {
200
222
  cellSize;
201
223
  grid = /* @__PURE__ */ new Map();
202
224
  constructor(t = 100) {
@@ -206,24 +228,24 @@ 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
- class F {
248
+ class V {
227
249
  hitstopTime = 0;
228
250
  shakeTime = 0;
229
251
  shakeDuration = 0.14;
@@ -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,9 +623,15 @@ const I = {
517
623
  closeButton: "关闭",
518
624
  grabInstruction: "按住以抓住敌人",
519
625
  throwInstruction: "拖动并释放以抛投",
520
- comboText: "多重击杀 x{combo}!"
521
- }
522
- }, k = [
626
+ comboText: "多重击杀 x{combo}!",
627
+ tutorialInstruction: "弹射敌人撞击另一个敌人!",
628
+ dontShowTutorialLabel: "不再显示教程",
629
+ tutorialSettingLabel: "启动时显示教程",
630
+ tutorialStep1Text: "步骤 1: 按住指定的敌人",
631
+ tutorialStep2Text: "步骤 2: 朝目标快速挥动抛投",
632
+ tutorialDragWarning: "最佳策略是快速挥动抛投!"
633
+ }
634
+ }, U = [
523
635
  "es",
524
636
  "en",
525
637
  "fr",
@@ -536,30 +648,30 @@ const I = {
536
648
  "ko",
537
649
  "zh"
538
650
  ];
539
- function V(x) {
540
- return k.includes(x);
651
+ function F(E) {
652
+ return U.includes(E);
541
653
  }
542
- const N = "axon_surge_language";
543
- class J {
654
+ const O = "axon_surge_language";
655
+ class Y {
544
656
  currentLanguage;
545
657
  constructor(t) {
546
- if (t && I[t])
658
+ if (t && w[t])
547
659
  this.currentLanguage = t;
548
660
  else {
549
- let i = "es";
661
+ let e = "es";
550
662
  try {
551
- const e = localStorage.getItem(N);
552
- e && V(e) && (i = e);
663
+ const i = localStorage.getItem(O);
664
+ i && F(i) && (e = i);
553
665
  } catch {
554
666
  }
555
- this.currentLanguage = i;
667
+ this.currentLanguage = e;
556
668
  }
557
669
  }
558
670
  setLanguage(t) {
559
- if (I[t]) {
671
+ if (w[t]) {
560
672
  this.currentLanguage = t;
561
673
  try {
562
- localStorage.setItem(N, t);
674
+ localStorage.setItem(O, t);
563
675
  } catch {
564
676
  }
565
677
  }
@@ -567,19 +679,19 @@ class J {
567
679
  getLanguage() {
568
680
  return this.currentLanguage;
569
681
  }
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));
682
+ translate(t, e) {
683
+ let s = (w[this.currentLanguage] || w.es)[t] || w.es[t] || String(t);
684
+ return e && Object.entries(e).forEach(([a, l]) => {
685
+ s = s.replace(`{${a}}`, String(l));
574
686
  }), s;
575
687
  }
576
688
  }
577
- class Y {
689
+ class J {
578
690
  execute(t) {
579
- const { thrownEnemy: i, targetEnemy: e, shockwaves: s, particles: a, floatingTexts: c } = t;
580
- e.active = !1, s.push({
691
+ const { thrownEnemy: e, targetEnemy: i, shockwaves: s, particles: a, floatingTexts: l } = t;
692
+ i.active = !1, s.push({
581
693
  id: Math.random().toString(),
582
- position: { ...e.position },
694
+ position: { ...i.position },
583
695
  radius: 10,
584
696
  maxRadius: 180,
585
697
  color: "#ff2a5f",
@@ -587,11 +699,11 @@ class Y {
587
699
  lifetime: 0,
588
700
  maxLifetime: 0.5
589
701
  });
590
- for (let h = 0; h < 30; h++) {
702
+ for (let r = 0; r < 30; r++) {
591
703
  const n = Math.random() * Math.PI * 2, o = 180 + Math.random() * 320;
592
704
  a.push({
593
705
  id: Math.random().toString(),
594
- position: { ...e.position },
706
+ position: { ...i.position },
595
707
  velocity: { x: Math.cos(n) * o, y: Math.sin(n) * o },
596
708
  color: "#ff2a5f",
597
709
  radius: 3 + Math.random() * 4,
@@ -600,10 +712,10 @@ class Y {
600
712
  maxLifetime: 0.5
601
713
  });
602
714
  }
603
- c.push({
715
+ l.push({
604
716
  id: Math.random().toString(),
605
717
  text: "PIERCING SLICE",
606
- position: { ...e.position },
718
+ position: { ...i.position },
607
719
  velocity: { x: 0, y: -50 },
608
720
  color: "#ff2a5f",
609
721
  alpha: 1,
@@ -613,10 +725,10 @@ class Y {
613
725
  });
614
726
  }
615
727
  }
616
- class W {
728
+ class Z {
617
729
  execute(t) {
618
- const { thrownEnemy: i, pools: e, shockwaves: s, particles: a, floatingTexts: c, eventBus: h } = t, n = i.position;
619
- e.push({
730
+ const { thrownEnemy: e, pools: i, shockwaves: s, particles: a, floatingTexts: l, eventBus: r } = t, n = e.position;
731
+ i.push({
620
732
  id: Math.random().toString(),
621
733
  position: { ...n },
622
734
  radius: 220,
@@ -634,11 +746,11 @@ class W {
634
746
  maxLifetime: 0.6
635
747
  });
636
748
  for (let o = 0; o < 45; o++) {
637
- const r = Math.random() * Math.PI * 2, l = 120 + Math.random() * 260;
749
+ const h = Math.random() * Math.PI * 2, c = 120 + Math.random() * 260;
638
750
  a.push({
639
751
  id: Math.random().toString(),
640
752
  position: { ...n },
641
- velocity: { x: Math.cos(r) * l, y: Math.sin(r) * l },
753
+ velocity: { x: Math.cos(h) * c, y: Math.sin(h) * c },
642
754
  color: "#39ff14",
643
755
  radius: 4 + Math.random() * 5,
644
756
  alpha: 1,
@@ -646,7 +758,7 @@ class W {
646
758
  maxLifetime: 0.9
647
759
  });
648
760
  }
649
- c.push({
761
+ l.push({
650
762
  id: Math.random().toString(),
651
763
  text: "MASSIVE SPORE NEBULA",
652
764
  position: { ...n },
@@ -656,13 +768,13 @@ class W {
656
768
  lifetime: 0,
657
769
  maxLifetime: 1.2,
658
770
  size: 26
659
- }), i.active = !1, h.emit("onPoolCreated", { position: n });
771
+ }), e.active = !1, r.emit("onPoolCreated", { position: n });
660
772
  }
661
773
  }
662
774
  class X {
663
775
  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({
776
+ const { thrownEnemy: e, targetEnemy: i, allEnemies: s, shockwaves: a, particles: l, floatingTexts: r } = t, n = i.position;
777
+ e.active = !1, i.active = !1, a.push({
666
778
  id: Math.random().toString(),
667
779
  position: { ...n },
668
780
  radius: 15,
@@ -673,21 +785,21 @@ class X {
673
785
  maxLifetime: 0.6
674
786
  });
675
787
  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
788
+ const h = o * Math.PI * 2 / 6, c = {
789
+ x: n.x + Math.cos(h) * 15,
790
+ y: n.y + Math.sin(h) * 15
791
+ }, u = S.createEnemy("micro", c, {
792
+ x: c.x + Math.cos(h) * 200,
793
+ y: c.y + Math.sin(h) * 200
682
794
  });
683
- p.isThrown = !0, s.push(p);
795
+ u.isThrown = !0, s.push(u);
684
796
  }
685
797
  for (let o = 0; o < 35; o++) {
686
- const r = Math.random() * Math.PI * 2, l = 200 + Math.random() * 300;
687
- c.push({
798
+ const h = Math.random() * Math.PI * 2, c = 200 + Math.random() * 300;
799
+ l.push({
688
800
  id: Math.random().toString(),
689
801
  position: { ...n },
690
- velocity: { x: Math.cos(r) * l, y: Math.sin(r) * l },
802
+ velocity: { x: Math.cos(h) * c, y: Math.sin(h) * c },
691
803
  color: "#ffd700",
692
804
  radius: 4 + Math.random() * 4,
693
805
  alpha: 1,
@@ -695,7 +807,7 @@ class X {
695
807
  maxLifetime: 0.6
696
808
  });
697
809
  }
698
- h.push({
810
+ r.push({
699
811
  id: Math.random().toString(),
700
812
  text: "CLUSTER DETONATION",
701
813
  position: { ...n },
@@ -710,41 +822,41 @@ class X {
710
822
  }
711
823
  class $ {
712
824
  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
825
+ const { thrownEnemy: e, targetEnemy: i, vortices: s, shockwaves: a } = t, l = {
826
+ x: (e.position.x + i.position.x) / 2,
827
+ y: (e.position.y + i.position.y) / 2
716
828
  };
717
829
  s.push({
718
830
  id: Math.random().toString(),
719
- position: c,
831
+ position: l,
720
832
  radius: 480,
721
833
  duration: 0,
722
834
  maxDuration: 6,
723
835
  pullForce: 3500
724
836
  }), a.push({
725
837
  id: Math.random().toString(),
726
- position: c,
838
+ position: l,
727
839
  radius: 20,
728
840
  maxRadius: 480,
729
841
  color: "#9d4edd",
730
842
  alpha: 1,
731
843
  lifetime: 0,
732
844
  maxLifetime: 0.65
733
- }), i.triggerDissolveDeath(), e.triggerDissolveDeath();
845
+ }), e.triggerDissolveDeath(), i.triggerDissolveDeath();
734
846
  }
735
847
  }
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
848
+ class S {
849
+ static createEnemy(t, e, i) {
850
+ const s = `enemy_${Date.now()}_${Math.random()}`, a = new N(s);
851
+ return this.configureEnemy(a, t, e, i), a;
852
+ }
853
+ static configureEnemy(t, e, i, s) {
854
+ t.type = e, t.position = { ...i }, t.active = !0, t.isGrabbed = !1, t.isThrown = !1;
855
+ const a = s.x - i.x, l = s.y - i.y, r = Math.atan2(l, a);
856
+ let n = 70, o = 100, h = 20, c = "#ff2a5f", u = null;
857
+ 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 = {
858
+ x: Math.cos(r) * n,
859
+ y: Math.sin(r) * n
748
860
  };
749
861
  }
750
862
  }
@@ -754,60 +866,60 @@ class z {
754
866
  i18n;
755
867
  currentThrowKills = 0;
756
868
  currentThrowPos = null;
757
- constructor(t, i) {
758
- this.spatialHash = new K(100), this.eventBus = t, this.i18n = i;
869
+ constructor(t, e) {
870
+ this.spatialHash = new W(100), this.eventBus = t, this.i18n = e;
759
871
  }
760
- update(t, i, e, s, a, c, h, n, o, r, l, p, f, g) {
872
+ update(t, e, i, s, a, l, r, n, o, h, c, u, p, f) {
761
873
  this.spatialHash.clear();
762
- for (const d of e)
874
+ for (const d of i)
763
875
  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];
876
+ for (let d = l.length - 1; d >= 0; d--) {
877
+ const m = l[d];
766
878
  if (!m) continue;
767
879
  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);
880
+ const x = m.lifetime / m.maxLifetime;
881
+ m.radius = m.maxRadius * x, m.alpha = Math.max(0, 1 - x), m.lifetime >= m.maxLifetime && l.splice(d, 1);
770
882
  }
771
883
  for (let d = a.length - 1; d >= 0; d--) {
772
884
  const m = a[d];
773
885
  if (m) {
774
886
  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;
887
+ for (const x of i) {
888
+ if (!x.active || x.isGrabbed || x.isDying || x.isThrown && x.type === "piercer") continue;
889
+ const L = m.position.x - x.position.x, A = m.position.y - x.position.y, b = Math.hypot(L, A);
890
+ if (b > 2 && b <= m.radius) {
891
+ const M = Math.pow(1 - b / m.radius, 0.7), y = m.pullForce * M, g = Math.atan2(A, L);
892
+ 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
893
  }
782
894
  }
783
895
  m.duration >= m.maxDuration && a.splice(d, 1);
784
896
  }
785
897
  }
786
- for (const d of e) {
898
+ for (const d of i) {
787
899
  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) {
900
+ const m = e.position.x - d.position.x, x = e.position.y - d.position.y;
901
+ if (Math.hypot(m, x) <= e.radius + d.radius) {
790
902
  d.active = !1;
791
- const v = i.takeDamage();
792
- this.eventBus.emit("onCoreDamaged", { currentIntegrity: i.integrity }), c.push({
903
+ const A = e.takeDamage();
904
+ this.eventBus.emit("onCoreDamaged", { currentIntegrity: e.integrity }), l.push({
793
905
  id: Math.random().toString(),
794
- position: { ...i.position },
906
+ position: { ...e.position },
795
907
  radius: 20,
796
- maxRadius: Math.max(p, f) * 1.3,
908
+ maxRadius: Math.max(u, p) * 1.3,
797
909
  color: "#00f0ff",
798
910
  alpha: 1,
799
911
  lifetime: 0,
800
912
  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({
913
+ }), o.triggerScreenShake({ x: m, y: x }, 25), o.triggerHitstop(0.15), o.triggerFlash(0.6);
914
+ for (const b of i)
915
+ if (b.active && !b.isGrabbed) {
916
+ b.triggerDissolveDeath();
917
+ for (let M = 0; M < 8; M++) {
918
+ const y = Math.random() * Math.PI * 2, g = 100 + Math.random() * 200;
919
+ r.push({
808
920
  id: Math.random().toString(),
809
- position: { ...S.position },
810
- velocity: { x: Math.cos(M) * E, y: Math.sin(M) * E },
921
+ position: { ...b.position },
922
+ velocity: { x: Math.cos(y) * g, y: Math.sin(y) * g },
811
923
  color: "#00f0ff",
812
924
  radius: 3 + Math.random() * 3,
813
925
  alpha: 1,
@@ -819,112 +931,135 @@ class z {
819
931
  n.push({
820
932
  id: Math.random().toString(),
821
933
  text: "CORE OVERLOAD PULSE!",
822
- position: { ...i.position },
934
+ position: { ...e.position },
823
935
  velocity: { x: 0, y: -90 },
824
936
  color: "#00f0ff",
825
937
  alpha: 1,
826
938
  lifetime: 0,
827
939
  maxLifetime: 1.5,
828
940
  size: 32
829
- }), (!v || i.integrity <= 0) && this.eventBus.emit("onGameOver", { score: l.value, wave: 1 });
941
+ }), (!A || e.integrity <= 0) && this.eventBus.emit("onGameOver", { score: c.value, wave: 1 });
830
942
  break;
831
943
  }
832
944
  }
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({
945
+ let T = !1;
946
+ for (const d of i)
947
+ if (!(!d.active || !d.isThrown || d.isDying)) {
948
+ if (T = !0, d.position.x < -120 || d.position.x > u + 120 || d.position.y < -120 || d.position.y > p + 120) {
949
+ d.active = !1, d.isThrown = !1;
950
+ continue;
951
+ }
952
+ for (const m of i) {
953
+ if (m === d || !m.active || m.isGrabbed || m.isDying) continue;
954
+ const x = m.position.x - d.position.x, L = m.position.y - d.position.y;
955
+ if (Math.hypot(x, L) <= d.getHitRadius() + m.getHitRadius()) {
956
+ this.currentThrowPos = { x: d.position.x, y: d.position.y };
957
+ const b = Math.atan2(d.velocity.y, d.velocity.x);
958
+ if (d.type === "piercer") {
959
+ this.currentThrowKills++, this.killEnemyWithChainReaction(m, b, s, a, l, r, i), o.triggerHitstop(0.05), o.triggerScreenShake({ x, y: L }, 7), l.push({
861
960
  id: Math.random().toString(),
862
- position: { ...u.position },
863
- velocity: { x: Math.cos(E) * w, y: Math.sin(E) * w },
961
+ position: { ...m.position },
962
+ radius: 10,
963
+ maxRadius: 180,
864
964
  color: "#ff2a5f",
865
- radius: 3 + Math.random() * 3,
866
965
  alpha: 1,
867
966
  lifetime: 0,
868
- maxLifetime: 0.4
967
+ maxLifetime: 0.45
869
968
  });
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({
969
+ for (let M = 0; M < 16; M++) {
970
+ const y = Math.random() * Math.PI * 2, g = 150 + Math.random() * 300;
971
+ r.push({
972
+ id: Math.random().toString(),
973
+ position: { ...m.position },
974
+ velocity: { x: Math.cos(y) * g, y: Math.sin(y) * g },
975
+ color: "#ff2a5f",
976
+ radius: 3 + Math.random() * 3,
977
+ alpha: 1,
978
+ lifetime: 0,
979
+ maxLifetime: 0.4
980
+ });
981
+ }
982
+ f && f();
983
+ } else {
984
+ const M = d.type === m.type, y = M ? 360 : 250;
985
+ l.push({
887
986
  id: Math.random().toString(),
888
987
  position: { ...this.currentThrowPos },
889
- velocity: { x: Math.cos(w) * R, y: Math.sin(w) * R },
988
+ radius: 15,
989
+ maxRadius: y,
890
990
  color: d.color,
891
- radius: 4 + Math.random() * 5,
892
991
  alpha: 1,
893
992
  lifetime: 0,
894
- maxLifetime: 0.65
993
+ maxLifetime: 0.55
895
994
  });
995
+ for (let g = 0; g < 45; g++) {
996
+ const I = Math.random() * Math.PI * 2, v = 200 + Math.random() * 450;
997
+ r.push({
998
+ id: Math.random().toString(),
999
+ position: { ...this.currentThrowPos },
1000
+ velocity: { x: Math.cos(I) * v, y: Math.sin(I) * v },
1001
+ color: d.color,
1002
+ radius: 4 + Math.random() * 6,
1003
+ alpha: 1,
1004
+ lifetime: 0,
1005
+ maxLifetime: 0.7
1006
+ });
1007
+ }
1008
+ if (M) {
1009
+ if (this.currentThrowKills += 2, o.triggerHitstop(0.14), o.triggerFlash(0.5), o.triggerScreenShake({ x, y: L }, 16), n.push({
1010
+ id: Math.random().toString(),
1011
+ text: "COLOR SYNERGY!",
1012
+ position: { ...this.currentThrowPos },
1013
+ velocity: { x: 0, y: -80 },
1014
+ color: d.color,
1015
+ alpha: 1,
1016
+ lifetime: 0,
1017
+ maxLifetime: 1.2,
1018
+ size: 26
1019
+ }), d.type === "spore")
1020
+ s.push({
1021
+ id: Math.random().toString(),
1022
+ position: { ...this.currentThrowPos },
1023
+ radius: 340,
1024
+ duration: 0,
1025
+ maxDuration: 10,
1026
+ damage: 100
1027
+ });
1028
+ else if (d.type === "parasite")
1029
+ a.push({
1030
+ id: Math.random().toString(),
1031
+ position: { ...this.currentThrowPos },
1032
+ radius: 600,
1033
+ duration: 0,
1034
+ maxDuration: 7,
1035
+ pullForce: 5e3
1036
+ });
1037
+ else if (d.type === "cluster")
1038
+ for (let g = 0; g < 8; g++) {
1039
+ const I = g * Math.PI * 2 / 8, v = {
1040
+ x: this.currentThrowPos.x + Math.cos(I) * 15,
1041
+ y: this.currentThrowPos.y + Math.sin(I) * 15
1042
+ }, P = S.createEnemy("micro", v, {
1043
+ x: v.x + Math.cos(I) * 220,
1044
+ y: v.y + Math.sin(I) * 220
1045
+ });
1046
+ P.isThrown = !0, i.push(P);
1047
+ }
1048
+ this.killEnemyWithChainReaction(d, b, s, a, l, r, i), this.killEnemyWithChainReaction(m, b, s, a, l, r, i);
1049
+ } else
1050
+ 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);
1051
+ for (const g of i) {
1052
+ if (g === d || g === m || !g.active || g.isGrabbed || g.isDying) continue;
1053
+ const I = g.position.x - this.currentThrowPos.x, v = g.position.y - this.currentThrowPos.y;
1054
+ Math.hypot(I, v) <= y && (this.killEnemyWithChainReaction(g, b, s, a, l, r, i), this.currentThrowKills++);
1055
+ }
1056
+ f && f();
1057
+ break;
896
1058
  }
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
1059
  }
924
1060
  }
925
1061
  }
926
- }
927
- r.value = this.currentThrowKills, !b && this.currentThrowKills > 0 && (this.currentThrowKills >= 2 && this.currentThrowPos && n.push({
1062
+ h.value = this.currentThrowKills, !T && this.currentThrowKills > 0 && (this.currentThrowKills >= 2 && this.currentThrowPos && n.push({
928
1063
  id: Math.random().toString(),
929
1064
  text: `MULTIKILL x${this.currentThrowKills}!`,
930
1065
  position: { ...this.currentThrowPos },
@@ -934,21 +1069,21 @@ class z {
934
1069
  lifetime: 0,
935
1070
  maxLifetime: 1.4,
936
1071
  size: 32
937
- }), this.eventBus.emit("onComboUpdated", { combo: r.value }), this.currentThrowKills = 0, this.currentThrowPos = null);
1072
+ }), this.eventBus.emit("onComboUpdated", { combo: h.value }), this.currentThrowKills = 0, this.currentThrowPos = null);
938
1073
  for (let d = s.length - 1; d >= 0; d--) {
939
1074
  const m = s[d];
940
1075
  if (m) {
941
1076
  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());
1077
+ for (const x of i) {
1078
+ if (!x.active || x.isGrabbed || x.isDying || x.isThrown && x.type === "piercer") continue;
1079
+ const L = x.position.x - m.position.x, A = x.position.y - m.position.y;
1080
+ Math.hypot(L, A) <= m.radius && (this.killEnemyWithChainReaction(x, 0, s, a, l, r, i), this.currentThrowKills++, f && f());
946
1081
  }
947
1082
  m.duration >= m.maxDuration && s.splice(d, 1);
948
1083
  }
949
1084
  }
950
1085
  }
951
- killEnemyWithChainReaction(t, i, e, s, a, c, h) {
1086
+ killEnemyWithChainReaction(t, e, i, s, a, l, r) {
952
1087
  if (!(!t.active || t.isDying))
953
1088
  if (a.push({
954
1089
  id: Math.random().toString(),
@@ -960,7 +1095,7 @@ class z {
960
1095
  lifetime: 0,
961
1096
  maxLifetime: 0.5
962
1097
  }), t.type === "spore")
963
- t.triggerDissolveDeath(), e.push({
1098
+ t.triggerDissolveDeath(), i.push({
964
1099
  id: Math.random().toString(),
965
1100
  position: { ...t.position },
966
1101
  radius: 200,
@@ -971,14 +1106,14 @@ class z {
971
1106
  else if (t.type === "cluster") {
972
1107
  t.triggerDissolveDeath();
973
1108
  for (let n = 0; n < 6; n++) {
974
- const o = n * Math.PI * 2 / 6, r = {
1109
+ const o = n * Math.PI * 2 / 6, h = {
975
1110
  x: t.position.x + Math.cos(o) * 15,
976
1111
  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
1112
+ }, c = S.createEnemy("micro", h, {
1113
+ x: h.x + Math.cos(o) * 200,
1114
+ y: h.y + Math.sin(o) * 200
980
1115
  });
981
- l.isThrown = !0, h.push(l);
1116
+ c.isThrown = !0, r.push(c);
982
1117
  }
983
1118
  } else t.type === "parasite" ? (t.triggerDissolveDeath(), s.push({
984
1119
  id: Math.random().toString(),
@@ -987,22 +1122,22 @@ class z {
987
1122
  duration: 0,
988
1123
  maxDuration: 5,
989
1124
  pullForce: 3e3
990
- })) : t.type === "piercer" ? t.triggerSliceDeath(i) : t.triggerDissolveDeath();
1125
+ })) : t.type === "piercer" ? t.triggerSliceDeath(e) : t.triggerDissolveDeath();
991
1126
  }
992
1127
  }
993
- class Z {
1128
+ class _ {
994
1129
  pool = [];
995
1130
  constructor(t = 500) {
996
- for (let i = 0; i < t; i++) {
997
- const e = new P(`pool_enemy_${i}`);
998
- this.pool.push(e);
1131
+ for (let e = 0; e < t; e++) {
1132
+ const i = new N(`pool_enemy_${e}`);
1133
+ this.pool.push(i);
999
1134
  }
1000
1135
  }
1001
1136
  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()}`);
1137
+ for (const e of this.pool)
1138
+ if (!e.active)
1139
+ return e.reset(), e;
1140
+ const t = new N(`fallback_enemy_${Date.now()}_${Math.random()}`);
1006
1141
  return this.pool.push(t), t;
1007
1142
  }
1008
1143
  resetAll() {
@@ -1010,148 +1145,155 @@ class Z {
1010
1145
  t.reset();
1011
1146
  }
1012
1147
  }
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 };
1148
+ class C {
1149
+ static getOffscreenPosition(t, e) {
1150
+ const i = Math.floor(Math.random() * 4), s = 70;
1151
+ 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
1152
  }
1018
- static spawnCircleOfDeath(t, i, e, s) {
1019
- const a = [], h = Math.max(e, s) * 0.55 + 80;
1153
+ static spawnCircleOfDeath(t, e, i, s) {
1154
+ const a = [], r = Math.max(i, s) * 0.55 + 80;
1020
1155
  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 = {
1156
+ const o = n * Math.PI * 2 / 18, h = {
1157
+ x: e.x + Math.cos(o) * r,
1158
+ y: e.y + Math.sin(o) * r
1159
+ }, c = t.get(), u = ["piercer", "spore", "cluster", "parasite"], p = u[n % u.length];
1160
+ S.configureEnemy(c, p, h, e), c.velocity = {
1026
1161
  x: Math.cos(o + Math.PI) * 55,
1027
1162
  y: Math.sin(o + Math.PI) * 55
1028
- }, a.push(l);
1163
+ }, a.push(c);
1029
1164
  }
1030
1165
  return a;
1031
1166
  }
1032
- static spawnDenseCluster(t, i, e, s) {
1033
- const a = [], h = Math.floor(Math.random() * 4);
1167
+ static spawnDenseCluster(t, e, i, s) {
1168
+ const a = [], r = Math.floor(Math.random() * 4);
1034
1169
  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 };
1170
+ 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
1171
  for (let o = 0; o < 14; o++) {
1037
- const r = {
1172
+ const h = {
1038
1173
  x: (Math.random() - 0.5) * 60,
1039
1174
  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);
1175
+ }, c = { x: n.x + h.x, y: n.y + h.y }, u = t.get();
1176
+ S.configureEnemy(u, "spore", c, s);
1177
+ const p = s.x - c.x, f = s.y - c.y, T = Math.atan2(f, p);
1178
+ u.velocity = {
1179
+ x: Math.cos(T) * (50 + Math.random() * 20),
1180
+ y: Math.sin(T) * (50 + Math.random() * 20)
1181
+ }, a.push(u);
1047
1182
  }
1048
1183
  return a;
1049
1184
  }
1050
- static spawnSineSnake(t, i, e, s) {
1051
- const a = [], h = e * 0.2 + Math.random() * e * 0.6;
1185
+ static spawnSineSnake(t, e, i, s) {
1186
+ const a = [], r = i * 0.2 + Math.random() * i * 0.6;
1052
1187
  for (let n = 0; n < 12; n++) {
1053
1188
  const o = {
1054
1189
  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);
1190
+ y: r + Math.sin(n * 0.45) * 70
1191
+ }, h = t.get();
1192
+ S.configureEnemy(h, "cluster", o, s), h.velocity = { x: 75, y: Math.cos(n * 0.45) * 30 }, a.push(h);
1058
1193
  }
1059
1194
  return a;
1060
1195
  }
1061
- static spawnDoubleSpiral(t, i, e, s) {
1196
+ static spawnDoubleSpiral(t, e, i, s) {
1062
1197
  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);
1198
+ for (let r = 0; r < 14; r++) {
1199
+ const n = r / 14, o = n * Math.PI * 4, h = 120 + n * 450, c = {
1200
+ x: e + Math.cos(o) * h,
1201
+ y: -60 + Math.sin(o) * h
1202
+ }, u = t.get();
1203
+ S.configureEnemy(u, "parasite", c, s), a.push(u);
1069
1204
  }
1070
1205
  return a;
1071
1206
  }
1072
- static spawnMarchingWall(t, i, e, s) {
1073
- const a = [], h = Math.random() > 0.5;
1207
+ static spawnMarchingWall(t, e, i, s) {
1208
+ const a = [], r = Math.random() > 0.5;
1074
1209
  for (let n = 0; n < 12; n++) {
1075
- const o = n / 11 * e, r = {
1076
- x: h ? -60 : i + 60,
1210
+ const o = n / 11 * i, h = {
1211
+ x: r ? -60 : e + 60,
1077
1212
  y: o
1078
- }, l = t.get();
1079
- L.configureEnemy(l, "piercer", r, s), l.velocity = {
1080
- x: h ? 70 : -70,
1213
+ }, c = t.get();
1214
+ S.configureEnemy(c, "piercer", h, s), c.velocity = {
1215
+ x: r ? 70 : -70,
1081
1216
  y: 0
1082
- }, a.push(l);
1217
+ }, a.push(c);
1083
1218
  }
1084
1219
  return a;
1085
1220
  }
1086
- static spawnCrossfireStreams(t, i, e, s) {
1221
+ static spawnCrossfireStreams(t, e, i, s) {
1087
1222
  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);
1223
+ for (let r = 0; r < 10; r++) {
1224
+ const n = { x: -50 - r * 35, y: -50 - r * 35 }, o = t.get();
1225
+ S.configureEnemy(o, "spore", n, s), a.push(o);
1226
+ const h = { x: e + 50 + r * 35, y: i + 50 + r * 35 }, c = t.get();
1227
+ S.configureEnemy(c, "cluster", h, s), a.push(c);
1093
1228
  }
1094
1229
  return a;
1095
1230
  }
1096
1231
  }
1097
- class _ {
1232
+ class q {
1098
1233
  wave = 1;
1099
1234
  pool;
1100
1235
  spawnTimer = 0;
1101
1236
  waveTimer = 0;
1102
1237
  patternCooldown = 0;
1103
- initialGracePeriod = 25;
1238
+ initialGracePeriod = 6;
1104
1239
  constructor() {
1105
- this.pool = new Z(500);
1240
+ this.pool = new _(500);
1106
1241
  }
1107
1242
  reset() {
1108
1243
  this.wave = 1, this.spawnTimer = 0, this.waveTimer = 0, this.patternCooldown = 0;
1109
1244
  }
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) {
1245
+ update(t, e, i, s, a) {
1246
+ this.waveTimer += t, this.spawnTimer += t, this.patternCooldown += t, this.applyFlockingBehaviors(e, t, a);
1247
+ const l = e.filter((o) => o.active).length, r = Math.max(0.9, 2.2 - (this.wave - 1) * 0.18);
1248
+ if (this.waveTimer > this.initialGracePeriod && this.patternCooldown > Math.max(12 - this.wave, 6) && l < 35) {
1114
1249
  this.patternCooldown = 0;
1115
- const n = this.spawnPatternFormation(e, s, a);
1116
- for (const o of n)
1117
- i.push(o);
1250
+ const o = this.spawnPatternFormation(i, s, a);
1251
+ for (const h of o)
1252
+ e.push(h);
1118
1253
  }
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;
1254
+ const n = Math.min(18 + this.wave * 4, 80);
1255
+ return this.spawnTimer >= r && l < n ? (this.spawnTimer = 0, this.spawnSingleEnemy(i, s, a)) : null;
1121
1256
  }
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;
1257
+ spawnSingleEnemy(t, e, i) {
1258
+ const s = C.getOffscreenPosition(t, e), a = Math.random();
1259
+ let l = "piercer";
1260
+ a > 0.75 ? l = "parasite" : a > 0.5 ? l = "cluster" : a > 0.25 && (l = "spore");
1261
+ const r = this.pool.get();
1262
+ return S.configureEnemy(r, l, s, i), r;
1128
1263
  }
1129
- spawnPatternFormation(t, i, e) {
1264
+ spawnPatternFormation(t, e, i) {
1130
1265
  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);
1266
+ 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
1267
  }
1133
- applyFlockingBehaviors(t, i, e) {
1268
+ applyFlockingBehaviors(t, e, i) {
1134
1269
  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++);
1270
+ const l = t[a];
1271
+ if (!l.active || l.isGrabbed || l.isThrown || l.isDying) continue;
1272
+ let r = 0, n = 0, o = 0;
1273
+ for (let p = 0; p < t.length; p++) {
1274
+ if (a === p) continue;
1275
+ const f = t[p];
1276
+ if (!f.active || f.isGrabbed || f.isDying) continue;
1277
+ const T = l.position.x - f.position.x, d = l.position.y - f.position.y, m = Math.hypot(T, d);
1278
+ m > 0 && m < 70 && (r += T / m, n += d / m, o++);
1279
+ }
1280
+ o > 0 && (r /= o, n /= o, l.velocity.x += r * 60 * e, l.velocity.y += n * 60 * e);
1281
+ const h = i.x - l.position.x, c = i.y - l.position.y, u = Math.hypot(h, c);
1282
+ if (u > 0) {
1283
+ const p = 80 + Math.min(this.wave * 4, 40);
1284
+ l.velocity.x += h / u * p * e, l.velocity.y += c / u * p * e;
1144
1285
  }
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;
1286
+ if (l.maxSpeed > 0) {
1287
+ const p = Math.hypot(l.velocity.x, l.velocity.y);
1288
+ if (p > l.maxSpeed) {
1289
+ const f = l.maxSpeed / p;
1290
+ l.velocity.x *= f, l.velocity.y *= f;
1291
+ }
1150
1292
  }
1151
1293
  }
1152
1294
  }
1153
1295
  }
1154
- const C = {
1296
+ const R = {
1155
1297
  bioluminescent: {
1156
1298
  bgInner: "#081220",
1157
1299
  bgMid: "#050b16",
@@ -1201,22 +1343,22 @@ const C = {
1201
1343
  tendrilCyan: "#0077b6"
1202
1344
  }
1203
1345
  }, D = "axon_surge_theme";
1204
- class q {
1346
+ class j {
1205
1347
  currentTheme = "bioluminescent";
1206
1348
  constructor(t) {
1207
1349
  if (t)
1208
1350
  this.setTheme(t);
1209
1351
  else {
1210
1352
  try {
1211
- const i = localStorage.getItem(D);
1212
- i && C[i] && (this.currentTheme = i);
1353
+ const e = localStorage.getItem(D);
1354
+ e && R[e] && (this.currentTheme = e);
1213
1355
  } catch {
1214
1356
  }
1215
1357
  this.applyThemeToDOM();
1216
1358
  }
1217
1359
  }
1218
1360
  setTheme(t) {
1219
- if (C[t]) {
1361
+ if (R[t]) {
1220
1362
  this.currentTheme = t, this.applyThemeToDOM();
1221
1363
  try {
1222
1364
  localStorage.setItem(D, t);
@@ -1228,169 +1370,232 @@ class q {
1228
1370
  return this.currentTheme;
1229
1371
  }
1230
1372
  getPalette() {
1231
- return C[this.currentTheme] || C.bioluminescent;
1373
+ return R[this.currentTheme] || R.bioluminescent;
1232
1374
  }
1233
1375
  applyThemeToDOM() {
1234
1376
  document.documentElement.setAttribute("data-theme", this.currentTheme);
1235
1377
  }
1236
1378
  }
1237
1379
  class Q {
1380
+ maxDistance = 450;
1381
+ maxThickness = 28;
1382
+ minThickness = 4;
1383
+ maxLength = 140;
1384
+ minLength = 40;
1385
+ render(t, e, i, s) {
1386
+ for (const a of e) {
1387
+ if (!a.active || a.isGrabbed || a.isDying) continue;
1388
+ const l = a.position.x, r = a.position.y;
1389
+ if (l >= 0 && l <= i && r >= 0 && r <= s) continue;
1390
+ const n = Math.min(i, Math.max(0, l)), o = Math.min(s, Math.max(0, r)), h = Math.hypot(l - n, r - o);
1391
+ if (h <= 0 || h > this.maxDistance) continue;
1392
+ 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;
1393
+ 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) {
1394
+ const T = Math.max(0, o - p / 2), d = Math.min(s, o + p / 2);
1395
+ t.moveTo(n, T), t.lineTo(n, d);
1396
+ } else {
1397
+ const T = Math.max(0, n - p / 2), d = Math.min(i, n + p / 2);
1398
+ t.moveTo(T, o), t.lineTo(d, o);
1399
+ }
1400
+ t.stroke(), t.strokeStyle = "#ffffff", t.lineWidth = Math.max(1.5, u * 0.25), t.globalAlpha = f * 0.8, t.stroke(), t.restore();
1401
+ }
1402
+ }
1403
+ }
1404
+ class tt {
1405
+ render(t, e, i, s, a) {
1406
+ 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));
1407
+ h.addColorStop(0, r), h.addColorStop(0.55, n), h.addColorStop(1, o), t.fillStyle = h, t.fillRect(0, 0, e, i);
1408
+ 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);
1409
+ 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();
1410
+ 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);
1411
+ 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();
1412
+ }
1413
+ }
1414
+ class et {
1415
+ render(t, e, i) {
1416
+ if (!e.isActive) return;
1417
+ const s = e.getLauncher(), a = e.getTarget();
1418
+ if (!s || !a || !s.active || !a.active) return;
1419
+ const l = e.getStep();
1420
+ if (t.save(), l === 1) {
1421
+ const r = Math.sin(i * 6) * 10, n = s.position.x, o = s.position.y - 65 + r;
1422
+ 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();
1423
+ const h = s.radius * (1.6 + Math.sin(i * 8) * 0.3);
1424
+ 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();
1425
+ } else if (l === 2) {
1426
+ const r = a.position.x - s.position.x, n = a.position.y - s.position.y;
1427
+ if (Math.hypot(r, n) > 10) {
1428
+ const h = Math.atan2(n, r);
1429
+ 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([]);
1430
+ const c = a.position.x - Math.cos(h) * (a.radius + 10), u = a.position.y - Math.sin(h) * (a.radius + 10);
1431
+ 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();
1432
+ const p = a.radius * (1.8 + Math.cos(i * 10) * 0.3);
1433
+ 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();
1434
+ }
1435
+ }
1436
+ t.restore();
1437
+ }
1438
+ }
1439
+ class it {
1238
1440
  canvas;
1239
1441
  ctx;
1240
1442
  themeManager;
1241
- constructor(t, i) {
1242
- this.canvas = t, this.ctx = t.getContext("2d"), this.themeManager = i;
1443
+ indicatorRenderer;
1444
+ bgRenderer;
1445
+ tutorialArrowRenderer;
1446
+ constructor(t, e) {
1447
+ this.canvas = t, this.ctx = t.getContext("2d"), this.themeManager = e, this.indicatorRenderer = new Q(), this.bgRenderer = new tt(), this.tutorialArrowRenderer = new et();
1243
1448
  }
1244
- render(t, i, e, s, a, c, h, n, o, r) {
1449
+ render(t, e, i, s, a, l, r, n, o, h, c = 1, u) {
1245
1450
  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();
1451
+ const p = this.themeManager.getPalette(), { width: f, height: T } = this.canvas, d = n.getShakeOffset();
1452
+ 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
1453
  }
1249
- drawToxicPools(t, i) {
1454
+ drawToxicPools(t, e) {
1250
1455
  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;
1456
+ for (const i of t) {
1457
+ const s = i.duration / i.maxDuration, a = Math.min(0.7, (1 - s) * 0.7), { x: l, y: r } = i.position;
1253
1458
  this.ctx.save();
1254
- const n = this.ctx.createRadialGradient(c, h, 10, c, h, e.radius * 1.2);
1459
+ const n = this.ctx.createRadialGradient(l, r, 10, l, r, i.radius * 1.2);
1255
1460
  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
1461
  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);
1462
+ for (let h = 0; h <= o; h++) {
1463
+ 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;
1464
+ h === 0 ? this.ctx.moveTo(T, d) : this.ctx.lineTo(T, d);
1260
1465
  }
1261
1466
  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);
1467
+ for (let h = 0; h <= o; h++) {
1468
+ 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;
1469
+ h === 0 ? this.ctx.moveTo(f, T) : this.ctx.lineTo(f, T);
1265
1470
  }
1266
1471
  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();
1472
+ for (let h = 0; h < 6; h++) {
1473
+ 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;
1474
+ 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
1475
  }
1271
1476
  this.ctx.restore();
1272
1477
  }
1273
1478
  }
1274
1479
  drawShockwaves(t) {
1275
1480
  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,
1481
+ for (const e of t) {
1482
+ this.ctx.save(), this.ctx.globalAlpha = e.alpha;
1483
+ const i = this.ctx.createRadialGradient(
1484
+ e.position.x,
1485
+ e.position.y,
1281
1486
  0,
1282
- i.position.x,
1283
- i.position.y,
1284
- i.radius
1487
+ e.position.x,
1488
+ e.position.y,
1489
+ e.radius
1285
1490
  );
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();
1491
+ 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
1492
  }
1288
1493
  }
1289
- drawGravityVortices(t, i) {
1494
+ drawGravityVortices(t, e) {
1290
1495
  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;
1496
+ for (const i of t) {
1497
+ 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
1498
  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;
1499
+ const n = this.ctx.createRadialGradient(l, r, 0, l, r, 60);
1500
+ 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
1501
  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();
1502
+ const h = a * o / 5, c = e * o * 2.2;
1503
+ this.ctx.beginPath(), this.ctx.arc(l, r, h, c, c + Math.PI * 1.5), this.ctx.stroke();
1299
1504
  }
1300
1505
  this.ctx.restore();
1301
1506
  }
1302
1507
  }
1303
- drawFluidCosmosBackground(t, i, e, s) {
1508
+ drawFluidCosmosBackground(t, e, i, s) {
1304
1509
  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) {
1510
+ const a = this.ctx.createRadialGradient(t / 2, e / 2, 40, t / 2, e / 2, Math.max(t, e));
1511
+ 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);
1512
+ 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);
1513
+ 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();
1514
+ 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);
1515
+ 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();
1516
+ }
1517
+ drawCoreFilaments(t, e) {
1313
1518
  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();
1519
+ const i = 12;
1520
+ this.ctx.lineWidth = 1.5, this.ctx.strokeStyle = e.nebulaCyan;
1521
+ for (let s = 0; s < i; s++) {
1522
+ 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;
1523
+ 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
1524
  }
1320
1525
  }
1321
- drawOrganicConsciousnessCore(t, i) {
1526
+ drawOrganicConsciousnessCore(t, e) {
1322
1527
  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();
1528
+ const { x: i, y: s } = t.position;
1529
+ for (let r = 0; r < t.integrity; r++) {
1530
+ const n = t.radius + 16 + r * 12;
1531
+ this.ctx.strokeStyle = e.corePrimary, this.ctx.lineWidth = 2.2, this.ctx.shadowColor = e.corePrimary, this.ctx.shadowBlur = 12, this.ctx.beginPath();
1327
1532
  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);
1533
+ for (let h = 0; h <= o; h++) {
1534
+ 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;
1535
+ h === 0 ? this.ctx.moveTo(p, f) : this.ctx.lineTo(p, f);
1331
1536
  }
1332
1537
  this.ctx.closePath(), this.ctx.stroke();
1333
1538
  }
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);
1539
+ const a = this.ctx.createRadialGradient(i, s, 5, i, s, t.radius * 2.2);
1540
+ 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();
1541
+ const l = 80;
1542
+ for (let r = 0; r <= l; r++) {
1543
+ const n = r * Math.PI * 2 / l, o = t.getMembraneRadius(n), h = Math.cos(n) * o, c = Math.sin(n) * o;
1544
+ r === 0 ? this.ctx.moveTo(h, c) : this.ctx.lineTo(h, c);
1340
1545
  }
1341
1546
  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
1547
  }
1343
- drawPsionicTendril(t, i, e) {
1548
+ drawPsionicTendril(t, e, i) {
1344
1549
  if (!this.ctx) return;
1345
1550
  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();
1551
+ const s = e.x - t.x, a = e.y - t.y;
1552
+ 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);
1553
+ 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;
1554
+ 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
1555
  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();
1556
+ const o = Math.random(), h = t.x + s * o + (Math.random() - 0.5) * 24, c = t.y + a * o + (Math.random() - 0.5) * 24;
1557
+ 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
1558
  }
1354
1559
  this.ctx.restore();
1355
1560
  }
1356
- drawHoverTendril(t, i, e, s) {
1561
+ drawHoverTendril(t, e, i, s) {
1357
1562
  if (this.ctx)
1358
- for (const a of e) {
1563
+ for (const a of i) {
1359
1564
  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()) {
1565
+ const l = e.x - a.position.x, r = e.y - a.position.y;
1566
+ if (Math.hypot(l, r) <= a.getHitRadius()) {
1362
1567
  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
1568
  break;
1364
1569
  }
1365
1570
  }
1366
1571
  }
1367
- drawOrganicEnemies(t, i, e) {
1572
+ drawOrganicEnemies(t, e, i) {
1368
1573
  if (this.ctx)
1369
1574
  for (const s of t) {
1370
1575
  if (!s.active) continue;
1371
1576
  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();
1577
+ 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);
1578
+ const { x: l, y: r } = s.position;
1579
+ if (this.ctx.save(), this.ctx.translate(l, r), s.wasManipulated && !s.isDying) {
1580
+ const n = s.radius * 1.5 + Math.sin(e * 6) * 4;
1581
+ 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();
1582
+ const o = s.radius * 1.8 + Math.cos(e * 8) * 3;
1583
+ 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
1584
  }
1380
1585
  if (s.isDying) {
1381
1586
  const n = s.deathTimer / s.maxDeathTimer, o = Math.max(0, 1 - n);
1382
1587
  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();
1588
+ const h = s.radius * (1 - n * 0.7);
1589
+ 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();
1590
+ for (let c = 0; c < 4; c++) {
1591
+ const u = c * Math.PI * 0.5 + n * 4, p = h * 0.8 * n;
1592
+ 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
1593
  }
1389
1594
  this.ctx.restore();
1390
1595
  continue;
1391
1596
  } 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();
1597
+ const h = n * 24, c = s.sliceAngle + Math.PI / 2, u = Math.cos(c) * h, p = Math.sin(c) * h;
1598
+ 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
1599
  continue;
1395
1600
  }
1396
1601
  }
@@ -1398,30 +1603,30 @@ class Q {
1398
1603
  this.ctx.rotate(s.rotation), this.ctx.beginPath();
1399
1604
  const n = 12;
1400
1605
  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);
1606
+ 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;
1607
+ o === 0 ? this.ctx.moveTo(p, f) : this.ctx.lineTo(p, f);
1403
1608
  }
1404
1609
  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
1610
  } else if (s.type === "spore") {
1406
1611
  this.ctx.beginPath();
1407
1612
  const n = 8;
1408
1613
  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);
1614
+ 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;
1615
+ o === 0 ? this.ctx.moveTo(u, p) : this.ctx.lineTo(u, p);
1411
1616
  }
1412
1617
  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
1618
  } else if (s.type === "cluster") {
1414
1619
  this.ctx.beginPath();
1415
- const n = Math.sin(i * 3) * 2;
1620
+ const n = Math.sin(e * 3) * 2;
1416
1621
  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
1622
  } else if (s.type === "parasite") {
1418
1623
  this.ctx.beginPath();
1419
1624
  const n = 14;
1420
1625
  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);
1626
+ 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;
1627
+ o === 0 ? this.ctx.moveTo(u, p) : this.ctx.lineTo(u, p);
1423
1628
  }
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();
1629
+ 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
1630
  } else
1426
1631
  this.ctx.beginPath(), this.ctx.arc(0, 0, s.radius, 0, Math.PI * 2), this.ctx.fill();
1427
1632
  this.ctx.restore();
@@ -1429,39 +1634,39 @@ class Q {
1429
1634
  }
1430
1635
  drawParticles(t) {
1431
1636
  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();
1637
+ for (const e of t)
1638
+ 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
1639
  }
1435
1640
  drawFloatingTexts(t) {
1436
1641
  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();
1642
+ for (const e of t)
1643
+ 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
1644
  }
1440
1645
  }
1441
- class j {
1646
+ class st {
1442
1647
  container;
1443
1648
  i18n;
1444
1649
  waveLabelElement;
1445
1650
  progressSlot;
1446
1651
  comboElement;
1447
1652
  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 = `
1653
+ constructor(t, e, i) {
1654
+ 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
1655
  <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
1656
  <circle cx="12" cy="12" r="3"></circle>
1452
1657
  <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
1658
  </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);
1659
+ `, 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
1660
  }
1456
1661
  renderLabels() {
1457
1662
  let t = this.waveLabelElement.querySelector(".axon-level-title");
1458
1663
  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>';
1664
+ let e = this.waveLabelElement.querySelector("#axon-wave-val");
1665
+ 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
1666
  }
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");
1667
+ update(t, e) {
1668
+ const i = this.container.querySelector("#axon-wave-val"), s = this.container.querySelector("#axon-combo-val");
1669
+ i && (i.textContent = t.toString()), s && (e >= 2 ? (s.textContent = `x${e}`, s.style.display = "block") : s.style.display = "none");
1465
1670
  }
1466
1671
  show() {
1467
1672
  this.renderLabels(), this.container.style.display = "flex";
@@ -1470,12 +1675,12 @@ class j {
1470
1675
  this.container.style.display = "none";
1471
1676
  }
1472
1677
  }
1473
- class tt {
1678
+ class at {
1474
1679
  container;
1475
1680
  i18n;
1476
1681
  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);
1682
+ constructor(t, e, i) {
1683
+ this.i18n = e, this.onStartCallback = i, this.container = document.createElement("div"), this.container.className = "axon-start-menu", this.renderContent(), t.appendChild(this.container);
1479
1684
  }
1480
1685
  renderContent() {
1481
1686
  this.container.innerHTML = `
@@ -1496,7 +1701,7 @@ class tt {
1496
1701
  this.container.style.display = "none";
1497
1702
  }
1498
1703
  }
1499
- class it {
1704
+ class nt {
1500
1705
  modal;
1501
1706
  card;
1502
1707
  i18n;
@@ -1505,10 +1710,10 @@ class it {
1505
1710
  onLanguageChangedCallback;
1506
1711
  onCloseCallback;
1507
1712
  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", () => {
1713
+ constructor(t, e, i, s, a, l) {
1714
+ this.i18n = e, this.themeManager = i, this.platform = s, this.onLanguageChangedCallback = a, this.onCloseCallback = l;
1715
+ const r = localStorage.getItem("axon_surge_haptics");
1716
+ 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
1717
  this.onCloseCallback && this.onCloseCallback();
1513
1718
  }), this.renderContent();
1514
1719
  }
@@ -1516,15 +1721,15 @@ class it {
1516
1721
  this.card.innerHTML = "";
1517
1722
  const t = document.createElement("h2");
1518
1723
  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");
1724
+ const e = document.createElement("div");
1725
+ e.className = "axon-setting-row";
1726
+ const i = document.createElement("span");
1727
+ i.textContent = this.i18n.translate("languageLabel");
1523
1728
  const s = document.createElement("div");
1524
1729
  s.className = "axon-select-wrapper";
1525
1730
  const a = document.createElement("select");
1526
1731
  a.className = "axon-select";
1527
- const c = {
1732
+ const l = {
1528
1733
  es: "ESPAÑOL (ES)",
1529
1734
  en: "ENGLISH (EN)",
1530
1735
  fr: "FRANÇAIS (FR)",
@@ -1541,57 +1746,74 @@ class it {
1541
1746
  ko: "한국어 (KO)",
1542
1747
  zh: "中文 (ZH)"
1543
1748
  };
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);
1749
+ for (const y of U) {
1750
+ const g = document.createElement("option");
1751
+ g.value = y, g.textContent = l[y], this.i18n.getLanguage() === y && (g.selected = !0), a.appendChild(g);
1547
1752
  }
1548
1753
  a.addEventListener("change", () => {
1549
- const u = a.value;
1550
- this.i18n.setLanguage(u), this.onLanguageChangedCallback && this.onLanguageChangedCallback(u), this.renderContent();
1754
+ const y = a.value;
1755
+ this.i18n.setLanguage(y), this.onLanguageChangedCallback && this.onLanguageChangedCallback(y), this.renderContent();
1551
1756
  });
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);
1757
+ const r = document.createElement("span");
1758
+ r.className = "axon-select-arrow", r.textContent = "▼", s.appendChild(a), s.appendChild(r), e.appendChild(i), e.appendChild(s);
1554
1759
  const n = document.createElement("div");
1555
1760
  n.className = "axon-setting-row";
1556
1761
  const o = document.createElement("span");
1557
1762
  o.textContent = this.i18n.translate("themeLabel");
1558
- const r = document.createElement("div");
1559
- r.className = "axon-toggle-group";
1560
- const l = [
1763
+ const h = document.createElement("div");
1764
+ h.className = "axon-toggle-group";
1765
+ const c = [
1561
1766
  { id: "bioluminescent", label: "BIO" },
1562
1767
  { id: "dark", label: "DARK" },
1563
1768
  { id: "light", label: "LIGHT" }
1564
1769
  ];
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);
1770
+ for (const y of c) {
1771
+ const g = document.createElement("button");
1772
+ g.type = "button", g.className = `axon-toggle-btn ${this.themeManager.getTheme() === y.id ? "active" : ""}`, g.textContent = y.label, g.addEventListener("click", () => {
1773
+ this.themeManager.setTheme(y.id), this.renderContent();
1774
+ }), h.appendChild(g);
1570
1775
  }
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 = [
1776
+ n.appendChild(o), n.appendChild(h);
1777
+ const u = document.createElement("div");
1778
+ u.className = "axon-setting-row";
1779
+ const p = document.createElement("span");
1780
+ p.textContent = this.i18n.translate("hapticsLabel");
1781
+ const f = document.createElement("div");
1782
+ f.className = "axon-toggle-group";
1783
+ const T = [
1579
1784
  { enabled: !0, label: this.i18n.translate("hapticsOn") },
1580
1785
  { enabled: !1, label: this.i18n.translate("hapticsOff") }
1581
1786
  ];
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);
1787
+ for (const y of T) {
1788
+ const g = document.createElement("button");
1789
+ g.type = "button", g.className = `axon-toggle-btn ${this.hapticsEnabled === y.enabled ? "active" : ""}`, g.textContent = y.label, g.addEventListener("click", () => {
1790
+ this.hapticsEnabled = y.enabled, localStorage.setItem("axon_surge_haptics", String(y.enabled)), this.hapticsEnabled && this.platform.haptics.selectionChanged(), this.renderContent();
1791
+ }), f.appendChild(g);
1587
1792
  }
1588
- p.appendChild(f), p.appendChild(g);
1793
+ u.appendChild(p), u.appendChild(f);
1589
1794
  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", () => {
1795
+ d.className = "axon-setting-row";
1796
+ const m = document.createElement("span");
1797
+ m.textContent = this.i18n.translate("tutorialSettingLabel");
1798
+ const x = document.createElement("div");
1799
+ x.className = "axon-toggle-group";
1800
+ const L = localStorage.getItem("axon_surge_show_tutorial") !== "false", A = [
1801
+ { enabled: !0, label: this.i18n.translate("hapticsOn") },
1802
+ { enabled: !1, label: this.i18n.translate("hapticsOff") }
1803
+ ];
1804
+ for (const y of A) {
1805
+ const g = document.createElement("button");
1806
+ g.type = "button", g.className = `axon-toggle-btn ${L === y.enabled ? "active" : ""}`, g.textContent = y.label, g.addEventListener("click", () => {
1807
+ localStorage.setItem("axon_surge_show_tutorial", String(y.enabled)), this.renderContent();
1808
+ }), x.appendChild(g);
1809
+ }
1810
+ d.appendChild(m), d.appendChild(x);
1811
+ const b = document.createElement("div");
1812
+ b.className = "axon-settings-credits", b.textContent = this.i18n.translate("creditsJam");
1813
+ const M = document.createElement("button");
1814
+ 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
1815
  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);
1816
+ }), 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
1817
  }
1596
1818
  isHapticsEnabled() {
1597
1819
  return this.hapticsEnabled;
@@ -1603,64 +1825,136 @@ class it {
1603
1825
  this.modal.close();
1604
1826
  }
1605
1827
  }
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);
1828
+ const G = "axon_surge_show_tutorial";
1829
+ class ot {
1830
+ isActive = !1;
1831
+ showWarning = !1;
1832
+ dummyLauncher = null;
1833
+ dummyTarget = null;
1834
+ initialLauncherPos = { x: 0, y: 0 };
1835
+ initialTargetPos = { x: 0, y: 0 };
1836
+ isTutorialEnabled() {
1614
1837
  try {
1615
- localStorage.getItem(O) === "true" && (this.hasCompleted = !0);
1838
+ return localStorage.getItem(G) !== "false";
1616
1839
  } catch {
1840
+ return !0;
1617
1841
  }
1618
1842
  }
1619
- isCompleted() {
1620
- return this.hasCompleted;
1843
+ setTutorialEnabled(t) {
1844
+ try {
1845
+ localStorage.setItem(G, String(t));
1846
+ } catch {
1847
+ }
1621
1848
  }
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");
1849
+ getLauncher() {
1850
+ return this.dummyLauncher;
1628
1851
  }
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");
1852
+ getTarget() {
1853
+ return this.dummyTarget;
1635
1854
  }
1636
- complete() {
1637
- this.hasCompleted = !0, this.container.style.display = "none";
1638
- try {
1639
- localStorage.setItem(O, "true");
1640
- } catch {
1855
+ getStep() {
1856
+ return this.dummyLauncher && (this.dummyLauncher.isGrabbed || this.dummyLauncher.wasManipulated) ? 2 : 1;
1857
+ }
1858
+ start(t, e, i) {
1859
+ if (!this.isTutorialEnabled()) {
1860
+ this.isActive = !1;
1861
+ return;
1862
+ }
1863
+ 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(
1864
+ "piercer",
1865
+ this.initialLauncherPos,
1866
+ this.initialTargetPos
1867
+ ), this.dummyLauncher.velocity = { x: 0, y: 0 }, this.dummyTarget = S.createEnemy(
1868
+ "spore",
1869
+ this.initialTargetPos,
1870
+ this.initialLauncherPos
1871
+ ), this.dummyTarget.velocity = { x: 0, y: 0 }, i.push(this.dummyLauncher), i.push(this.dummyTarget);
1872
+ }
1873
+ update(t, e, i, s, a, l) {
1874
+ if (!this.isActive || !this.dummyLauncher || !this.dummyTarget) return;
1875
+ const r = this.dummyLauncher, n = this.dummyTarget;
1876
+ e.includes(r) || e.push(r), e.includes(n) || e.push(n);
1877
+ const o = n.position.x - r.position.x, h = n.position.y - r.position.y, c = Math.hypot(o, h);
1878
+ if (r.isGrabbed) {
1879
+ if (this.showWarning = !1, c <= r.radius + n.radius + 60) {
1880
+ l && l(), r.isGrabbed = !1, this.showWarning = !0, this.resetDummies(r, n);
1881
+ return;
1882
+ }
1883
+ return;
1884
+ }
1885
+ if (r.wasManipulated) {
1886
+ const u = Math.hypot(r.velocity.x, r.velocity.y);
1887
+ if (!r.isThrown || u < 70) {
1888
+ l && l(), this.showWarning = !0, this.resetDummies(r, n);
1889
+ return;
1890
+ }
1891
+ if (c <= r.getHitRadius() + n.getHitRadius()) {
1892
+ r.triggerDissolveDeath(), n.triggerDissolveDeath(), this.showWarning = !1, this.isActive = !1, a();
1893
+ return;
1894
+ }
1895
+ (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
1896
  }
1642
1897
  }
1643
- reset() {
1644
- this.hasCompleted || (this.isStep1Done = !1, this.container.style.display = "none");
1898
+ resetDummies(t, e) {
1899
+ 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;
1900
+ }
1901
+ complete() {
1902
+ this.isActive = !1, this.showWarning = !1;
1645
1903
  }
1646
1904
  }
1647
- class st {
1905
+ class rt {
1906
+ container;
1907
+ i18n;
1908
+ tutorialManager;
1909
+ bannerElement;
1910
+ textElement;
1911
+ checkboxElement;
1912
+ currentStep = 1;
1913
+ constructor(t, e, i) {
1914
+ 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();
1915
+ }
1916
+ render() {
1917
+ 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);
1918
+ const t = document.createElement("label");
1919
+ 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", () => {
1920
+ this.tutorialManager.setTutorialEnabled(!this.checkboxElement.checked);
1921
+ });
1922
+ const e = document.createElement("span");
1923
+ e.textContent = this.i18n.translate("dontShowTutorialLabel"), t.appendChild(this.checkboxElement), t.appendChild(e), this.container.appendChild(this.bannerElement), this.container.appendChild(t);
1924
+ }
1925
+ updateBannerContent() {
1926
+ !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")));
1927
+ }
1928
+ updateStep(t) {
1929
+ this.currentStep = t, this.updateBannerContent();
1930
+ }
1931
+ updateLanguage() {
1932
+ this.render();
1933
+ }
1934
+ show() {
1935
+ this.currentStep = 1, this.render(), this.container.style.display = "flex";
1936
+ }
1937
+ hide() {
1938
+ this.container.style.display = "none";
1939
+ }
1940
+ }
1941
+ class ht {
1648
1942
  fillElement;
1649
1943
  killsCount = 0;
1650
1944
  currentLevel = 1;
1651
1945
  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);
1946
+ constructor(t, e) {
1947
+ this.onLevelUpCallback = e;
1948
+ const i = document.createElement("div");
1949
+ 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
1950
  }
1657
1951
  getKillsRequiredForLevel(t) {
1658
1952
  return 16 + (t - 1) * 6;
1659
1953
  }
1660
1954
  addKill() {
1661
1955
  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));
1956
+ const t = this.getKillsRequiredForLevel(this.currentLevel), e = Math.min(100, this.killsCount / t * 100);
1957
+ 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
1958
  }
1665
1959
  getLevel() {
1666
1960
  return this.currentLevel;
@@ -1675,18 +1969,18 @@ class st {
1675
1969
  this.fillElement && this.fillElement.parentElement && (this.fillElement.parentElement.style.display = "none");
1676
1970
  }
1677
1971
  }
1678
- class at {
1972
+ class lt {
1679
1973
  haptics = {
1680
1974
  impact: async (t) => {
1681
1975
  if ("vibrate" in navigator) {
1682
- const i = t === "light" ? 10 : t === "medium" ? 25 : 40;
1683
- navigator.vibrate(i);
1976
+ const e = t === "light" ? 10 : t === "medium" ? 25 : 40;
1977
+ navigator.vibrate(e);
1684
1978
  }
1685
1979
  },
1686
1980
  notification: async (t) => {
1687
1981
  if ("vibrate" in navigator) {
1688
- const i = t === "error" ? [30, 40, 30] : [20, 20];
1689
- navigator.vibrate(i);
1982
+ const e = t === "error" ? [30, 40, 30] : [20, 20];
1983
+ navigator.vibrate(e);
1690
1984
  }
1691
1985
  },
1692
1986
  selectionChanged: async () => {
@@ -1715,7 +2009,7 @@ class at {
1715
2009
  }
1716
2010
  };
1717
2011
  }
1718
- class nt {
2012
+ class ct {
1719
2013
  container;
1720
2014
  canvas;
1721
2015
  i18n;
@@ -1731,7 +2025,8 @@ class nt {
1731
2025
  hud;
1732
2026
  startMenu;
1733
2027
  settingsModal;
1734
- onboarding;
2028
+ interactiveTutorial;
2029
+ tutorialOverlay;
1735
2030
  progressBar;
1736
2031
  core;
1737
2032
  enemies = [];
@@ -1745,23 +2040,22 @@ class nt {
1745
2040
  combo = { value: 0 };
1746
2041
  isRunning = !1;
1747
2042
  isPaused = !1;
1748
- firstPlay = !0;
1749
2043
  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(
2044
+ this.container = t.root, this.container.classList.add("axon-game-root"), this.i18n = new Y(t.language), this.themeManager = new j(t.theme), 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 k(), this.core = new H(this.canvas.width / 2, this.canvas.height / 2), this.inputManager = new K(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 V(), this.settingsModal = new nt(
1751
2045
  this.container,
1752
2046
  this.i18n,
1753
2047
  this.themeManager,
1754
2048
  this.platform,
1755
- (i) => this.onLanguageChanged(i),
2049
+ (e) => this.onLanguageChanged(e),
1756
2050
  () => {
1757
2051
  this.isPaused = !1;
1758
2052
  }
1759
- ), this.onboarding = new et(this.container, this.i18n), this.hud = new j(this.container, this.i18n, () => {
2053
+ ), this.interactiveTutorial = new ot(), this.tutorialOverlay = new rt(this.container, this.i18n, this.interactiveTutorial), this.hud = new st(this.container, this.i18n, () => {
1760
2054
  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),
2055
+ }), this.hud.show(), this.progressBar = new ht(this.hud.progressSlot, (e) => {
2056
+ this.waveDirector.wave = e;
2057
+ }), this.startMenu = new at(this.container, this.i18n, () => this.startGame()), this.initAmbientArena(), this.gameLoop = new B(
2058
+ (e) => this.update(e),
1765
2059
  () => this.render()
1766
2060
  ), this.setupEvents(), this.gameLoop.start();
1767
2061
  }
@@ -1772,46 +2066,47 @@ class nt {
1772
2066
  this.themeManager.setTheme(t);
1773
2067
  }
1774
2068
  onLanguageChanged(t) {
1775
- this.startMenu.renderContent(), this.hud.renderLabels();
2069
+ this.startMenu.renderContent(), this.hud.renderLabels(), this.tutorialOverlay.updateLanguage();
1776
2070
  }
1777
2071
  initAmbientArena() {
1778
2072
  this.ambientEnemies = [];
1779
2073
  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 = {
2074
+ for (let e = 0; e < 16; e++) {
2075
+ const i = t[e % t.length], s = e * Math.PI * 2 / 16, a = 180 + Math.random() * 220, l = {
1782
2076
  x: this.canvas.width / 2 + Math.cos(s) * a,
1783
2077
  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
2078
+ }, r = S.createEnemy(i, l, {
2079
+ x: l.x + Math.sin(s) * 100,
2080
+ y: l.y - Math.cos(s) * 100
1787
2081
  });
1788
- this.ambientEnemies.push(h);
2082
+ this.ambientEnemies.push(r);
1789
2083
  }
1790
2084
  }
1791
2085
  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 });
2086
+ const t = this.container.clientWidth || window.innerWidth, e = this.container.clientHeight || window.innerHeight, i = 1100, s = 750, a = t / Math.max(1, e);
2087
+ 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
2088
  }
1794
2089
  setupEvents() {
1795
2090
  this.eventBus.on("onCoreDamaged", () => {
1796
2091
  this.settingsModal.isHapticsEnabled() && this.platform.haptics.notification("error");
1797
2092
  }), this.eventBus.on("onGameOver", () => {
1798
- this.isRunning = !1, this.onboarding.complete(), this.progressBar.hide(), this.initAmbientArena(), this.startMenu.show();
2093
+ this.isRunning = !1, this.tutorialOverlay.hide(), this.progressBar.hide(), this.initAmbientArena(), this.startMenu.show();
1799
2094
  });
1800
- const t = () => {
2095
+ const t = (i = !1) => {
1801
2096
  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 = () => {
2097
+ this.inputManager.tryGrab(this.enemies, i) && this.settingsModal.isHapticsEnabled() && this.platform.haptics.impact("light");
2098
+ }, e = () => {
1804
2099
  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"));
2100
+ this.inputManager.releaseAndThrow() && this.settingsModal.isHapticsEnabled() && this.platform.haptics.impact("medium");
1806
2101
  };
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 });
2102
+ this.canvas.addEventListener("mousedown", (i) => {
2103
+ i.button === 0 && t(!1);
2104
+ }), this.canvas.addEventListener("mouseup", (i) => {
2105
+ i.button === 0 && e();
2106
+ }), this.canvas.addEventListener("touchstart", () => t(!0), { passive: !0 }), this.canvas.addEventListener("touchend", e, { passive: !0 }), this.canvas.addEventListener("touchcancel", e, { passive: !0 });
1812
2107
  }
1813
2108
  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();
2109
+ 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
2110
  }
1816
2111
  update(t) {
1817
2112
  if (this.core.update(t), !this.isRunning || this.isPaused) {
@@ -1819,14 +2114,28 @@ class nt {
1819
2114
  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
2115
  return;
1821
2116
  }
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(
2117
+ if (this.interactiveTutorial.isActive)
2118
+ this.interactiveTutorial.update(
2119
+ t,
2120
+ this.enemies,
2121
+ this.canvas.width,
2122
+ this.canvas.height,
2123
+ () => {
2124
+ this.tutorialOverlay.hide();
2125
+ },
2126
+ () => this.inputManager.forceRelease()
2127
+ ), this.tutorialOverlay.updateStep(this.interactiveTutorial.getStep());
2128
+ else {
2129
+ const e = this.waveDirector.update(
2130
+ t,
2131
+ this.enemies,
2132
+ this.canvas.width,
2133
+ this.canvas.height,
2134
+ this.core.position
2135
+ );
2136
+ e && this.enemies.push(e);
2137
+ }
2138
+ this.juice.hitstopTime <= 0 && this.physicsEngine.update(
1830
2139
  t,
1831
2140
  this.core,
1832
2141
  this.enemies,
@@ -1841,7 +2150,7 @@ class nt {
1841
2150
  this.canvas.width,
1842
2151
  this.canvas.height,
1843
2152
  () => this.progressBar.addKill()
1844
- ), this.hud.update(this.progressBar.getLevel(), this.combo.value), this.juice.update(t, this.floatingTexts, this.particles);
2153
+ ), 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
2154
  }
1846
2155
  render() {
1847
2156
  const t = this.isRunning ? this.enemies : this.ambientEnemies;
@@ -1855,18 +2164,20 @@ class nt {
1855
2164
  this.floatingTexts,
1856
2165
  this.juice,
1857
2166
  this.inputManager.grabbedEnemy,
1858
- this.inputManager.pointerPosition
2167
+ this.inputManager.pointerPosition,
2168
+ this.progressBar.getLevel(),
2169
+ this.interactiveTutorial.isActive ? this.interactiveTutorial : void 0
1859
2170
  );
1860
2171
  }
1861
2172
  }
1862
- function ot(x) {
1863
- return new nt(x);
2173
+ function dt(E) {
2174
+ return new ct(E);
1864
2175
  }
1865
2176
  export {
1866
- at as BrowserPlatform,
1867
- nt as GameEngine,
1868
- k as LANGUAGES,
1869
- q as ThemeManager,
1870
- ot as createAxonSurge,
1871
- V as isLanguage
2177
+ lt as BrowserPlatform,
2178
+ ct as GameEngine,
2179
+ U as LANGUAGES,
2180
+ j as ThemeManager,
2181
+ dt as createAxonSurge,
2182
+ F as isLanguage
1872
2183
  };