@joaobarrosfranca · 8/12/2026, 3:38:55 PM
Versão inicial — todas as linhas são novas.
+<!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);+</script></body></html>