Liveloop

Uma timeline interativa para redes sociais. Cada post é um app minúsculo que você pode jogar, salvar e remixar.

Produto

  • Feed
  • Jogos
  • Criar
  • Plugin do Claude Code
  • Blog

Jurídico

  • Política de Privacidade
  • Termos de Serviço
  • Política de Cookies
  • DMCA

Projeto

  • Templates
© 2026 Liveloop. Todos os direitos reservados.
LiveloopHistórico de versões

v2Atual

@joaobarrosfranca · 8/12/2026, 4:00:23 PM

Diferença em relação à v1.

-<!doctype html>
-<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><title>Void Vanguard 3D</title>
-<style>
-*{box-sizing:border-box}html,body{margin:0;height:100%;overflow:hidden;background:#030313;font-family:system-ui,-apple-system,sans-serif;touch-action:none}canvas{display:block}#hud{position:fixed;z-index:5;top:0;left:0;right:0;padding:18px 18px;color:white;display:flex;justify-content:space-between;pointer-events:none;text-shadow:0 2px 7px #000}.small{font-size:10px;font-weight:950;letter-spacing:1.7px;color:#cbd0ff}.number{font-size:29px;line-height:1;font-weight:1000}.right{text-align:right}.heart{color:#ff6d9c;font-size:19px;letter-spacing:2px}#bossHud{position:fixed;z-index:5;top:76px;left:15%;right:15%;display:none;text-align:center;color:#fff;font-size:10px;letter-spacing:2px;font-weight:950;text-shadow:0 2px 5px #000}.bossBar{height:9px;border:1px solid #ffe0ec;background:#230b2a;margin-top:5px;border-radius:5px;overflow:hidden}.bossFill{height:100%;width:100%;background:linear-gradient(90deg,#f61b7a,#ffb14e);transition:width .12s}.controls{position:fixed;z-index:6;bottom:18px;left:13px;right:13px;display:flex;justify-content:space-between;align-items:end}.dpad{position:relative;width:130px;height:112px}.dpad button,.fire{position:absolute;border:2px solid #ffffffa8;color:#fff;font-weight:1000;box-shadow:0 4px 12px #050518aa;user-select:none}.dpad button{width:43px;height:43px;border-radius:11px;background:#303b8ebd;font-size:19px}.up{top:0;left:44px}.down{bottom:0;left:44px}.left{top:34px;left:0}.rightBtn{top:34px;right:0}.fire{position:relative;width:71px;height:71px;border-radius:50%;background:#e63875ce;font-size:12px;letter-spacing:1px}.controls button:active{transform:scale(.93);filter:brightness(1.35)}#cover{position:fixed;z-index:10;inset:0;display:grid;place-items:center;text-align:center;padding:26px;background:radial-gradient(circle at 52% 15%,#6849ae99,transparent 34%),linear-gradient(155deg,#070826eb,#18103ce8 56%,#8e1f63c5);color:#fff}#card{max-width:325px}.tag{font-size:11px;letter-spacing:4px;font-weight:1000;color:#91f4ff}.title{font-size:54px;line-height:.8;font-weight:1000;letter-spacing:-4px;margin:18px 0 21px;text-shadow:4px 4px 0 #251044}.title span{color:#ff5ba6}.copy{font-size:16px;line-height:1.5;color:#e7e4ff;margin:0 0 26px}#start{border:3px solid #e6eaff;border-radius:6px;background:#7258e8;color:#fff;padding:15px 29px;font-weight:1000;font-size:14px;letter-spacing:1px;box-shadow:0 5px 0 #32176a;cursor:pointer}#start:active{transform:translateY(3px);box-shadow:0 2px 0 #32176a}.hint{font-size:12px;color:#d7d4ff;margin-top:18px}
-</style></head><body>
-<div id="hud"><div><div class="small">SCORE</div><div id="score" class="number">0</div></div><div class="right"><div class="small">LIVES</div><div id="lives" class="heart">♥ ♥ ♥</div></div></div>
-<div id="bossHud">DREADNOUGHT<div class="bossBar"><div id="bossFill" class="bossFill"></div></div></div>
-<div class="controls"><div class="dpad"><button id="up" class="up">▲</button><button id="down" class="down">▼</button><button id="left" class="left">◀</button><button id="right" class="rightBtn">▶</button></div><button id="fire" class="fire">FIRE</button></div>
-<div id="cover"><div id="card"><div class="tag">ARCADE SPACE ASSAULT</div><div class="title">VOID<br><span>VANGUARD</span></div><p id="copy" class="copy">Float through the void, blast the enemy fleet, and bring down their massive dreadnoughts.</p><button id="start" type="button">LAUNCH</button><div class="hint">Move with the pad or WASD · Fire with the button or Space</div></div></div>
-<script type="module">
-import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js";
-const scene=new THREE.Scene();scene.background=new THREE.Color(0x030313);scene.fog=new THREE.Fog(0x030313,15,58);
-const camera=new THREE.PerspectiveCamera(62,innerWidth/innerHeight,.1,100);camera.position.set(0,0,8.7);camera.lookAt(0,0,-10);
-const renderer=new THREE.WebGLRenderer({antialias:true});renderer.setPixelRatio(Math.min(devicePixelRatio,2));renderer.setSize(innerWidth,innerHeight);renderer.outputColorSpace=THREE.SRGBColorSpace;document.body.appendChild(renderer.domElement);
-scene.add(new THREE.HemisphereLight(0x6873ff,0x0b092b,2.2));const blue=new THREE.PointLight(0x4cdcff,13,15);blue.position.set(-3,2,2);scene.add(blue);const magenta=new THREE.PointLight(0xf34a9d,14,16);magenta.position.set(3,-1,-4);scene.add(magenta);
-const starGeo=new THREE.BufferGeometry(),stars=[];for(let i=0;i<650;i++){stars.push((Math.random()-.5)*30,(Math.random()-.5)*20,-Math.random()*70)}starGeo.setAttribute("position",new THREE.Float32BufferAttribute(stars,3));const starField=new THREE.Points(starGeo,new THREE.PointsMaterial({color:0xe4ecff,size:.065,sizeAttenuation:true}));scene.add(starField);
-function ship(color,enemy){const g=new THREE.Group(),mat=new THREE.MeshStandardMaterial({color,emissive:color,emissiveIntensity:.45,metalness:.55,roughness:.25}),dark=new THREE.MeshStandardMaterial({color:0x16162b,metalness:.65,roughness:.28});const core=new THREE.Mesh(new THREE.ConeGeometry(enemy?.42:.32,enemy?1.5:1.3,4),mat);core.rotation.x=-Math.PI/2;g.add(core);const wing=new THREE.Mesh(new THREE.BoxGeometry(enemy?1.65:1.35,.12,.75),mat);wing.position.z=.23;g.add(wing);const cockpit=new THREE.Mesh(new THREE.SphereGeometry(enemy?.25:.2,12,8),dark);cockpit.scale.set(1,.7,1.2);cockpit.position.z=-.12;g.add(cockpit);[-1,1].forEach(s=>{const engine=new THREE.Mesh(new THREE.CylinderGeometry(.1,.15,.45,8),dark);engine.rotation.x=Math.PI/2;engine.position.set(s*(enemy?.46:.35),0,.54);g.add(engine)});return g}
-const player=ship(0x63eaff,false);player.position.set(0,0,3.1);scene.add(player);
-const flame=new THREE.PointLight(0x54dcff,5,4);flame.position.z=.75;player.add(flame);
-const entities=[],shots=[];function laser(color){return new THREE.Mesh(new THREE.BoxGeometry(.09,.09,.7),new THREE.MeshBasicMaterial({color}))}
-function addEnemy(){const g=ship(Math.random()<.5?0xf35d9b:0x9167ff,true);g.position.set((Math.random()-.5)*6, (Math.random()-.5)*3.1,-42);scene.add(g);entities.push({g,hp:2,boss:false,shotAt:0})}
-function addBoss(){const g=new THREE.Group(),mat=new THREE.MeshStandardMaterial({color:0x8b236a,emissive:0x451139,emissiveIntensity:1.25,metalness:.55,roughness:.25}),dark=new THREE.MeshStandardMaterial({color:0x171126,metalness:.7,roughness:.2});const hull=new THREE.Mesh(new THREE.BoxGeometry(4.5,1.45,2.2),mat);g.add(hull);const crown=new THREE.Mesh(new THREE.ConeGeometry(1.2,2.2,6),mat);crown.rotation.x=-Math.PI/2;crown.position.z=-1.2;g.add(crown);[-1,1].forEach(s=>{const pod=new THREE.Mesh(new THREE.SphereGeometry(.7,12,8),dark);pod.position.set(s*2.35,0,.15);g.add(pod);const glow=new THREE.PointLight(0xff327e,4,4);glow.position.set(s*1.5,0,.4);g.add(glow)});g.position.set(0,0,-47);scene.add(g);entities.push({g,hp:45,maxHp:45,boss:true,shotAt:0});bossActive=true;document.querySelector("#bossHud").style.display="block";document.querySelector("#bossFill").style.width="100%"}
-function fire(playerShot){const s=laser(playerShot?0x8cffff:0xff558d);s.position.copy(playerShot?player.position:currentEnemyPos);s.position.z+=playerShot?-.75:.75;scene.add(s);shots.push({m:s,player:playerShot})}
-let currentEnemyPos=new THREE.Vector3(),running=false,score=0,lives=3,moveX=0,moveY=0,firing=false,last=0,nextEnemy=0,nextFire=0,nextBoss=12,kills=0,bossActive=false;
-const scoreEl=document.querySelector("#score"),livesEl=document.querySelector("#lives"),cover=document.querySelector("#cover"),copy=document.querySelector("#copy"),start=document.querySelector("#start"),bossHud=document.querySelector("#bossHud"),bossFill=document.querySelector("#bossFill");
-function updateLives(){livesEl.textContent=Array(lives).fill("♥").join(" ")||"—"}function clearAll(){entities.forEach(e=>scene.remove(e.g));shots.forEach(s=>scene.remove(s.m));entities.length=0;shots.length=0}
-function takeHit(){lives--;updateLives();player.rotation.z=.45;if(lives<=0){running=false;copy.innerHTML="Your final score: <b>"+score+"</b><br>Launch again and take the void back.";start.textContent="RELAUNCH";cover.style.display="grid";clearAll();bossHud.style.display="none"}}
-function destroy(i){const e=entities[i];scene.remove(e.g);entities.splice(i,1);score+=e.boss?50:5;kills+=e.boss?4:1;scoreEl.textContent=score;if(e.boss){bossActive=false;bossHud.style.display="none";nextBoss=kills+14}}
-function startGame(){clearAll();score=0;lives=3;kills=0;nextBoss=12;bossActive=false;player.position.set(0,0,3.1);scoreEl.textContent=0;updateLives();cover.style.display="none";bossHud.style.display="none";running=true;last=0;nextEnemy=0;nextFire=0}
-function hold(el,axis,v){el.addEventListener("pointerdown",e=>{e.preventDefault();if(axis==="x")moveX=v;else moveY=v});["pointerup","pointerleave","pointercancel"].forEach(t=>el.addEventListener(t,()=>{if(axis==="x")moveX=0;else moveY=0}))}
-hold(document.querySelector("#left"),"x",-1);hold(document.querySelector("#right"),"x",1);hold(document.querySelector("#up"),"y",1);hold(document.querySelector("#down"),"y",-1);
-const fireButton=document.querySelector("#fire");fireButton.addEventListener("pointerdown",e=>{e.preventDefault();firing=true});["pointerup","pointerleave","pointercancel"].forEach(t=>fireButton.addEventListener(t,()=>firing=false));
-start.addEventListener("click",startGame);
-addEventListener("keydown",e=>{const k=e.key.toLowerCase();if(k==="a"||k==="arrowleft")moveX=-1;if(k==="d"||k==="arrowright")moveX=1;if(k==="w"||k==="arrowup")moveY=1;if(k==="s"||k==="arrowdown")moveY=-1;if(k===" ")firing=true;if((k==="enter")&&!running)startGame()});addEventListener("keyup",e=>{const k=e.key.toLowerCase();if(k==="a"||k==="arrowleft"||k==="d"||k==="arrowright")moveX=0;if(k==="w"||k==="arrowup"||k==="s"||k==="arrowdown")moveY=0;if(k===" ")firing=false});
-function animate(t){requestAnimationFrame(animate);const dt=Math.min(35,last?t-last:16);last=t;const p=starGeo.attributes.position;for(let i=0;i<p.count;i++){let z=p.getZ(i)+dt*.018;if(z>7)z=-65;p.setZ(i,z)}p.needsUpdate=true;player.rotation.z+=(0-player.rotation.z)*.1;
-if(running){player.position.x=Math.max(-3.65,Math.min(3.65,player.position.x+moveX*dt*.005));player.position.y=Math.max(-2.35,Math.min(2.35,player.position.y+moveY*dt*.005));player.rotation.z=-moveX*.18;player.rotation.x=moveY*.1;
-if(!bossActive&&kills>=nextBoss)addBoss();if(!bossActive&&t>nextEnemy){addEnemy();nextEnemy=t+Math.max(360,780-score*2)}if(firing&&t>nextFire){fire(true);nextFire=t+170}
-for(let i=entities.length-1;i>=0;i--){const e=entities[i];if(e.boss){e.g.position.z+=(e.g.position.z<-10?dt*.012:0);e.g.position.x=Math.sin(t*.0012)*2.2;e.g.rotation.y=Math.sin(t*.001)*.1}else{e.g.position.z+=dt*.018;e.g.position.x+=Math.sin(t*.003+i)*dt*.001}e.g.rotation.z=Math.sin(t*.004+i)*.08;if(t-e.shotAt>(e.boss?800:1450)&&e.g.position.z>-20){currentEnemyPos.copy(e.g.position);fire(false);e.shotAt=t}if(e.g.position.distanceTo(player.position)<(e.boss?2.2:.72)){takeHit();scene.remove(e.g);entities.splice(i,1)}if(e.g.position.z>10){scene.remove(e.g);entities.splice(i,1)}}
-for(let i=shots.length-1;i>=0;i--){const s=shots[i];s.m.position.z+=s.player?-dt*.07:dt*.055;if(s.player){for(let j=entities.length-1;j>=0;j--){const e=entities[j];if(s.m.position.distanceTo(e.g.position)<(e.boss?2.3:.72)){e.hp--;scene.remove(s.m);shots.splice(i,1);if(e.boss)bossFill.style.width=(e.hp/e.maxHp*100)+"%";if(e.hp<=0)destroy(j);break}}}else if(s.m.position.distanceTo(player.position)<.58){scene.remove(s.m);shots.splice(i,1);takeHit();continue}if(s.m.position.z<-55||s.m.position.z>11){scene.remove(s.m);shots.splice(i,1)}}}
-renderer.render(scene,camera)}
-addEventListener("resize",()=>{camera.aspect=innerWidth/innerHeight;camera.updateProjectionMatrix();renderer.setSize(innerWidth,innerHeight)});animate(0);
+<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><style>
+*{box-sizing:border-box}html,body{margin:0;height:100%;overflow:hidden;background:#05061b;font-family:system-ui,sans-serif;touch-action:none}canvas{position:fixed;inset:0;width:100%;height:100%;z-index:0}.hud{position:fixed;z-index:3;top:0;left:0;right:0;padding:17px;display:flex;justify-content:space-between;color:#fff;pointer-events:none;text-shadow:0 2px 5px #000}.lab{font-size:10px;letter-spacing:1.7px;font-weight:950;color:#b9c9ff}.num{font-size:28px;font-weight:1000}.r{text-align:right}.life{color:#ff6d9b;font-size:19px;letter-spacing:2px}#power{position:fixed;z-index:3;top:74px;left:18px;color:#ffe66d;font-weight:900;font-size:11px;letter-spacing:1px;text-shadow:0 2px #000;display:none}.boss{position:fixed;z-index:3;top:71px;left:16%;right:16%;display:none;color:white;text-align:center;font-size:10px;font-weight:1000;letter-spacing:2px;text-shadow:0 2px #000}.bar{height:9px;border:2px solid #fff;background:#3b122b;border-radius:6px;overflow:hidden;margin-top:5px}.bar i{display:block;height:100%;width:100%;background:linear-gradient(90deg,#ff397b,#ffcc5a)}.controls{position:fixed;z-index:4;bottom:17px;left:13px;right:13px;display:flex;justify-content:space-between;align-items:end}.pad{position:relative;width:126px;height:108px}.pad button,.fire{position:absolute;border:2px solid #fff9;color:#fff;font-weight:1000;box-shadow:0 4px 11px #0009;cursor:pointer}.pad button{width:42px;height:42px;border-radius:12px;background:#343c96c9;font-size:18px}.u{top:0;left:42px}.d{bottom:0;left:42px}.l{top:33px;left:0}.rr{top:33px;right:0}.fire{position:relative;width:71px;height:71px;border-radius:50%;background:#e73e78cc;font-size:11px;letter-spacing:1px}.controls button:active{transform:scale(.94)}#overlay{position:fixed;z-index:8;inset:0;display:grid;place-items:center;text-align:center;padding:25px;color:#fff;background:radial-gradient(circle at 52% 15%,#5e52b777,transparent 34%),linear-gradient(155deg,#060626eb,#1a1042e8 56%,#89255fbe)}#card{max-width:325px}.tag{font-size:11px;letter-spacing:4px;font-weight:1000;color:#93efff}.title{font-size:54px;line-height:.8;font-weight:1000;letter-spacing:-4px;margin:18px;text-shadow:4px 4px #251044}.title span{color:#ff5ca8}.copy{font-size:16px;line-height:1.5}.start{border:3px solid #e4e9ff;border-radius:6px;background:#7158e8;color:#fff;padding:15px 28px;font-weight:1000;cursor:pointer;box-shadow:0 5px #32176a}.tip{font-size:12px;color:#d8d4ff;margin-top:17px}
+</style></head><body><canvas id="game"></canvas><div class="hud"><div><div class="lab">SCORE</div><div id="score" class="num">0</div></div><div class="r"><div class="lab">LIVES</div><div id="lives" class="life">♥ ♥ ♥</div></div></div><div id="power">POWER: ×1</div><div id="boss" class="boss">DREADNOUGHT<div class="bar"><i id="bossFill"></i></div></div><div class="controls"><div class="pad"><button id="up" class="u">▲</button><button id="down" class="d">▼</button><button id="left" class="l">◀</button><button id="right" class="rr">▶</button></div><button id="fire" class="fire">FIRE</button></div><div id="overlay"><div id="card"><div class="tag">2D ARCADE SPACE ASSAULT</div><div class="title">VOID<br><span>VANGUARD</span></div><p id="copy" class="copy">Fly through enemy formations, collect power cores, and destroy the dreadnoughts crossing your path.</p><button id="start" class="start">LAUNCH</button><div class="tip">WASD / arrows move · Space fires</div></div></div>
</script></body></html>

v2Atual

@joaobarrosfranca · 8/12/2026, 4:00:23 PM

Diferença em relação à v1.

-<!doctype html>
-<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><title>Void Vanguard 3D</title>
-<style>
-*{box-sizing:border-box}html,body{margin:0;height:100%;overflow:hidden;background:#030313;font-family:system-ui,-apple-system,sans-serif;touch-action:none}canvas{display:block}#hud{position:fixed;z-index:5;top:0;left:0;right:0;padding:18px 18px;color:white;display:flex;justify-content:space-between;pointer-events:none;text-shadow:0 2px 7px #000}.small{font-size:10px;font-weight:950;letter-spacing:1.7px;color:#cbd0ff}.number{font-size:29px;line-height:1;font-weight:1000}.right{text-align:right}.heart{color:#ff6d9c;font-size:19px;letter-spacing:2px}#bossHud{position:fixed;z-index:5;top:76px;left:15%;right:15%;display:none;text-align:center;color:#fff;font-size:10px;letter-spacing:2px;font-weight:950;text-shadow:0 2px 5px #000}.bossBar{height:9px;border:1px solid #ffe0ec;background:#230b2a;margin-top:5px;border-radius:5px;overflow:hidden}.bossFill{height:100%;width:100%;background:linear-gradient(90deg,#f61b7a,#ffb14e);transition:width .12s}.controls{position:fixed;z-index:6;bottom:18px;left:13px;right:13px;display:flex;justify-content:space-between;align-items:end}.dpad{position:relative;width:130px;height:112px}.dpad button,.fire{position:absolute;border:2px solid #ffffffa8;color:#fff;font-weight:1000;box-shadow:0 4px 12px #050518aa;user-select:none}.dpad button{width:43px;height:43px;border-radius:11px;background:#303b8ebd;font-size:19px}.up{top:0;left:44px}.down{bottom:0;left:44px}.left{top:34px;left:0}.rightBtn{top:34px;right:0}.fire{position:relative;width:71px;height:71px;border-radius:50%;background:#e63875ce;font-size:12px;letter-spacing:1px}.controls button:active{transform:scale(.93);filter:brightness(1.35)}#cover{position:fixed;z-index:10;inset:0;display:grid;place-items:center;text-align:center;padding:26px;background:radial-gradient(circle at 52% 15%,#6849ae99,transparent 34%),linear-gradient(155deg,#070826eb,#18103ce8 56%,#8e1f63c5);color:#fff}#card{max-width:325px}.tag{font-size:11px;letter-spacing:4px;font-weight:1000;color:#91f4ff}.title{font-size:54px;line-height:.8;font-weight:1000;letter-spacing:-4px;margin:18px 0 21px;text-shadow:4px 4px 0 #251044}.title span{color:#ff5ba6}.copy{font-size:16px;line-height:1.5;color:#e7e4ff;margin:0 0 26px}#start{border:3px solid #e6eaff;border-radius:6px;background:#7258e8;color:#fff;padding:15px 29px;font-weight:1000;font-size:14px;letter-spacing:1px;box-shadow:0 5px 0 #32176a;cursor:pointer}#start:active{transform:translateY(3px);box-shadow:0 2px 0 #32176a}.hint{font-size:12px;color:#d7d4ff;margin-top:18px}
-</style></head><body>
-<div id="hud"><div><div class="small">SCORE</div><div id="score" class="number">0</div></div><div class="right"><div class="small">LIVES</div><div id="lives" class="heart">♥ ♥ ♥</div></div></div>
-<div id="bossHud">DREADNOUGHT<div class="bossBar"><div id="bossFill" class="bossFill"></div></div></div>
-<div class="controls"><div class="dpad"><button id="up" class="up">▲</button><button id="down" class="down">▼</button><button id="left" class="left">◀</button><button id="right" class="rightBtn">▶</button></div><button id="fire" class="fire">FIRE</button></div>
-<div id="cover"><div id="card"><div class="tag">ARCADE SPACE ASSAULT</div><div class="title">VOID<br><span>VANGUARD</span></div><p id="copy" class="copy">Float through the void, blast the enemy fleet, and bring down their massive dreadnoughts.</p><button id="start" type="button">LAUNCH</button><div class="hint">Move with the pad or WASD · Fire with the button or Space</div></div></div>
-<script type="module">
-import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js";
-const scene=new THREE.Scene();scene.background=new THREE.Color(0x030313);scene.fog=new THREE.Fog(0x030313,15,58);
-const camera=new THREE.PerspectiveCamera(62,innerWidth/innerHeight,.1,100);camera.position.set(0,0,8.7);camera.lookAt(0,0,-10);
-const renderer=new THREE.WebGLRenderer({antialias:true});renderer.setPixelRatio(Math.min(devicePixelRatio,2));renderer.setSize(innerWidth,innerHeight);renderer.outputColorSpace=THREE.SRGBColorSpace;document.body.appendChild(renderer.domElement);
-scene.add(new THREE.HemisphereLight(0x6873ff,0x0b092b,2.2));const blue=new THREE.PointLight(0x4cdcff,13,15);blue.position.set(-3,2,2);scene.add(blue);const magenta=new THREE.PointLight(0xf34a9d,14,16);magenta.position.set(3,-1,-4);scene.add(magenta);
-const starGeo=new THREE.BufferGeometry(),stars=[];for(let i=0;i<650;i++){stars.push((Math.random()-.5)*30,(Math.random()-.5)*20,-Math.random()*70)}starGeo.setAttribute("position",new THREE.Float32BufferAttribute(stars,3));const starField=new THREE.Points(starGeo,new THREE.PointsMaterial({color:0xe4ecff,size:.065,sizeAttenuation:true}));scene.add(starField);
-function ship(color,enemy){const g=new THREE.Group(),mat=new THREE.MeshStandardMaterial({color,emissive:color,emissiveIntensity:.45,metalness:.55,roughness:.25}),dark=new THREE.MeshStandardMaterial({color:0x16162b,metalness:.65,roughness:.28});const core=new THREE.Mesh(new THREE.ConeGeometry(enemy?.42:.32,enemy?1.5:1.3,4),mat);core.rotation.x=-Math.PI/2;g.add(core);const wing=new THREE.Mesh(new THREE.BoxGeometry(enemy?1.65:1.35,.12,.75),mat);wing.position.z=.23;g.add(wing);const cockpit=new THREE.Mesh(new THREE.SphereGeometry(enemy?.25:.2,12,8),dark);cockpit.scale.set(1,.7,1.2);cockpit.position.z=-.12;g.add(cockpit);[-1,1].forEach(s=>{const engine=new THREE.Mesh(new THREE.CylinderGeometry(.1,.15,.45,8),dark);engine.rotation.x=Math.PI/2;engine.position.set(s*(enemy?.46:.35),0,.54);g.add(engine)});return g}
-const player=ship(0x63eaff,false);player.position.set(0,0,3.1);scene.add(player);
-const flame=new THREE.PointLight(0x54dcff,5,4);flame.position.z=.75;player.add(flame);
-const entities=[],shots=[];function laser(color){return new THREE.Mesh(new THREE.BoxGeometry(.09,.09,.7),new THREE.MeshBasicMaterial({color}))}
-function addEnemy(){const g=ship(Math.random()<.5?0xf35d9b:0x9167ff,true);g.position.set((Math.random()-.5)*6, (Math.random()-.5)*3.1,-42);scene.add(g);entities.push({g,hp:2,boss:false,shotAt:0})}
-function addBoss(){const g=new THREE.Group(),mat=new THREE.MeshStandardMaterial({color:0x8b236a,emissive:0x451139,emissiveIntensity:1.25,metalness:.55,roughness:.25}),dark=new THREE.MeshStandardMaterial({color:0x171126,metalness:.7,roughness:.2});const hull=new THREE.Mesh(new THREE.BoxGeometry(4.5,1.45,2.2),mat);g.add(hull);const crown=new THREE.Mesh(new THREE.ConeGeometry(1.2,2.2,6),mat);crown.rotation.x=-Math.PI/2;crown.position.z=-1.2;g.add(crown);[-1,1].forEach(s=>{const pod=new THREE.Mesh(new THREE.SphereGeometry(.7,12,8),dark);pod.position.set(s*2.35,0,.15);g.add(pod);const glow=new THREE.PointLight(0xff327e,4,4);glow.position.set(s*1.5,0,.4);g.add(glow)});g.position.set(0,0,-47);scene.add(g);entities.push({g,hp:45,maxHp:45,boss:true,shotAt:0});bossActive=true;document.querySelector("#bossHud").style.display="block";document.querySelector("#bossFill").style.width="100%"}
-function fire(playerShot){const s=laser(playerShot?0x8cffff:0xff558d);s.position.copy(playerShot?player.position:currentEnemyPos);s.position.z+=playerShot?-.75:.75;scene.add(s);shots.push({m:s,player:playerShot})}
-let currentEnemyPos=new THREE.Vector3(),running=false,score=0,lives=3,moveX=0,moveY=0,firing=false,last=0,nextEnemy=0,nextFire=0,nextBoss=12,kills=0,bossActive=false;
-const scoreEl=document.querySelector("#score"),livesEl=document.querySelector("#lives"),cover=document.querySelector("#cover"),copy=document.querySelector("#copy"),start=document.querySelector("#start"),bossHud=document.querySelector("#bossHud"),bossFill=document.querySelector("#bossFill");
-function updateLives(){livesEl.textContent=Array(lives).fill("♥").join(" ")||"—"}function clearAll(){entities.forEach(e=>scene.remove(e.g));shots.forEach(s=>scene.remove(s.m));entities.length=0;shots.length=0}
-function takeHit(){lives--;updateLives();player.rotation.z=.45;if(lives<=0){running=false;copy.innerHTML="Your final score: <b>"+score+"</b><br>Launch again and take the void back.";start.textContent="RELAUNCH";cover.style.display="grid";clearAll();bossHud.style.display="none"}}
-function destroy(i){const e=entities[i];scene.remove(e.g);entities.splice(i,1);score+=e.boss?50:5;kills+=e.boss?4:1;scoreEl.textContent=score;if(e.boss){bossActive=false;bossHud.style.display="none";nextBoss=kills+14}}
-function startGame(){clearAll();score=0;lives=3;kills=0;nextBoss=12;bossActive=false;player.position.set(0,0,3.1);scoreEl.textContent=0;updateLives();cover.style.display="none";bossHud.style.display="none";running=true;last=0;nextEnemy=0;nextFire=0}
-function hold(el,axis,v){el.addEventListener("pointerdown",e=>{e.preventDefault();if(axis==="x")moveX=v;else moveY=v});["pointerup","pointerleave","pointercancel"].forEach(t=>el.addEventListener(t,()=>{if(axis==="x")moveX=0;else moveY=0}))}
-hold(document.querySelector("#left"),"x",-1);hold(document.querySelector("#right"),"x",1);hold(document.querySelector("#up"),"y",1);hold(document.querySelector("#down"),"y",-1);
-const fireButton=document.querySelector("#fire");fireButton.addEventListener("pointerdown",e=>{e.preventDefault();firing=true});["pointerup","pointerleave","pointercancel"].forEach(t=>fireButton.addEventListener(t,()=>firing=false));
-start.addEventListener("click",startGame);
-addEventListener("keydown",e=>{const k=e.key.toLowerCase();if(k==="a"||k==="arrowleft")moveX=-1;if(k==="d"||k==="arrowright")moveX=1;if(k==="w"||k==="arrowup")moveY=1;if(k==="s"||k==="arrowdown")moveY=-1;if(k===" ")firing=true;if((k==="enter")&&!running)startGame()});addEventListener("keyup",e=>{const k=e.key.toLowerCase();if(k==="a"||k==="arrowleft"||k==="d"||k==="arrowright")moveX=0;if(k==="w"||k==="arrowup"||k==="s"||k==="arrowdown")moveY=0;if(k===" ")firing=false});
-function animate(t){requestAnimationFrame(animate);const dt=Math.min(35,last?t-last:16);last=t;const p=starGeo.attributes.position;for(let i=0;i<p.count;i++){let z=p.getZ(i)+dt*.018;if(z>7)z=-65;p.setZ(i,z)}p.needsUpdate=true;player.rotation.z+=(0-player.rotation.z)*.1;
-if(running){player.position.x=Math.max(-3.65,Math.min(3.65,player.position.x+moveX*dt*.005));player.position.y=Math.max(-2.35,Math.min(2.35,player.position.y+moveY*dt*.005));player.rotation.z=-moveX*.18;player.rotation.x=moveY*.1;
-if(!bossActive&&kills>=nextBoss)addBoss();if(!bossActive&&t>nextEnemy){addEnemy();nextEnemy=t+Math.max(360,780-score*2)}if(firing&&t>nextFire){fire(true);nextFire=t+170}
-for(let i=entities.length-1;i>=0;i--){const e=entities[i];if(e.boss){e.g.position.z+=(e.g.position.z<-10?dt*.012:0);e.g.position.x=Math.sin(t*.0012)*2.2;e.g.rotation.y=Math.sin(t*.001)*.1}else{e.g.position.z+=dt*.018;e.g.position.x+=Math.sin(t*.003+i)*dt*.001}e.g.rotation.z=Math.sin(t*.004+i)*.08;if(t-e.shotAt>(e.boss?800:1450)&&e.g.position.z>-20){currentEnemyPos.copy(e.g.position);fire(false);e.shotAt=t}if(e.g.position.distanceTo(player.position)<(e.boss?2.2:.72)){takeHit();scene.remove(e.g);entities.splice(i,1)}if(e.g.position.z>10){scene.remove(e.g);entities.splice(i,1)}}
-for(let i=shots.length-1;i>=0;i--){const s=shots[i];s.m.position.z+=s.player?-dt*.07:dt*.055;if(s.player){for(let j=entities.length-1;j>=0;j--){const e=entities[j];if(s.m.position.distanceTo(e.g.position)<(e.boss?2.3:.72)){e.hp--;scene.remove(s.m);shots.splice(i,1);if(e.boss)bossFill.style.width=(e.hp/e.maxHp*100)+"%";if(e.hp<=0)destroy(j);break}}}else if(s.m.position.distanceTo(player.position)<.58){scene.remove(s.m);shots.splice(i,1);takeHit();continue}if(s.m.position.z<-55||s.m.position.z>11){scene.remove(s.m);shots.splice(i,1)}}}
-renderer.render(scene,camera)}
-addEventListener("resize",()=>{camera.aspect=innerWidth/innerHeight;camera.updateProjectionMatrix();renderer.setSize(innerWidth,innerHeight)});animate(0);
+<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><style>
+*{box-sizing:border-box}html,body{margin:0;height:100%;overflow:hidden;background:#05061b;font-family:system-ui,sans-serif;touch-action:none}canvas{position:fixed;inset:0;width:100%;height:100%;z-index:0}.hud{position:fixed;z-index:3;top:0;left:0;right:0;padding:17px;display:flex;justify-content:space-between;color:#fff;pointer-events:none;text-shadow:0 2px 5px #000}.lab{font-size:10px;letter-spacing:1.7px;font-weight:950;color:#b9c9ff}.num{font-size:28px;font-weight:1000}.r{text-align:right}.life{color:#ff6d9b;font-size:19px;letter-spacing:2px}#power{position:fixed;z-index:3;top:74px;left:18px;color:#ffe66d;font-weight:900;font-size:11px;letter-spacing:1px;text-shadow:0 2px #000;display:none}.boss{position:fixed;z-index:3;top:71px;left:16%;right:16%;display:none;color:white;text-align:center;font-size:10px;font-weight:1000;letter-spacing:2px;text-shadow:0 2px #000}.bar{height:9px;border:2px solid #fff;background:#3b122b;border-radius:6px;overflow:hidden;margin-top:5px}.bar i{display:block;height:100%;width:100%;background:linear-gradient(90deg,#ff397b,#ffcc5a)}.controls{position:fixed;z-index:4;bottom:17px;left:13px;right:13px;display:flex;justify-content:space-between;align-items:end}.pad{position:relative;width:126px;height:108px}.pad button,.fire{position:absolute;border:2px solid #fff9;color:#fff;font-weight:1000;box-shadow:0 4px 11px #0009;cursor:pointer}.pad button{width:42px;height:42px;border-radius:12px;background:#343c96c9;font-size:18px}.u{top:0;left:42px}.d{bottom:0;left:42px}.l{top:33px;left:0}.rr{top:33px;right:0}.fire{position:relative;width:71px;height:71px;border-radius:50%;background:#e73e78cc;font-size:11px;letter-spacing:1px}.controls button:active{transform:scale(.94)}#overlay{position:fixed;z-index:8;inset:0;display:grid;place-items:center;text-align:center;padding:25px;color:#fff;background:radial-gradient(circle at 52% 15%,#5e52b777,transparent 34%),linear-gradient(155deg,#060626eb,#1a1042e8 56%,#89255fbe)}#card{max-width:325px}.tag{font-size:11px;letter-spacing:4px;font-weight:1000;color:#93efff}.title{font-size:54px;line-height:.8;font-weight:1000;letter-spacing:-4px;margin:18px;text-shadow:4px 4px #251044}.title span{color:#ff5ca8}.copy{font-size:16px;line-height:1.5}.start{border:3px solid #e4e9ff;border-radius:6px;background:#7158e8;color:#fff;padding:15px 28px;font-weight:1000;cursor:pointer;box-shadow:0 5px #32176a}.tip{font-size:12px;color:#d8d4ff;margin-top:17px}
+</style></head><body><canvas id="game"></canvas><div class="hud"><div><div class="lab">SCORE</div><div id="score" class="num">0</div></div><div class="r"><div class="lab">LIVES</div><div id="lives" class="life">♥ ♥ ♥</div></div></div><div id="power">POWER: ×1</div><div id="boss" class="boss">DREADNOUGHT<div class="bar"><i id="bossFill"></i></div></div><div class="controls"><div class="pad"><button id="up" class="u">▲</button><button id="down" class="d">▼</button><button id="left" class="l">◀</button><button id="right" class="rr">▶</button></div><button id="fire" class="fire">FIRE</button></div><div id="overlay"><div id="card"><div class="tag">2D ARCADE SPACE ASSAULT</div><div class="title">VOID<br><span>VANGUARD</span></div><p id="copy" class="copy">Fly through enemy formations, collect power cores, and destroy the dreadnoughts crossing your path.</p><button id="start" class="start">LAUNCH</button><div class="tip">WASD / arrows move · Space fires</div></div></div>
</script></body></html>
+<script>
+<script>
+const cv=document.getElementById("game"),g=cv.getContext("2d"),el={score:document.getElementById("score"),lives:document.getElementById("lives"),power:document.getElementById("power"),boss:document.getElementById("boss"),fill:document.getElementById("bossFill"),overlay:document.getElementById("overlay"),copy:document.getElementById("copy"),start:document.getElementById("start")};let W,H,stars=[],keys={},player,enemies=[],shots=[],drops=[],boss=null,run=false,score=0,lives=3,level=1,last=0,spawn=0,fireAt=0,bossAt=0;
+const cv=document.getElementById("game"),g=cv.getContext("2d"),el={score:document.getElementById("score"),lives:document.getElementById("lives"),power:document.getElementById("power"),boss:document.getElementById("boss"),fill:document.getElementById("bossFill"),overlay:document.getElementById("overlay"),copy:document.getElementById("copy"),start:document.getElementById("start")};let W,H,stars=[],keys={},player,enemies=[],shots=[],drops=[],boss=null,run=false,score=0,lives=3,level=1,last=0,spawn=0,fireAt=0,bossAt=0;
+function size(){W=cv.width=innerWidth;H=cv.height=innerHeight;stars=Array.from({length:110},()=>({x:Math.random()*W,y:Math.random()*H,z:1+Math.random()*3}))}addEventListener("resize",size);size();
+function size(){W=cv.width=innerWidth;H=cv.height=innerHeight;stars=Array.from({length:110},()=>({x:Math.random()*W,y:Math.random()*H,z:1+Math.random()*3}))}addEventListener("resize",size);size();
+function reset(){player={x:W*.5,y:H*.72,r:18,power:1,inv:0};enemies=[];shots=[];drops=[];boss=null;score=0;lives=3;level=1;spawn=0;fireAt=0;bossAt=18;el.score.textContent=0;el.lives.textContent="♥ ♥ ♥";el.power.style.display="none";el.boss.style.display="none";run=true;el.overlay.style.display="none";last=0}
+function reset(){player={x:W*.5,y:H*.72,r:18,power:1,inv:0};enemies=[];shots=[];drops=[];boss=null;score=0;lives=3;level=1;spawn=0;fireAt=0;bossAt=18;el.score.textContent=0;el.lives.textContent="♥ ♥ ♥";el.power.style.display="none";el.boss.style.display="none";run=true;el.overlay.style.display="none";last=0}
+function enemy(){let type=Math.random()<.25?"cross":"down";enemies.push({type,x:type==="cross"?(Math.random()<.5?-40:W+40):40+Math.random()*(W-80),y:-35,vx:type==="cross"?(Math.random()<.5?2.3:-2.3):0,vy:type==="cross"?1.15:1.5+Math.random(),hp:2,r:16,shot:0})}
+function enemy(){let type=Math.random()<.25?"cross":"down";enemies.push({type,x:type==="cross"?(Math.random()<.5?-40:W+40):40+Math.random()*(W-80),y:-35,vx:type==="cross"?(Math.random()<.5?2.3:-2.3):0,vy:type==="cross"?1.15:1.5+Math.random(),hp:2,r:16,shot:0})}
+function shoot(x,y,vx,vy,friendly){shots.push({x,y,vx,vy,friendly,r:friendly?4:5})}
+function shoot(x,y,vx,vy,friendly){shots.push({x,y,vx,vy,friendly,r:friendly?4:5})}
+function fire(){if(!run)return;let n=player.power;for(let i=0;i<n;i++){let spread=(i-(n-1)/2)*.18;shoot(player.x,player.y-20,spread,-8,true)}}
+function fire(){if(!run)return;let n=player.power;for(let i=0;i<n;i++){let spread=(i-(n-1)/2)*.18;shoot(player.x,player.y-20,spread,-8,true)}}
+function hit(){if(player.inv>0)return;lives--;player.inv=1300;el.lives.textContent=Array(lives).fill("♥").join(" ")||"—";if(lives<=0){run=false;el.copy.innerHTML="The fleet overwhelmed you.<br>Score: <b>"+score+"</b>";el.start.textContent="RELAUNCH";el.overlay.style.display="grid";el.boss.style.display="none"}}
+function hit(){if(player.inv>0)return;lives--;player.inv=1300;el.lives.textContent=Array(lives).fill("♥").join(" ")||"—";if(lives<=0){run=false;el.copy.innerHTML="The fleet overwhelmed you.<br>Score: <b>"+score+"</b>";el.start.textContent="RELAUNCH";el.overlay.style.display="grid";el.boss.style.display="none"}}
+function addBoss(){boss={x:W*.5,y:-85,hp:100,max:100,dir:1,shot:0};el.boss.style.display="block";el.fill.style.width="100%"}
+function addBoss(){boss={x:W*.5,y:-85,hp:100,max:100,dir:1,shot:0};el.boss.style.display="block";el.fill.style.width="100%"}
+function killEnemy(i){let e=enemies[i];enemies.splice(i,1);score+=20;el.score.textContent=score;if(Math.random()<.17)drops.push({x:e.x,y:e.y,r:12})}
+function killEnemy(i){let e=enemies[i];enemies.splice(i,1);score+=20;el.score.textContent=score;if(Math.random()<.17)drops.push({x:e.x,y:e.y,r:12})}
+function drawShip(x,y,col,flip=false,big=1){g.save();g.translate(x,y);g.scale(flip?-big:big,big);g.fillStyle=col;g.beginPath();g.moveTo(0,-23);g.lineTo(18,18);g.lineTo(0,11);g.lineTo(-18,18);g.closePath();g.fill();g.fillStyle="#bffbff";g.fillRect(-5,-7,10,13);g.fillStyle="#ffda55";g.fillRect(-22,12,8,5);g.fillRect(14,12,8,5);g.restore()}
+function drawShip(x,y,col,flip=false,big=1){g.save();g.translate(x,y);g.scale(flip?-big:big,big);g.fillStyle=col;g.beginPath();g.moveTo(0,-23);g.lineTo(18,18);g.lineTo(0,11);g.lineTo(-18,18);g.closePath();g.fill();g.fillStyle="#bffbff";g.fillRect(-5,-7,10,13);g.fillStyle="#ffda55";g.fillRect(-22,12,8,5);g.fillRect(14,12,8,5);g.restore()}
+function loop(t){requestAnimationFrame(loop);let dt=Math.min(35,last?t-last:16);last=t;g.fillStyle="#05061b";g.fillRect(0,0,W,H);for(let s of stars){s.y+=s.z*dt*.06;if(s.y>H){s.y=-3;s.x=Math.random()*W}g.fillStyle="#c7dcff";g.fillRect(s.x,s.y,s.z*.55,s.z*.55)}if(run){let sp=dt*.23;player.x=Math.max(19,Math.min(W-19,player.x+((keys.l?-1:0)+(keys.r?1:0))*sp));player.y=Math.max(75,Math.min(H-28,player.y+((keys.u?-1:0)+(keys.d?1:0))*sp));player.inv=Math.max(0,player.inv-dt);if((keys.fire||keys.auto)&&t>fireAt){fire();fireAt=t+170}if(!boss&&score>=bossAt)addBoss();if(!boss&&t>spawn){enemy();spawn=t+Math.max(360,790-score*2)}for(let i=enemies.length-1;i>=0;i--){let e=enemies[i];e.x+=e.vx*dt*.06;e.y+=e.vy*dt*.06;e.shot-=dt;if(e.shot<0&&e.y>30){shoot(e.x,e.y,0,3.1,false);e.shot=900+Math.random()*700}if(Math.hypot(e.x-player.x,e.y-player.y)<e.r+player.r){enemies.splice(i,1);hit()}else if(e.y>H+50||e.x<-60||e.x>W+60)enemies.splice(i,1)}if(boss){boss.y=Math.min(135,boss.y+dt*.035);boss.x+=boss.dir*dt*.08;if(boss.x<70||boss.x>W-70)boss.dir*=-1;boss.shot-=dt;if(boss.shot<0){for(let a=-.45;a<=.45;a+=.22)shoot(boss.x,boss.y,Math.sin(a)*2.1,3.3,false);boss.shot=750}if(Math.hypot(boss.x-player.x,boss.y-player.y)<65)hit()}for(let i=shots.length-1;i>=0;i--){let q=shots[i];q.x+=q.vx*dt*.06;q.y+=q.vy*dt*.06;let remove=q.y<-20||q.y>H+20||q.x<-20||q.x>W+20;if(q.friendly){for(let j=enemies.length-1;j>=0;j--){let e=enemies[j];if(Math.hypot(q.x-e.x,q.y-e.y)<20){e.hp--;remove=true;if(e.hp<=0)killEnemy(j);break}}if(boss&&Math.hypot(q.x-boss.x,q.y-boss.y)<65){boss.hp--;remove=true;el.fill.style.width=boss.hp+"%";if(boss.hp<=0){score+=300;el.score.textContent=score;boss=null;bossAt=score+300;el.boss.style.display="none"}}}else if(Math.hypot(q.x-player.x,q.y-player.y)<player.r+q.r){remove=true;hit()}if(remove)shots.splice(i,1)}for(let i=drops.length-1;i>=0;i--){let d=drops[i];d.y+=dt*.04;if(Math.hypot(d.x-player.x,d.y-player.y)<30){player.power=Math.min(3,player.power+1);el.power.style.display="block";el.power.textContent="POWER: ×"+player.power;drops.splice(i,1)}else if(d.y>H)drops.splice(i,1)}}for(let e of enemies)drawShip(e.x,e.y,"#ef5a9b",true,.8);if(boss){drawShip(boss.x,boss.y,"#a94fca",true,2.5);g.fillStyle="#ffd96b";g.fillRect(boss.x-15,boss.y+9,30,8)}for(let d of drops){g.fillStyle="#ffe868";g.beginPath();g.arc(d.x,d.y,11,0,7);g.fill()}for(let q of shots){g.fillStyle=q.friendly?"#90fbff":"#ff6494";g.fillRect(q.x-2,q.y-8,4,16)}if(player&&(player.inv<=0||Math.floor(t/90)%2))drawShip(player.x,player.y,"#5ee5e9");}
+function loop(t){requestAnimationFrame(loop);let dt=Math.min(35,last?t-last:16);last=t;g.fillStyle="#05061b";g.fillRect(0,0,W,H);for(let s of stars){s.y+=s.z*dt*.06;if(s.y>H){s.y=-3;s.x=Math.random()*W}g.fillStyle="#c7dcff";g.fillRect(s.x,s.y,s.z*.55,s.z*.55)}if(run){let sp=dt*.23;player.x=Math.max(19,Math.min(W-19,player.x+((keys.l?-1:0)+(keys.r?1:0))*sp));player.y=Math.max(75,Math.min(H-28,player.y+((keys.u?-1:0)+(keys.d?1:0))*sp));player.inv=Math.max(0,player.inv-dt);if((keys.fire||keys.auto)&&t>fireAt){fire();fireAt=t+170}if(!boss&&score>=bossAt)addBoss();if(!boss&&t>spawn){enemy();spawn=t+Math.max(360,790-score*2)}for(let i=enemies.length-1;i>=0;i--){let e=enemies[i];e.x+=e.vx*dt*.06;e.y+=e.vy*dt*.06;e.shot-=dt;if(e.shot<0&&e.y>30){shoot(e.x,e.y,0,3.1,false);e.shot=900+Math.random()*700}if(Math.hypot(e.x-player.x,e.y-player.y)<e.r+player.r){enemies.splice(i,1);hit()}else if(e.y>H+50||e.x<-60||e.x>W+60)enemies.splice(i,1)}if(boss){boss.y=Math.min(135,boss.y+dt*.035);boss.x+=boss.dir*dt*.08;if(boss.x<70||boss.x>W-70)boss.dir*=-1;boss.shot-=dt;if(boss.shot<0){for(let a=-.45;a<=.45;a+=.22)shoot(boss.x,boss.y,Math.sin(a)*2.1,3.3,false);boss.shot=750}if(Math.hypot(boss.x-player.x,boss.y-player.y)<65)hit()}for(let i=shots.length-1;i>=0;i--){let q=shots[i];q.x+=q.vx*dt*.06;q.y+=q.vy*dt*.06;let remove=q.y<-20||q.y>H+20||q.x<-20||q.x>W+20;if(q.friendly){for(let j=enemies.length-1;j>=0;j--){let e=enemies[j];if(Math.hypot(q.x-e.x,q.y-e.y)<20){e.hp--;remove=true;if(e.hp<=0)killEnemy(j);break}}if(boss&&Math.hypot(q.x-boss.x,q.y-boss.y)<65){boss.hp--;remove=true;el.fill.style.width=boss.hp+"%";if(boss.hp<=0){score+=300;el.score.textContent=score;boss=null;bossAt=score+300;el.boss.style.display="none"}}}else if(Math.hypot(q.x-player.x,q.y-player.y)<player.r+q.r){remove=true;hit()}if(remove)shots.splice(i,1)}for(let i=drops.length-1;i>=0;i--){let d=drops[i];d.y+=dt*.04;if(Math.hypot(d.x-player.x,d.y-player.y)<30){player.power=Math.min(3,player.power+1);el.power.style.display="block";el.power.textContent="POWER: ×"+player.power;drops.splice(i,1)}else if(d.y>H)drops.splice(i,1)}}for(let e of enemies)drawShip(e.x,e.y,"#ef5a9b",true,.8);if(boss){drawShip(boss.x,boss.y,"#a94fca",true,2.5);g.fillStyle="#ffd96b";g.fillRect(boss.x-15,boss.y+9,30,8)}for(let d of drops){g.fillStyle="#ffe868";g.beginPath();g.arc(d.x,d.y,11,0,7);g.fill()}for(let q of shots){g.fillStyle=q.friendly?"#90fbff":"#ff6494";g.fillRect(q.x-2,q.y-8,4,16)}if(player&&(player.inv<=0||Math.floor(t/90)%2))drawShip(player.x,player.y,"#5ee5e9");}
+requestAnimationFrame(loop);
+requestAnimationFrame(loop);
← Histórico de versões