SIMON Master Console Rebuild
True command center for SIMON + WEB360
This rebuild gives you a cleaner production spine: interactive tree, live viewer, guarded editor, dynamic graphics, architecture map, and note storage. It is designed to sit beside your existing
console.php
and become the stronger replacement path.
Dashboard
Tree
Viewer
System Map
File Registry
Notes
Files
15,680
Folders
433
Scanned Size
3.89 GB
PHP Files
988
Editable Text Files
12,938
File viewer
guarded to /htdocs
/downloads/galaxyminer2.html
<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover" /> <title>GALAXY MINER v2 — Big Bang Forge</title> <meta name="theme-color" content="#070b16" /> <style> :root{ --bg:#070b16; --bg2:#050812; --txt:#eaf2ff; --mut:#9fb0d8; --cyan:#6ae0ff; --ind:#7b62ff; --pink:#ff4fd6; --gold:#ffd166; --green:#44d18a; --bad:#ff4f6d; --panel:rgba(255,255,255,.07); --edge:rgba(255,255,255,.14); --shadow:0 18px 60px rgba(0,0,0,.55); --r:18px; } *{box-sizing:border-box} html,body{height:100%} body{ margin:0; overflow:hidden; background: radial-gradient(1000px 700px at 50% -10%, #162b74 0%, transparent 55%), radial-gradient(700px 500px at 90% 90%, rgba(123,98,255,.16), transparent 50%), radial-gradient(600px 460px at 10% 80%, rgba(255,79,214,.10), transparent 52%), linear-gradient(180deg,var(--bg),var(--bg2)); font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif; color:var(--txt); } canvas{position:fixed; inset:0; width:100%; height:100%} .ui{ position:fixed; top:14px; left:14px; right:14px; z-index:5; display:grid; grid-template-columns:1fr auto; gap:12px; pointer-events:none; } .panel{ pointer-events:auto; background:linear-gradient(180deg, rgba(255,255,255,.08), rgba(255,255,255,.03)); border:1px solid var(--edge); border-radius:var(--r); box-shadow:var(--shadow); backdrop-filter:blur(14px) saturate(130%); overflow:hidden; } .panel .inner{padding:12px 14px} .title{font-size:14px; letter-spacing:.16em; font-weight:800;} .sub{color:var(--mut); font-size:12px; margin-top:2px;} .toprow{display:flex; gap:10px; align-items:center; justify-content:space-between; flex-wrap:wrap;} .stats{display:flex; gap:10px; flex-wrap:wrap; margin-top:10px;} .pill{ font-size:12px; padding:7px 10px; border-radius:999px; border:1px solid rgba(255,255,255,.12); background:rgba(0,0,0,.18); color:var(--mut); white-space:nowrap; } .pill b{color:var(--txt)} .pill.ok{color:#d9ffea; border-color:rgba(68,209,138,.34)} .pill.bad{color:#ffd7df; border-color:rgba(255,79,109,.34)} .controls{pointer-events:auto; display:flex; gap:10px; flex-wrap:wrap;} .btn{ appearance:none; border:1px solid rgba(255,255,255,.16); background:rgba(0,0,0,.18); color:var(--txt); border-radius:14px; padding:10px 12px; cursor:pointer; box-shadow:0 10px 30px rgba(0,0,0,.30); } .btn.primary{ border-color:rgba(106,224,255,.28); background:linear-gradient(180deg, rgba(123,98,255,.38), rgba(106,224,255,.16)); } .btn.pink{ border-color:rgba(255,79,214,.28); background:linear-gradient(180deg, rgba(255,79,214,.20), rgba(0,0,0,.18)); } .btn.bad{ border-color:rgba(255,79,109,.28); background:linear-gradient(180deg, rgba(255,79,109,.22), rgba(0,0,0,.18)); } .bottom{ position:fixed; left:14px; right:14px; bottom:14px; z-index:5; display:grid; grid-template-columns:1fr 440px; gap:12px; } @media (max-width:1100px){ .bottom{grid-template-columns:1fr} } .readout{ min-height:138px; white-space:pre-wrap; line-height:1.45; font-size:13px; } .legend{ font-size:12px; line-height:1.55; color:var(--mut); } .bar{ width:100%; height:10px; border-radius:999px; overflow:hidden; background:rgba(255,255,255,.08); margin-top:8px; } .fill{ height:100%; width:0%; border-radius:999px; background:linear-gradient(90deg,var(--cyan),var(--ind),var(--pink)); } .overlay{ position:fixed; inset:0; display:grid; place-items:center; z-index:10; background:rgba(0,0,0,.32); backdrop-filter:blur(4px); } .modal{ width:min(960px,92vw); background:linear-gradient(180deg, rgba(12,16,34,.96), rgba(10,14,28,.92)); border:1px solid rgba(255,255,255,.16); border-radius:22px; box-shadow:0 26px 90px rgba(0,0,0,.68); padding:20px; } .modal h1{margin:0 0 8px; font-size:30px; line-height:1.05;} .modal p{margin:10px 0 0; color:var(--mut); line-height:1.5;} .modal .actions{display:flex; gap:10px; flex-wrap:wrap; margin-top:16px;} .kbd{ display:inline-block; font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:12px; padding:2px 6px; border:1px solid rgba(255,255,255,.14); border-radius:8px; background:rgba(0,0,0,.22); color:var(--txt); } .sectionTitle{ margin-top:10px; margin-bottom:6px; font-size:12px; letter-spacing:.12em; color:var(--mut); } </style> </head> <body> <canvas id="bg"></canvas> <canvas id="game"></canvas> <div class="ui"> <div class="panel"> <div class="inner"> <div class="toprow"> <div> <div class="title">GALAXY MINER v2 — BIG BANG FORGE</div> <div class="sub">sector mining • drones • pirates • crafting • black holes</div> </div> <div class="pill"> <span class="kbd">Hold Click</span> mine • <span class="kbd">Space</span> bang • <span class="kbd">S</span> stabilize • <span class="kbd">D</span> drone </div> </div> <div class="stats"> <div class="pill ok">Ore <b id="oreVal">0</b></div> <div class="pill">Gas <b id="gasVal">0</b></div> <div class="pill">Crystal <b id="crystalVal">0</b></div> <div class="pill">Dark <b id="darkVal">0</b></div> <div class="pill">Alloy <b id="alloyVal">0</b></div> <div class="pill">Lattice <b id="latticeVal">0</b></div> <div class="pill">Exotic <b id="exoticVal">0</b></div> <div class="pill">Reactor <b id="reactorVal">0%</b></div> <div class="pill bad">Instability <b id="instabilityVal">0</b></div> <div class="pill">Sector <b id="sectorVal">Alpha</b></div> <div class="pill">Drones <b id="droneVal">0</b></div> <div class="pill">Score <b id="scoreVal">0</b></div> </div> <div class="bar"><div class="fill" id="progressFill"></div></div> </div> </div> <div class="controls"> <button class="btn" id="soundBtn">Sound: Off</button> <button class="btn" id="sectorBtn">Next Sector</button> <button class="btn pink" id="evolveBtn">Craft / Evolve</button> <button class="btn" id="droneBtn">Buy Drone</button> <button class="btn bad" id="stabilizeBtn">Stabilize</button> <button class="btn primary" id="restartBtn">Restart</button> </div> </div> <div class="bottom"> <div class="panel"> <div class="inner readout" id="readout"> Mine the galaxy, fill the forge reactor, trigger micro big bangs, and craft evolved minerals. Watch out for pirate miners and black holes. </div> </div> <div class="panel"> <div class="inner legend"> <div class="sectionTitle">CRAFT TREE</div> Ore → Alloy Shard<br> Crystal → Lattice Gem<br> Gas + Dark Matter → Exotic Core<br><br> <div class="sectionTitle">SECTORS</div> Alpha: balanced field<br> Beta: crystal rich<br> Gamma: dark matter anomalies<br> Delta: pirate activity<br> Omega: black hole pressure<br><br> <div class="sectionTitle">DRONES</div> Drones auto-mine nearby nodes and help scale your forge. </div> </div> </div> <div class="overlay" id="startOverlay"> <div class="modal"> <h1>GALAXY MINER v2 ✨</h1> <p> Pilot a mining craft across dangerous sectors of the galaxy. Extract ore, gas, crystal, and dark matter, then compress that matter in a forge reactor to create micro big bangs that produce new minerals. </p> <p> In v2, you also manage mining drones, evade pirate miners, navigate black holes, and build a true mineral crafting ladder. </p> <div class="actions"> <button class="btn primary" id="startBtn">Begin</button> <button class="btn" id="howBtn">How to Play</button> </div> </div> </div> <script> (() => { const SECTORS = [ { name:"Alpha", ore:8, gas:6, crystal:5, dark:2, pirates:0.0, blackholes:0 }, { name:"Beta", ore:6, gas:5, crystal:9, dark:2, pirates:0.1, blackholes:0 }, { name:"Gamma", ore:5, gas:6, crystal:4, dark:6, pirates:0.12, blackholes:1 }, { name:"Delta", ore:7, gas:5, crystal:5, dark:4, pirates:0.25, blackholes:1 }, { name:"Omega", ore:6, gas:7, crystal:6, dark:7, pirates:0.18, blackholes:2 } ]; const bg = document.getElementById("bg"); const game = document.getElementById("game"); const bctx = bg.getContext("2d"); const ctx = game.getContext("2d"); const oreVal = document.getElementById("oreVal"); const gasVal = document.getElementById("gasVal"); const crystalVal = document.getElementById("crystalVal"); const darkVal = document.getElementById("darkVal"); const alloyVal = document.getElementById("alloyVal"); const latticeVal = document.getElementById("latticeVal"); const exoticVal = document.getElementById("exoticVal"); const reactorVal = document.getElementById("reactorVal"); const instabilityVal = document.getElementById("instabilityVal"); const sectorVal = document.getElementById("sectorVal"); const droneVal = document.getElementById("droneVal"); const scoreVal = document.getElementById("scoreVal"); const progressFill = document.getElementById("progressFill"); const readout = document.getElementById("readout"); const soundBtn = document.getElementById("soundBtn"); const sectorBtn = document.getElementById("sectorBtn"); const evolveBtn = document.getElementById("evolveBtn"); const droneBtn = document.getElementById("droneBtn"); const stabilizeBtn = document.getElementById("stabilizeBtn"); const restartBtn = document.getElementById("restartBtn"); const startOverlay = document.getElementById("startOverlay"); const startBtn = document.getElementById("startBtn"); const howBtn = document.getElementById("howBtn"); function fitCanvas(c){ const dpr = Math.max(1, Math.min(2, window.devicePixelRatio || 1)); const w = Math.floor(window.innerWidth * dpr); const h = Math.floor(window.innerHeight * dpr); if (c.width !== w || c.height !== h){ c.width = w; c.height = h; c._dpr = dpr; } } let audio = { ctx:null, on:false }; function initAudio(){ if (audio.ctx) return; const Ctx = window.AudioContext || window.webkitAudioContext; if (!Ctx) return; audio.ctx = new Ctx(); } function beep(type="ok", intensity=0.5){ if (!audio.on || !audio.ctx) return; const ac = audio.ctx; const t = ac.currentTime; const o = ac.createOscillator(); const g = ac.createGain(); const f = ac.createBiquadFilter(); const base = type==="bad" ? 150 : type==="bang" ? 95 : type==="evolve" ? 420 : type==="pirate" ? 180 : type==="mine" ? 260 : 300; o.type = type==="bad" ? "square" : type==="bang" ? "sawtooth" : type==="pirate" ? "sawtooth" : type==="evolve" ? "triangle" : "sine"; o.frequency.value = base + intensity*260; f.type = "lowpass"; f.frequency.value = 900 + intensity*3200; g.gain.setValueAtTime(0.0001, t); g.gain.exponentialRampToValueAtTime(0.05 + intensity*0.08, t + 0.02); g.gain.exponentialRampToValueAtTime(0.0001, t + (type==="bang" ? 0.42 : 0.20)); o.connect(f); f.connect(g); g.connect(ac.destination); o.start(t); o.stop(t + (type==="bang" ? 0.48 : 0.24)); } soundBtn.addEventListener("click", () => { if (!audio.ctx) initAudio(); audio.on = !audio.on; soundBtn.textContent = "Sound: " + (audio.on ? "On" : "Off"); if (audio.on) beep("ok", 0.35); }); const rand = (a,b)=>a+Math.random()*(b-a); const clamp = (v,a,b)=>Math.max(a,Math.min(b,v)); const dist = (ax,ay,bx,by)=>Math.hypot(ax-bx, ay-by); const lerp = (a,b,t)=>a+(b-a)*t; const state = { running:false, last:performance.now(), time:0, mouse:{x:0.5,y:0.5,down:false}, player:{x:0,y:0,r:16,glow:0}, stars:[], nodes:[], pirates:[], blackholes:[], drones:[], particles:[], bangs:[], ore:0, gas:0, crystal:0, dark:0, reactor:0, instability:0, score:0, sectorIndex:0, evolved:{alloy:0,lattice:0,exotic:0} }; function setReadout(text){ readout.textContent = text; } function currentSector(){ return SECTORS[state.sectorIndex]; } function initStars(){ fitCanvas(bg); fitCanvas(game); const w = bg.width / bg._dpr; const h = bg.height / bg._dpr; state.stars = Array.from({length: 220}, () => ({ x: Math.random()*w, y: Math.random()*h, z: Math.random(), r: rand(0.5, 2.2), tw: rand(0, Math.PI*2), sp: rand(0.2, 0.8) })); state.player.x = w * 0.5; state.player.y = h * 0.55; } function spawnNode(type){ const w = game.width / game._dpr; const h = game.height / game._dpr; const colors = { ore:"#ffd166", gas:"#69e2ff", crystal:"#ff4fd6", dark:"#7b62ff" }; state.nodes.push({ type, x: rand(40, w-40), y: rand(60, h-60), r: type==="dark" ? rand(14,22) : rand(12,20), hp: type==="dark" ? 150 : type==="crystal" ? 110 : 90, maxHp: type==="dark" ? 150 : type==="crystal" ? 110 : 90, color: colors[type], pulse: rand(0, Math.PI*2), driftX: rand(-0.2,0.2), driftY: rand(-0.2,0.2) }); } function spawnPirate(){ const w = game.width / game._dpr; const h = game.height / game._dpr; state.pirates.push({ x: rand(20,w-20), y: rand(20,h-20), r: 15, target:null, pulse: rand(0,Math.PI*2) }); } function spawnBlackhole(){ const w = game.width / game._dpr; const h = game.height / game._dpr; state.blackholes.push({ x: rand(w*0.2,w*0.8), y: rand(h*0.2,h*0.8), r: rand(28,40), pulse: rand(0,Math.PI*2) }); } function initSector(){ state.nodes = []; state.pirates = []; state.blackholes = []; const s = currentSector(); for(let i=0;i<s.ore;i++) spawnNode("ore"); for(let i=0;i<s.gas;i++) spawnNode("gas"); for(let i=0;i<s.crystal;i++) spawnNode("crystal"); for(let i=0;i<s.dark;i++) spawnNode("dark"); for(let i=0;i<s.blackholes;i++) spawnBlackhole(); const pirates = Math.round(s.pirates * 10); for(let i=0;i<pirates;i++) spawnPirate(); } function addBurst(x,y,color,count=18,power=1){ for (let i=0;i<count;i++){ const a = rand(0, Math.PI*2); const s = rand(40, 180) * power; state.particles.push({ x,y, vx: Math.cos(a)*s, vy: Math.sin(a)*s, life: rand(0.35, 0.9), ttl: rand(0.35, 0.9), color }); } } function addBang(x,y){ state.bangs.push({ x,y,r:8,max:220 + getTier()*18,v:280,a:0.95 }); } function getTier(){ return 1 + Math.floor((state.evolved.alloy + state.evolved.lattice + state.evolved.exotic) / 4); } function updateUI(){ oreVal.textContent = Math.floor(state.ore); gasVal.textContent = Math.floor(state.gas); crystalVal.textContent = Math.floor(state.crystal); darkVal.textContent = Math.floor(state.dark); alloyVal.textContent = state.evolved.alloy; latticeVal.textContent = state.evolved.lattice; exoticVal.textContent = state.evolved.exotic; reactorVal.textContent = `${Math.floor(state.reactor)}%`; instabilityVal.textContent = Math.floor(state.instability); sectorVal.textContent = currentSector().name; droneVal.textContent = state.drones.length; scoreVal.textContent = Math.floor(state.score); progressFill.style.width = `${clamp((state.evolved.alloy + state.evolved.lattice + state.evolved.exotic)/50,0,1)*100}%`; } function updatePlayer(dt){ const w = game.width / game._dpr; const h = game.height / game._dpr; const tx = state.mouse.x * w; const ty = state.mouse.y * h; state.player.x = lerp(state.player.x, tx, 0.08); state.player.y = lerp(state.player.y, ty, 0.08); state.player.x = clamp(state.player.x, 20, w-20); state.player.y = clamp(state.player.y, 20, h-20); state.player.glow = lerp(state.player.glow, state.mouse.down ? 1 : 0.3, 0.08); } function collectFromNode(n, yieldScale=1){ const tier = getTier(); if (n.type==="ore") state.ore += Math.round(12 * yieldScale * (1+tier*0.18)); if (n.type==="gas") state.gas += Math.round(11 * yieldScale * (1+tier*0.18)); if (n.type==="crystal") state.crystal += Math.round(9 * yieldScale * (1+tier*0.18)); if (n.type==="dark") state.dark += Math.round(6 * yieldScale * (1+tier*0.18)); state.reactor = clamp(state.reactor + (n.type==="dark" ? 18 : n.type==="crystal" ? 14 : 10)*yieldScale, 0, 100); state.score += 60 + tier*12; } function mineNodes(dt){ if (!state.mouse.down) return; let minedAny = false; for (let i=state.nodes.length-1;i>=0;i--){ const n = state.nodes[i]; const d = dist(state.player.x,state.player.y,n.x,n.y); if (d < 150){ minedAny = true; n.hp -= (20 + getTier()*6) * dt; if (Math.random() < 0.10) addBurst(n.x,n.y,n.color,4,0.4); if (n.hp <= 0){ collectFromNode(n, 1); addBurst(n.x,n.y,n.color,20,1.0); beep("mine", 0.45); state.nodes.splice(i,1); spawnNode(n.type); } } } if (minedAny) state.instability = clamp(state.instability + dt*1.6, 0, 100); } function updateDrones(dt){ for (const d of state.drones){ let nearest = null, best = Infinity; for (const n of state.nodes){ const dd = dist(d.x,d.y,n.x,n.y); if (dd < best){ best = dd; nearest = n; } } if (!nearest) continue; d.x = lerp(d.x, nearest.x, 0.012 + d.speed*dt); d.y = lerp(d.y, nearest.y, 0.012 + d.speed*dt); if (best < 80){ nearest.hp -= (8 + getTier()*1.8) * dt; if (nearest.hp <= 0){ collectFromNode(nearest, 0.65); addBurst(nearest.x,nearest.y,nearest.color,12,0.7); const idx = state.nodes.indexOf(nearest); if (idx >= 0){ const t = nearest.type; state.nodes.splice(idx,1); spawnNode(t); } } } } } function updatePirates(dt){ for (const p of state.pirates){ p.pulse += dt*2; let nearest = null, best = Infinity; for (const n of state.nodes){ const dd = dist(p.x,p.y,n.x,n.y); if (dd < best){ best = dd; nearest = n; } } if (!nearest) continue; p.x = lerp(p.x, nearest.x, 0.01 + dt*0.8); p.y = lerp(p.y, nearest.y, 0.01 + dt*0.8); if (best < 75){ nearest.hp -= 12 * dt; if (nearest.hp <= 0){ // pirates steal instead of giving you mats addBurst(nearest.x,nearest.y,"#ff4f6d",10,0.8); const idx = state.nodes.indexOf(nearest); if (idx >= 0){ const t = nearest.type; state.nodes.splice(idx,1); spawnNode(t); } state.score = Math.max(0, state.score - 20); if (Math.random() < 0.18) setReadout("Pirate miners stole a node yield."); } } if (dist(p.x,p.y,state.player.x,state.player.y) < 28){ state.instability = clamp(state.instability + 12*dt, 0, 100); state.score = Math.max(0, state.score - 16*dt); } } } function updateBlackholes(dt){ for (const b of state.blackholes){ b.pulse += dt*1.8; const d = dist(state.player.x,state.player.y,b.x,b.y); if (d < b.r*3.2){ const pull = clamp(1 - d/(b.r*3.2), 0, 1); state.player.x = lerp(state.player.x, b.x, 0.006 + pull*0.018); state.player.y = lerp(state.player.y, b.y, 0.006 + pull*0.018); state.instability = clamp(state.instability + pull*8*dt, 0, 100); } for (const drone of state.drones){ const dd = dist(drone.x,drone.y,b.x,b.y); if (dd < b.r*2.5){ drone.x = lerp(drone.x, b.x, 0.008); drone.y = lerp(drone.y, b.y, 0.008); } } } } function triggerBigBang(){ if (state.reactor < 100){ setReadout("Reactor not ready. Mine more matter until it reaches 100%."); return; } const tier = getTier(); state.reactor = 0; state.instability = clamp(state.instability + 18, 0, 100); state.score += 250 + tier*50; const cx = state.player.x; const cy = state.player.y; addBang(cx,cy); addBurst(cx,cy,"#ff4fd6",42,1.5); beep("bang", 0.95); const oreGain = Math.round(8 + tier*3 + state.dark*0.08); const gasGain = Math.round(7 + tier*2 + state.crystal*0.06); const crystalGain = Math.round(4 + tier*2 + state.ore*0.03); const darkGain = Math.round(2 + tier*1 + state.gas*0.02); state.ore += oreGain; state.gas += gasGain; state.crystal += crystalGain; state.dark += darkGain; setReadout( `BIG BANG FORGE IGNITED ✅ New matter cloud generated: • Ore +${oreGain} • Gas +${gasGain} • Crystal +${crystalGain} • Dark Matter +${darkGain} Instability rose. Stabilize if needed, then craft minerals.` ); updateUI(); } function stabilize(){ const cut = Math.min(state.instability, 22 + getTier()*2); state.instability = Math.max(0, state.instability - cut); state.score += 20; addBurst(state.player.x,state.player.y,"#44d18a",24,1.0); beep("ok", 0.55); setReadout(`Forge stabilized.\nInstability -${cut}`); updateUI(); } function evolveMinerals(){ let changed = []; if (state.ore >= 30){ state.ore -= 30; state.evolved.alloy += 1; state.score += 100; changed.push("Alloy Shard +1"); } if (state.crystal >= 18){ state.crystal -= 18; state.evolved.lattice += 1; state.score += 120; changed.push("Lattice Gem +1"); } if (state.gas >= 14 && state.dark >= 8){ state.gas -= 14; state.dark -= 8; state.evolved.exotic += 1; state.score += 180; changed.push("Exotic Core +1"); } if (!changed.length){ setReadout( `CRAFT FAILED Needed: • 30 Ore → Alloy Shard • 18 Crystal → Lattice Gem • 14 Gas + 8 Dark Matter → Exotic Core` ); return; } addBurst(state.player.x,state.player.y,"#b8f3ff",32,1.25); beep("evolve", 0.75); setReadout( `MINERAL EVOLUTION ✅ ${changed.join("\n")} Current stock: • Alloy Shard = ${state.evolved.alloy} • Lattice Gem = ${state.evolved.lattice} • Exotic Core = ${state.evolved.exotic} Tier is now ${getTier()}.` ); updateUI(); } function buyDrone(){ const cost = 2 + state.drones.length; if (state.evolved.alloy < cost){ setReadout(`Need ${cost} Alloy Shards to build a drone.`); return; } state.evolved.alloy -= cost; const w = game.width / game._dpr; const h = game.height / game._dpr; state.drones.push({ x: rand(w*0.3,w*0.7), y: rand(h*0.3,h*0.7), r: 10, speed: rand(0.7,1.2) }); state.score += 90; addBurst(state.player.x,state.player.y,"#69e2ff",18,0.8); setReadout(`Drone constructed ✅\nActive drones: ${state.drones.length}`); updateUI(); } function nextSector(){ state.sectorIndex = (state.sectorIndex + 1) % SECTORS.length; initSector(); setReadout(`Jumped to sector ${currentSector().name}.`); updateUI(); } function resetGame(){ state.time = 0; state.ore = 0; state.gas = 0; state.crystal = 0; state.dark = 0; state.reactor = 0; state.instability = 0; state.score = 0; state.drones = []; state.particles = []; state.bangs = []; state.sectorIndex = 0; state.evolved = { alloy:0, lattice:0, exotic:0 }; initSector(); updateUI(); setReadout("Mine the galaxy, fill the forge reactor, trigger micro big bangs, and craft evolved minerals. Watch out for pirate miners and black holes."); } function updateSimulation(dt){ for (const n of state.nodes){ n.pulse += dt * 2; n.x += n.driftX * getTier(); n.y += n.driftY * getTier(); const w = game.width / game._dpr; const h = game.height / game._dpr; if (n.x < 20 || n.x > w-20) n.driftX *= -1; if (n.y < 40 || n.y > h-20) n.driftY *= -1; } updateDrones(dt); updatePirates(dt); updateBlackholes(dt); if (state.instability > 70){ state.score = Math.max(0, state.score - dt*10); if (Math.random() < 0.01){ const loss = Math.min(state.ore, 1 + Math.floor(Math.random()*4)); state.ore -= loss; } } for (let i=state.bangs.length-1;i>=0;i--){ const b = state.bangs[i]; b.r += b.v * dt; b.a -= dt * 0.55; if (b.r >= b.max || b.a <= 0) state.bangs.splice(i,1); } for (let i=state.particles.length-1;i>=0;i--){ const p = state.particles[i]; p.life -= dt; p.x += p.vx * dt; p.y += p.vy * dt; p.vx *= 0.985; p.vy *= 0.985; if (p.life <= 0) state.particles.splice(i,1); } } function drawBackground(dt){ fitCanvas(bg); const dpr = bg._dpr || 1; const w = bg.width / dpr; const h = bg.height / dpr; bctx.setTransform(dpr,0,0,dpr,0,0); bctx.clearRect(0,0,w,h); for (const s of state.stars){ s.tw += dt*(0.4+s.sp); const tw = (Math.sin(s.tw)*0.5+0.5); bctx.globalAlpha = (0.16 + tw*0.54) * (0.35 + s.z*0.65); bctx.fillStyle = "#EAF2FF"; bctx.beginPath(); bctx.arc(s.x, s.y, s.r*(0.5+s.z), 0, Math.PI*2); bctx.fill(); } bctx.globalAlpha = 1; } function drawGame(){ fitCanvas(game); const dpr = game._dpr || 1; const w = game.width / dpr; const h = game.height / dpr; ctx.setTransform(dpr,0,0,dpr,0,0); ctx.clearRect(0,0,w,h); // black holes for (const b of state.blackholes){ const pulse = 0.5 + 0.5*Math.sin(b.pulse); const rr = b.r*(0.92+pulse*0.08); const grad = ctx.createRadialGradient(b.x,b.y,0,b.x,b.y,rr*2.6); grad.addColorStop(0,"rgba(0,0,0,.95)"); grad.addColorStop(0.35,"rgba(123,98,255,.35)"); grad.addColorStop(1,"rgba(0,0,0,0)"); ctx.fillStyle = grad; ctx.beginPath(); ctx.arc(b.x,b.y,rr*2.6,0,Math.PI*2); ctx.fill(); ctx.strokeStyle = "#7b62ff"; ctx.lineWidth = 2; ctx.beginPath(); ctx.arc(b.x,b.y,rr,0,Math.PI*2); ctx.stroke(); } // nodes for (const n of state.nodes){ const pulse = 0.5 + 0.5*Math.sin(n.pulse); const rr = n.r*(0.9+pulse*0.12); const grad = ctx.createRadialGradient(n.x,n.y,0,n.x,n.y,rr*2.4); grad.addColorStop(0, n.color); grad.addColorStop(0.35, n.color + "33"); grad.addColorStop(1, "rgba(0,0,0,0)"); ctx.fillStyle = grad; ctx.beginPath(); ctx.arc(n.x,n.y,rr*2.4,0,Math.PI*2); ctx.fill(); ctx.fillStyle = n.color; ctx.beginPath(); ctx.arc(n.x,n.y,rr,0,Math.PI*2); ctx.fill(); ctx.strokeStyle = "rgba(255,255,255,.16)"; ctx.lineWidth = 1.2; ctx.beginPath(); ctx.arc(n.x,n.y,rr+4,0,Math.PI*2); ctx.stroke(); const pct = n.hp / n.maxHp; ctx.strokeStyle = "rgba(255,255,255,.6)"; ctx.lineWidth = 2; ctx.beginPath(); ctx.arc(n.x,n.y,rr+8,-Math.PI/2,-Math.PI/2 + pct*Math.PI*2); ctx.stroke(); } // pirates for (const p of state.pirates){ const g = ctx.createRadialGradient(p.x,p.y,0,p.x,p.y,p.r*2.4); g.addColorStop(0,"rgba(255,79,109,.75)"); g.addColorStop(0.4,"rgba(255,79,109,.18)"); g.addColorStop(1,"rgba(0,0,0,0)"); ctx.fillStyle = g; ctx.beginPath(); ctx.arc(p.x,p.y,p.r*2.4,0,Math.PI*2); ctx.fill(); ctx.save(); ctx.translate(p.x,p.y); ctx.fillStyle = "#ff4f6d"; ctx.beginPath(); ctx.moveTo(16,0); ctx.lineTo(-10,-9); ctx.lineTo(-3,0); ctx.lineTo(-10,9); ctx.closePath(); ctx.fill(); ctx.restore(); } // drones for (const d of state.drones){ const g = ctx.createRadialGradient(d.x,d.y,0,d.x,d.y,d.r*2.2); g.addColorStop(0,"rgba(106,224,255,.60)"); g.addColorStop(1,"rgba(0,0,0,0)"); ctx.fillStyle = g; ctx.beginPath(); ctx.arc(d.x,d.y,d.r*2.2,0,Math.PI*2); ctx.fill(); ctx.strokeStyle = "#69e2ff"; ctx.lineWidth = 2; ctx.beginPath(); ctx.arc(d.x,d.y,d.r,0,Math.PI*2); ctx.stroke(); } // mining beam if (state.mouse.down){ let nearest = null, best = Infinity; for (const n of state.nodes){ const d = dist(state.player.x,state.player.y,n.x,n.y); if (d < 150 && d < best){ best = d; nearest = n; } } if (nearest){ ctx.strokeStyle = "rgba(106,224,255,.85)"; ctx.lineWidth = 2.5; ctx.beginPath(); ctx.moveTo(state.player.x,state.player.y); ctx.lineTo(nearest.x,nearest.y); ctx.stroke(); } } // drone beams for (const d of state.drones){ let nearest = null, best = Infinity; for (const n of state.nodes){ const dd = dist(d.x,d.y,n.x,n.y); if (dd < best){ best = dd; nearest = n; } } if (nearest && best < 80){ ctx.strokeStyle = "rgba(184,243,255,.5)"; ctx.lineWidth = 1.4; ctx.beginPath(); ctx.moveTo(d.x,d.y); ctx.lineTo(nearest.x,nearest.y); ctx.stroke(); } } // bang rings for (const b of state.bangs){ ctx.globalAlpha = b.a; ctx.strokeStyle = "#ff4fd6"; ctx.lineWidth = 2.8; ctx.beginPath(); ctx.arc(b.x,b.y,b.r,0,Math.PI*2); ctx.stroke(); } ctx.globalAlpha = 1; // particles for (const p of state.particles){ const a = p.life / p.ttl; ctx.globalAlpha = a; ctx.fillStyle = p.color; ctx.beginPath(); ctx.arc(p.x,p.y,1.8 + a*1.6,0,Math.PI*2); ctx.fill(); } ctx.globalAlpha = 1; // miner halo const glow = 36 + state.reactor*0.4; const g1 = ctx.createRadialGradient(state.player.x,state.player.y,0,state.player.x,state.player.y,glow); g1.addColorStop(0, `rgba(255,255,255,.20)`); g1.addColorStop(0.18, `rgba(106,224,255,.18)`); g1.addColorStop(0.45, `rgba(123,98,255,.16)`); g1.addColorStop(1, `rgba(0,0,0,0)`); ctx.fillStyle = g1; ctx.beginPath(); ctx.arc(state.player.x,state.player.y,glow,0,Math.PI*2); ctx.fill(); // miner craft ctx.save(); ctx.translate(state.player.x, state.player.y); ctx.fillStyle = "#6ae0ff"; ctx.beginPath(); ctx.moveTo(18,0); ctx.lineTo(-10,-10); ctx.lineTo(-4,0); ctx.lineTo(-10,10); ctx.closePath(); ctx.fill(); ctx.strokeStyle = "rgba(255,255,255,.45)"; ctx.lineWidth = 1.5; ctx.stroke(); if (state.instability > 70){ ctx.strokeStyle = "#ff4f6d"; ctx.beginPath(); ctx.arc(0,0,18 + Math.sin(state.time*10)*2,0,Math.PI*2); ctx.stroke(); } ctx.restore(); } function startGame(){ state.running = true; startOverlay.style.display = "none"; if (audio.ctx && audio.ctx.state === "suspended") audio.ctx.resume().catch(()=>{}); setReadout("Mine the galaxy, fill the forge reactor, trigger micro big bangs, and craft evolved minerals. Watch out for pirate miners and black holes."); beep("ok", 0.45); } startBtn.addEventListener("click", () => { if (!audio.ctx) initAudio(); startGame(); }); howBtn.addEventListener("click", () => { setReadout( `HOW TO PLAY • Move the miner with the mouse • Hold click near a node to mine it • Fill the reactor to 100% • Press Space to trigger a Big Bang Forge event • Press Craft / Evolve to refine rare materials • Press D to buy a drone • Press S to stabilize if instability rises • Change sectors for different resource mixes Goal: Grow your mineral civilization and climb the crafting ladder.` ); startOverlay.style.display = "none"; startGame(); }); evolveBtn.addEventListener("click", evolveMinerals); droneBtn.addEventListener("click", buyDrone); stabilizeBtn.addEventListener("click", stabilize); sectorBtn.addEventListener("click", nextSector); restartBtn.addEventListener("click", resetGame); window.addEventListener("mousemove", (e) => { state.mouse.x = e.clientX / window.innerWidth; state.mouse.y = e.clientY / window.innerHeight; }, {passive:true}); window.addEventListener("mousedown", () => { state.mouse.down = true; }, {passive:true}); window.addEventListener("mouseup", () => { state.mouse.down = false; }, {passive:true}); window.addEventListener("keydown", (e) => { const k = e.key.toLowerCase(); if (e.key === " "){ e.preventDefault(); triggerBigBang(); } if (k === "s") stabilize(); if (k === "d") buyDrone(); if (k === "r"){ resetGame(); startGame(); } if (k === "p"){ state.running = !state.running; setReadout(state.running ? "Simulation resumed." : "Simulation paused."); } }); function loop(now){ const dt = Math.min(0.033, (now - state.last)/1000); state.last = now; state.time += dt; drawBackground(dt); if (state.running){ updatePlayer(dt); mineNodes(dt); updateSimulation(dt); updateUI(); } drawGame(); requestAnimationFrame(loop); } window.addEventListener("resize", () => { initStars(); initSector(); }); initStars(); resetGame(); requestAnimationFrame(loop); })(); </script> </body> </html>
Save file
Quick jump
open a path
Open