salomonsky commited on
Commit
22ec77f
·
verified ·
1 Parent(s): a230027

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +120 -16
index.html CHANGED
@@ -51,6 +51,14 @@
51
  box-shadow: 0 0 15px #ffd700;
52
  border: 1px solid #ffd700;
53
  }
 
 
 
 
 
 
 
 
54
  </style>
55
  </head>
56
 
@@ -64,7 +72,7 @@
64
  <div id="authStep1">
65
  <h2 class="text-4xl font-bold text-center mb-2 text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 via-blue-500 to-purple-600 drop-shadow-[0_0_15px_rgba(34,211,238,0.5)]">NEXUS</h2>
66
  <p class="text-cyan-500/60 text-center mb-8 text-[10px] tracking-[0.3em] uppercase">Visualizador Semántico Neural v2.5</p>
67
- <button id="btnGoToAnon" class="w-full bg-white/5 hover:bg-white/10 text-cyan-300 border border-cyan-500/20 font-bold py-4 px-4 rounded-lg transition-all flex items-center justify-center gap-3 mb-6 group hover:shadow-[0_0_15px_rgba(34,211,238,0.2)]">
68
  <svg class="w-5 h-5 group-hover:scale-110 transition-transform text-cyan-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path></svg>
69
  Entrar como Anónimo
70
  </button>
@@ -83,8 +91,8 @@
83
  <div class="absolute inset-0 border border-cyan-500/0 rounded-lg group-hover:border-cyan-500/20 pointer-events-none transition-colors"></div>
84
  </div>
85
  <div class="flex gap-3 pt-2">
86
- <button type="button" id="loginButton" class="flex-1 bg-blue-600/10 hover:bg-blue-600/30 text-blue-400 py-2 rounded border border-blue-500/30 text-xs font-bold transition-all uppercase tracking-wider hover:shadow-[0_0_10px_rgba(59,130,246,0.3)]">Entrar</button>
87
- <button type="button" id="registerButton" class="flex-1 bg-green-600/10 hover:bg-green-600/30 text-green-400 py-2 rounded border border-green-500/30 text-xs font-bold transition-all uppercase tracking-wider hover:shadow-[0_0_10px_rgba(74,222,128,0.3)]">Registrar</button>
88
  </div>
89
  </form>
90
  <p id="loginMessage" class="text-center text-xs mt-4 min-h-[1.5rem] text-red-400 font-bold tracking-wide"></p>
@@ -93,10 +101,10 @@
93
  <h2 class="text-2xl font-bold text-white mb-2 text-center">Identidad Digital</h2>
94
  <p class="text-gray-400 text-xs mb-8 text-center">Asigna un nombre clave a tu constelación.</p>
95
  <input type="text" id="usernameInput" class="w-full p-4 rounded-lg bg-black/50 border border-white/10 text-white placeholder-gray-600 focus:outline-none focus:border-purple-500 transition-all text-lg mb-8 text-center tracking-[0.2em] font-bold" placeholder="NICKNAME">
96
- <button id="saveUsernameButton" class="w-full bg-gradient-to-r from-cyan-600 to-blue-700 hover:from-cyan-500 hover:to-blue-600 text-white font-bold py-4 px-4 rounded-lg shadow-[0_0_20px_rgba(6,182,212,0.4)] transition-all uppercase text-sm tracking-widest mb-4">
97
  Establecer Enlace Neural
98
  </button>
99
- <button id="backToStep1" class="w-full mt-2 text-gray-500 text-[10px] hover:text-white transition-colors uppercase tracking-widest">Abortar Secuencia</button>
100
  </div>
101
  </div>
102
  </div>
@@ -138,16 +146,16 @@
138
  </h1>
139
  <div class="flex items-center gap-3">
140
  <span id="authStatus" class="text-[9px] text-cyan-500/80 uppercase tracking-widest border border-cyan-500/20 px-2 py-1 rounded bg-cyan-900/10"></span>
141
- <button id="mainLogoutButton" class="text-red-400/70 hover:text-red-300 text-[10px] uppercase transition-colors font-bold tracking-wider">Salir</button>
142
  </div>
143
  </div>
144
 
145
  <div class="grid grid-cols-3 gap-2 mb-4">
146
- <button onclick="setGameMode('explorer')" id="btnModeExplorer" class="bg-cyan-900/30 border border-cyan-500/50 text-cyan-300 text-[9px] py-2 rounded uppercase tracking-wider hover:bg-cyan-800/50 transition-all font-bold">Explorar</button>
147
- <button onclick="setGameMode('miner')" id="btnModeMiner" class="bg-black/30 border border-white/10 text-gray-500 text-[9px] py-2 rounded uppercase tracking-wider hover:border-yellow-500/50 hover:text-yellow-400 transition-all font-bold">Minero</button>
148
- <button onclick="setGameMode('bridge')" id="btnModeBridge" class="bg-black/30 border border-white/10 text-gray-500 text-[9px] py-2 rounded uppercase tracking-wider hover:border-purple-500/50 hover:text-purple-400 transition-all font-bold">Puente</button>
149
  </div>
150
- <button onclick="setGameMode('comet')" id="btnModeComet" class="w-full mb-4 bg-black/30 border border-white/10 text-gray-500 text-[9px] py-2 rounded uppercase tracking-wider hover:border-red-500/50 hover:text-red-400 transition-all font-bold">Defensa Cometa</button>
151
 
152
  <div id="bridgeControls" class="hidden space-y-3 mb-4 p-3 bg-purple-900/10 rounded border border-purple-500/30">
153
  <div class="text-[10px] text-purple-300 uppercase tracking-widest mb-1">Objetivo del Puente</div>
@@ -188,13 +196,13 @@
188
  </div>
189
  <div class="flex items-center gap-3 justify-end">
190
  <span id="geminiKeyStatus" class="text-[9px] text-green-400 italic font-mono"></span>
191
- <button id="saveGeminiKeyBtn" class="bg-white/5 hover:bg-white/10 px-3 py-1.5 rounded text-gray-300 text-[10px] border border-white/10 transition-colors uppercase tracking-wider hover:border-cyan-500/30 hover:text-cyan-300">Guardar</button>
192
  </div>
193
  </div>
194
  </details>
195
 
196
  <div class="flex gap-2 mb-2">
197
- <button id="visualizeButton" class="relative w-full overflow-hidden bg-cyan-900/20 hover:bg-cyan-800/40 text-cyan-300 font-bold py-4 px-4 rounded-lg border border-cyan-500/30 transition-all flex items-center justify-center space-x-3 group hover:shadow-[0_0_15px_rgba(34,211,238,0.2)]">
198
  <div class="absolute inset-0 w-full h-full bg-gradient-to-r from-transparent via-cyan-500/10 to-transparent -translate-x-full group-hover:animate-shimmer"></div>
199
  <svg class="w-4 h-4 text-cyan-400" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
200
  <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z" />
@@ -217,8 +225,8 @@
217
 
218
  <div id="minimapContainer" class="fixed bottom-4 right-4 z-[200] glass-panel p-2 rounded-lg group w-[320px] transition-opacity duration-300">
219
  <div class="absolute top-2 right-2 flex gap-1 z-10 opacity-0 group-hover:opacity-100 transition-opacity duration-300">
220
- <button id="zoomOutButton" class="w-6 h-6 bg-black/80 hover:bg-cyan-900/50 rounded border border-white/20 text-white flex items-center justify-center text-xs backdrop-blur-sm transition-colors">-</button>
221
- <button id="zoomInButton" class="w-6 h-6 bg-black/80 hover:bg-cyan-900/50 rounded border border-white/20 text-white flex items-center justify-center text-xs backdrop-blur-sm transition-colors">+</button>
222
  </div>
223
  <canvas id="minimap" width="320" height="130" class="w-full h-[130px] bg-black/60 rounded border border-white/10 cursor-crosshair shadow-inner"></canvas>
224
  <div class="text-[9px] text-center text-cyan-500/40 mt-1 uppercase tracking-[0.3em]">Radar Galáctico</div>
@@ -274,6 +282,8 @@
274
  let userCentroidForComet = new THREE.Vector3(0,0,0);
275
  let bgParticles;
276
 
 
 
277
  let db, auth, analytics, userId = null, appId = "neuronal-1f3b9", userProfile = null;
278
  let userMaps = {}, userProfileCache = {};
279
  let isAuthReady = false, isFontReady = false;
@@ -295,6 +305,43 @@
295
  let authMode = null;
296
  const normalizeString = (str) => { if (!str) return ""; return str.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); };
297
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
298
  window.setGameMode = function(mode) {
299
  gameState.mode = mode;
300
  const els = ['btnModeExplorer', 'btnModeMiner', 'btnModeBridge', 'btnModeComet'];
@@ -307,7 +354,7 @@
307
  else if(mode==='comet') btn.classList.add('bg-red-900/30', 'text-red-400', 'border-red-500');
308
  else btn.classList.add('bg-cyan-900/30', 'text-cyan-300', 'border-cyan-500');
309
  } else {
310
- btn.className = "bg-black/30 border border-white/10 text-gray-500 text-[9px] py-2 rounded uppercase tracking-wider hover:bg-white/5 transition-all font-bold";
311
  if(id === 'btnModeComet') btn.classList.add('w-full', 'mb-4');
312
  }
313
  });
@@ -332,6 +379,8 @@
332
  gameState.cometActive = false;
333
  if(trashGroup) { scene.remove(trashGroup); trashGroup = null; }
334
  }
 
 
335
  }
336
 
337
  const loader = new FontLoader();
@@ -548,7 +597,7 @@
548
  const bloomPass = new THREE.UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.5, 0.4, 0.85);
549
  bloomPass.threshold = 0.15;
550
  bloomPass.strength = 1.4;
551
- bloomPass.radius = 0.6;
552
 
553
  composer = new THREE.EffectComposer(renderer);
554
  composer.addPass(renderScene);
@@ -562,6 +611,7 @@
562
 
563
  createAdvancedBackground();
564
  initAdvancedComet();
 
565
 
566
  const visBtn = document.getElementById('visualizeButton');
567
  if(!visBtn.dataset.bound) {
@@ -588,6 +638,59 @@
588
  animate();
589
  }
590
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
591
  function updateHUD() {
592
  document.getElementById('energyBar').style.width = gameState.energy + '%';
593
  document.getElementById('rankDisplay').innerText = gameState.rank;
@@ -787,6 +890,7 @@
787
  updateAdvancedComet(delta, time);
788
  updateRaycaster();
789
  drawMinimap();
 
790
 
791
  hashtagGroup.children.forEach(obj => {
792
  if (obj.userData.isText) {
 
51
  box-shadow: 0 0 15px #ffd700;
52
  border: 1px solid #ffd700;
53
  }
54
+ .ui-spark {
55
+ position: fixed;
56
+ pointer-events: none;
57
+ background: radial-gradient(circle, #fff, #22d3ee);
58
+ border-radius: 50%;
59
+ mix-blend-mode: screen;
60
+ z-index: 999999;
61
+ }
62
  </style>
63
  </head>
64
 
 
72
  <div id="authStep1">
73
  <h2 class="text-4xl font-bold text-center mb-2 text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 via-blue-500 to-purple-600 drop-shadow-[0_0_15px_rgba(34,211,238,0.5)]">NEXUS</h2>
74
  <p class="text-cyan-500/60 text-center mb-8 text-[10px] tracking-[0.3em] uppercase">Visualizador Semántico Neural v2.5</p>
75
+ <button id="btnGoToAnon" class="game-btn w-full bg-white/5 hover:bg-white/10 text-cyan-300 border border-cyan-500/20 font-bold py-4 px-4 rounded-lg transition-all flex items-center justify-center gap-3 mb-6 group hover:shadow-[0_0_15px_rgba(34,211,238,0.2)]">
76
  <svg class="w-5 h-5 group-hover:scale-110 transition-transform text-cyan-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path></svg>
77
  Entrar como Anónimo
78
  </button>
 
91
  <div class="absolute inset-0 border border-cyan-500/0 rounded-lg group-hover:border-cyan-500/20 pointer-events-none transition-colors"></div>
92
  </div>
93
  <div class="flex gap-3 pt-2">
94
+ <button type="button" id="loginButton" class="game-btn flex-1 bg-blue-600/10 hover:bg-blue-600/30 text-blue-400 py-2 rounded border border-blue-500/30 text-xs font-bold transition-all uppercase tracking-wider hover:shadow-[0_0_10px_rgba(59,130,246,0.3)]">Entrar</button>
95
+ <button type="button" id="registerButton" class="game-btn flex-1 bg-green-600/10 hover:bg-green-600/30 text-green-400 py-2 rounded border border-green-500/30 text-xs font-bold transition-all uppercase tracking-wider hover:shadow-[0_0_10px_rgba(74,222,128,0.3)]">Registrar</button>
96
  </div>
97
  </form>
98
  <p id="loginMessage" class="text-center text-xs mt-4 min-h-[1.5rem] text-red-400 font-bold tracking-wide"></p>
 
101
  <h2 class="text-2xl font-bold text-white mb-2 text-center">Identidad Digital</h2>
102
  <p class="text-gray-400 text-xs mb-8 text-center">Asigna un nombre clave a tu constelación.</p>
103
  <input type="text" id="usernameInput" class="w-full p-4 rounded-lg bg-black/50 border border-white/10 text-white placeholder-gray-600 focus:outline-none focus:border-purple-500 transition-all text-lg mb-8 text-center tracking-[0.2em] font-bold" placeholder="NICKNAME">
104
+ <button id="saveUsernameButton" class="game-btn w-full bg-gradient-to-r from-cyan-600 to-blue-700 hover:from-cyan-500 hover:to-blue-600 text-white font-bold py-4 px-4 rounded-lg shadow-[0_0_20px_rgba(6,182,212,0.4)] transition-all uppercase text-sm tracking-widest mb-4">
105
  Establecer Enlace Neural
106
  </button>
107
+ <button id="backToStep1" class="game-btn w-full mt-2 text-gray-500 text-[10px] hover:text-white transition-colors uppercase tracking-widest">Abortar Secuencia</button>
108
  </div>
109
  </div>
110
  </div>
 
146
  </h1>
147
  <div class="flex items-center gap-3">
148
  <span id="authStatus" class="text-[9px] text-cyan-500/80 uppercase tracking-widest border border-cyan-500/20 px-2 py-1 rounded bg-cyan-900/10"></span>
149
+ <button id="mainLogoutButton" class="game-btn text-red-400/70 hover:text-red-300 text-[10px] uppercase transition-colors font-bold tracking-wider">Salir</button>
150
  </div>
151
  </div>
152
 
153
  <div class="grid grid-cols-3 gap-2 mb-4">
154
+ <button onclick="setGameMode('explorer')" id="btnModeExplorer" class="game-btn bg-cyan-900/30 border border-cyan-500/50 text-cyan-300 text-[9px] py-2 rounded uppercase tracking-wider hover:bg-cyan-800/50 transition-all font-bold">Explorar</button>
155
+ <button onclick="setGameMode('miner')" id="btnModeMiner" class="game-btn bg-black/30 border border-white/10 text-gray-500 text-[9px] py-2 rounded uppercase tracking-wider hover:border-yellow-500/50 hover:text-yellow-400 transition-all font-bold">Minero</button>
156
+ <button onclick="setGameMode('bridge')" id="btnModeBridge" class="game-btn bg-black/30 border border-white/10 text-gray-500 text-[9px] py-2 rounded uppercase tracking-wider hover:border-purple-500/50 hover:text-purple-400 transition-all font-bold">Puente</button>
157
  </div>
158
+ <button onclick="setGameMode('comet')" id="btnModeComet" class="game-btn w-full mb-4 bg-black/30 border border-white/10 text-gray-500 text-[9px] py-2 rounded uppercase tracking-wider hover:border-red-500/50 hover:text-red-400 transition-all font-bold">Defensa Cometa</button>
159
 
160
  <div id="bridgeControls" class="hidden space-y-3 mb-4 p-3 bg-purple-900/10 rounded border border-purple-500/30">
161
  <div class="text-[10px] text-purple-300 uppercase tracking-widest mb-1">Objetivo del Puente</div>
 
196
  </div>
197
  <div class="flex items-center gap-3 justify-end">
198
  <span id="geminiKeyStatus" class="text-[9px] text-green-400 italic font-mono"></span>
199
+ <button id="saveGeminiKeyBtn" class="game-btn bg-white/5 hover:bg-white/10 px-3 py-1.5 rounded text-gray-300 text-[10px] border border-white/10 transition-colors uppercase tracking-wider hover:border-cyan-500/30 hover:text-cyan-300">Guardar</button>
200
  </div>
201
  </div>
202
  </details>
203
 
204
  <div class="flex gap-2 mb-2">
205
+ <button id="visualizeButton" class="game-btn relative w-full overflow-hidden bg-cyan-900/20 hover:bg-cyan-800/40 text-cyan-300 font-bold py-4 px-4 rounded-lg border border-cyan-500/30 transition-all flex items-center justify-center space-x-3 group hover:shadow-[0_0_15px_rgba(34,211,238,0.2)]">
206
  <div class="absolute inset-0 w-full h-full bg-gradient-to-r from-transparent via-cyan-500/10 to-transparent -translate-x-full group-hover:animate-shimmer"></div>
207
  <svg class="w-4 h-4 text-cyan-400" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
208
  <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z" />
 
225
 
226
  <div id="minimapContainer" class="fixed bottom-4 right-4 z-[200] glass-panel p-2 rounded-lg group w-[320px] transition-opacity duration-300">
227
  <div class="absolute top-2 right-2 flex gap-1 z-10 opacity-0 group-hover:opacity-100 transition-opacity duration-300">
228
+ <button id="zoomOutButton" class="game-btn w-6 h-6 bg-black/80 hover:bg-cyan-900/50 rounded border border-white/20 text-white flex items-center justify-center text-xs backdrop-blur-sm transition-colors">-</button>
229
+ <button id="zoomInButton" class="game-btn w-6 h-6 bg-black/80 hover:bg-cyan-900/50 rounded border border-white/20 text-white flex items-center justify-center text-xs backdrop-blur-sm transition-colors">+</button>
230
  </div>
231
  <canvas id="minimap" width="320" height="130" class="w-full h-[130px] bg-black/60 rounded border border-white/10 cursor-crosshair shadow-inner"></canvas>
232
  <div class="text-[9px] text-center text-cyan-500/40 mt-1 uppercase tracking-[0.3em]">Radar Galáctico</div>
 
282
  let userCentroidForComet = new THREE.Vector3(0,0,0);
283
  let bgParticles;
284
 
285
+ let meteors, meteorGeo;
286
+
287
  let db, auth, analytics, userId = null, appId = "neuronal-1f3b9", userProfile = null;
288
  let userMaps = {}, userProfileCache = {};
289
  let isAuthReady = false, isFontReady = false;
 
305
  let authMode = null;
306
  const normalizeString = (str) => { if (!str) return ""; return str.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); };
307
 
308
+ function spawnUIExplosion(x, y) {
309
+ const colors = ['#22d3ee', '#ffffff', '#ffd700'];
310
+ const particleCount = 20;
311
+
312
+ for (let i = 0; i < particleCount; i++) {
313
+ const spark = document.createElement('div');
314
+ spark.classList.add('ui-spark');
315
+ const size = Math.random() * 4 + 2;
316
+ spark.style.width = `${size}px`;
317
+ spark.style.height = `${size}px`;
318
+ spark.style.left = `${x}px`;
319
+ spark.style.top = `${y}px`;
320
+ spark.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
321
+
322
+ document.body.appendChild(spark);
323
+
324
+ const angle = Math.random() * Math.PI * 2;
325
+ const vel = Math.random() * 80 + 20;
326
+ const tx = Math.cos(angle) * vel;
327
+ const ty = Math.sin(angle) * vel;
328
+
329
+ spark.animate([
330
+ { transform: 'translate(0,0) scale(1)', opacity: 1 },
331
+ { transform: `translate(${tx}px, ${ty}px) scale(0)`, opacity: 0 }
332
+ ], {
333
+ duration: 600,
334
+ easing: 'cubic-bezier(0, .9, .57, 1)',
335
+ }).onfinish = () => spark.remove();
336
+ }
337
+ }
338
+
339
+ document.addEventListener('click', (e) => {
340
+ if (e.target.closest('button') || e.target.closest('.game-btn')) {
341
+ spawnUIExplosion(e.clientX, e.clientY);
342
+ }
343
+ });
344
+
345
  window.setGameMode = function(mode) {
346
  gameState.mode = mode;
347
  const els = ['btnModeExplorer', 'btnModeMiner', 'btnModeBridge', 'btnModeComet'];
 
354
  else if(mode==='comet') btn.classList.add('bg-red-900/30', 'text-red-400', 'border-red-500');
355
  else btn.classList.add('bg-cyan-900/30', 'text-cyan-300', 'border-cyan-500');
356
  } else {
357
+ btn.className = "game-btn bg-black/30 border border-white/10 text-gray-500 text-[9px] py-2 rounded uppercase tracking-wider hover:bg-white/5 transition-all font-bold";
358
  if(id === 'btnModeComet') btn.classList.add('w-full', 'mb-4');
359
  }
360
  });
 
379
  gameState.cometActive = false;
380
  if(trashGroup) { scene.remove(trashGroup); trashGroup = null; }
381
  }
382
+
383
+ if(meteors) meteors.visible = (mode === 'miner');
384
  }
385
 
386
  const loader = new FontLoader();
 
597
  const bloomPass = new THREE.UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.5, 0.4, 0.85);
598
  bloomPass.threshold = 0.15;
599
  bloomPass.strength = 1.4;
600
+ bloomPass.radius = 0.6;
601
 
602
  composer = new THREE.EffectComposer(renderer);
603
  composer.addPass(renderScene);
 
611
 
612
  createAdvancedBackground();
613
  initAdvancedComet();
614
+ initMeteorShower();
615
 
616
  const visBtn = document.getElementById('visualizeButton');
617
  if(!visBtn.dataset.bound) {
 
638
  animate();
639
  }
640
 
641
+ function initMeteorShower() {
642
+ const count = 200;
643
+ const geo = new THREE.BufferGeometry();
644
+ const positions = new Float32Array(count * 3);
645
+ const velocities = [];
646
+
647
+ for(let i=0; i<count; i++) {
648
+ positions[i*3] = (Math.random()-0.5) * 800;
649
+ positions[i*3+1] = Math.random() * 400 + 100;
650
+ positions[i*3+2] = (Math.random()-0.5) * 800;
651
+ velocities.push({
652
+ x: (Math.random()-0.5) * 2,
653
+ y: -(Math.random() * 5 + 5),
654
+ z: (Math.random()-0.5) * 2
655
+ });
656
+ }
657
+
658
+ geo.setAttribute('position', new THREE.BufferAttribute(positions, 3));
659
+ const mat = new THREE.PointsMaterial({
660
+ color: 0x00ffff,
661
+ size: 2,
662
+ transparent: true,
663
+ opacity: 0.8,
664
+ blending: THREE.AdditiveBlending,
665
+ depthWrite: false
666
+ });
667
+
668
+ meteors = new THREE.Points(geo, mat);
669
+ meteors.userData = { velocities: velocities };
670
+ meteors.visible = false;
671
+ scene.add(meteors);
672
+ }
673
+
674
+ function updateMeteors() {
675
+ if(!meteors || !meteors.visible) return;
676
+
677
+ const positions = meteors.geometry.attributes.position.array;
678
+ const vels = meteors.userData.velocities;
679
+
680
+ for(let i=0; i<vels.length; i++) {
681
+ positions[i*3] += vels[i].x;
682
+ positions[i*3+1] += vels[i].y;
683
+ positions[i*3+2] += vels[i].z;
684
+
685
+ if(positions[i*3+1] < -50) {
686
+ positions[i*3] = (Math.random()-0.5) * 800 + camera.position.x;
687
+ positions[i*3+1] = 400;
688
+ positions[i*3+2] = (Math.random()-0.5) * 800 + camera.position.z;
689
+ }
690
+ }
691
+ meteors.geometry.attributes.position.needsUpdate = true;
692
+ }
693
+
694
  function updateHUD() {
695
  document.getElementById('energyBar').style.width = gameState.energy + '%';
696
  document.getElementById('rankDisplay').innerText = gameState.rank;
 
890
  updateAdvancedComet(delta, time);
891
  updateRaycaster();
892
  drawMinimap();
893
+ if(gameState.mode === 'miner') updateMeteors();
894
 
895
  hashtagGroup.children.forEach(obj => {
896
  if (obj.userData.isText) {