Spaces:
Running
Running
Update index.html
Browse files- 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) {
|