@joaobarrosfranca · 8/12/2026, 4:09:31 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"><style>+*{box-sizing:border-box}html,body{margin:0;height:100%;overflow:hidden;background:#80986c;font-family:system-ui,sans-serif;touch-action:none}canvas{position:fixed;inset:0;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;text-shadow:0 2px 6px #1f3022;pointer-events:none}.lab{font-size:10px;font-weight:1000;letter-spacing:1.8px}.num{font-size:28px;line-height:1;font-weight:1000}.r{text-align:right}#health{position:fixed;z-index:3;top:74px;left:17px;width:120px;height:10px;border:2px solid white;border-radius:6px;overflow:hidden;background:#3a2523}.hp{height:100%;background:linear-gradient(90deg,#ffcc55,#61dd7c);width:100%;transition:width .15s}.controls{position:fixed;z-index:4;bottom:17px;left:0;right:0;padding:0 14px;display:flex;justify-content:space-between;align-items:end}.drive{position:relative;width:145px;height:115px}.drive button,.fire{position:absolute;border:2px solid #fff9;color:#fff;font-weight:1000;box-shadow:0 4px 11px #1422159c;cursor:pointer}.drive button{width:47px;height:47px;border-radius:14px;background:#496b55d9;font-size:20px}.up{top:0;left:49px}.down{bottom:0;left:49px}.left{top:34px;left:0}.right{top:34px;right:0}.fire{position:relative;width:73px;height:73px;border-radius:50%;background:#db6d36d9;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:26px;background:radial-gradient(circle at 50% 12%,#dec06977,transparent 33%),linear-gradient(155deg,#253a28e8,#426638e1 54%,#b55c3dc8);color:#fff}#card{max-width:325px}.tag{font-size:11px;font-weight:1000;letter-spacing:4px;color:#ffe58e}.title{font-size:55px;line-height:.8;letter-spacing:-4px;font-weight:1000;margin:18px;text-shadow:4px 4px #243421}.title span{color:#ffbf55}.copy{font-size:16px;line-height:1.5}.start{border:3px solid #ffedab;border-radius:5px;background:#d96d36;color:#fff;padding:15px 28px;font-weight:1000;font-size:14px;letter-spacing:1px;box-shadow:0 5px #713628;cursor:pointer}.tip{font-size:12px;color:#fff3c8;margin-top:17px}+</style></head><body><div class="hud"><div><div class="lab">SCORE</div><div id="score" class="num">0</div></div><div class="r"><div class="lab">WAVE</div><div id="wave" class="num">1</div></div></div><div id="health"><div id="hp" class="hp"></div></div><div class="controls"><div class="drive"><button id="forward" class="up">▲</button><button id="back" class="down">▼</button><button id="turnLeft" class="left">◀</button><button id="turnRight" class="right">▶</button></div><button id="fire" class="fire">FIRE</button></div><div id="overlay"><div id="card"><div class="tag">ORIGINAL 3D TANK ARENA</div><div class="title">IRON<br><span>FRONT</span></div><p id="copy" class="copy">Drive through the desert arena, turn your cannon toward the threat, and clear every enemy wave.</p><button id="start" class="start">ROLL OUT</button><div class="tip">W/S drive · A/D turn · Space fires</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(),cam=new THREE.PerspectiveCamera(57,innerWidth/innerHeight,.1,120),renderer=new THREE.WebGLRenderer({antialias:true});renderer.setSize(innerWidth,innerHeight);renderer.setPixelRatio(Math.min(devicePixelRatio,2));renderer.outputColorSpace=THREE.SRGBColorSpace;document.body.appendChild(renderer.domElement);scene.background=new THREE.Color(0x91b179);scene.fog=new THREE.Fog(0x91b179,22,65);scene.add(new THREE.HemisphereLight(0xffffdf,0x33442d,2.8));const sun=new THREE.DirectionalLight(0xffe5a5,2.5);sun.position.set(-12,18,8);scene.add(sun);cam.position.set(0,7,10);+const ground=new THREE.Mesh(new THREE.PlaneGeometry(90,90),new THREE.MeshStandardMaterial({color:0x849f61,roughness:1}));ground.rotation.x=-Math.PI/2;scene.add(ground);const grid=new THREE.GridHelper(90,45,0x76945e,0x789d5d);grid.material.opacity=.25;grid.material.transparent=true;scene.add(grid);+for(let i=0;i<42;i++){let rock=new THREE.Mesh(new THREE.DodecahedronGeometry(.35+Math.random()*.9,0),new THREE.MeshStandardMaterial({color:Math.random()<.5?0x896f50:0x6d7851,roughness:1,flatShading:true}));rock.position.set((Math.random()-.5)*38,rock.geometry.parameters.radius*.4,(Math.random()-.5)*38);rock.scale.y=.55;scene.add(rock)}+function tank(color){let g=new THREE.Group(),bodyMat=new THREE.MeshStandardMaterial({color,roughness:.55,metalness:.1}),dark=new THREE.MeshStandardMaterial({color:0x202b24,roughness:.7});let body=new THREE.Mesh(new THREE.BoxGeometry(1.35,.38,1.75),bodyMat);body.position.y=.38;g.add(body);let turret=new THREE.Group(),cap=new THREE.Mesh(new THREE.CylinderGeometry(.46,.55,.27,10),bodyMat),barrel=new THREE.Mesh(new THREE.CylinderGeometry(.1,.13,1.15,10),dark);cap.position.y=.66;barrel.rotation.x=Math.PI/2;barrel.position.set(0,.66,-.73);turret.add(cap,barrel);g.add(turret);[-1,1].forEach(s=>{let tread=new THREE.Mesh(new THREE.BoxGeometry(.25,.27,1.78),dark);tread.position.set(s*.72,.23,0);g.add(tread)});g.userData.turret=turret;return g}+const player=tank(0x3f9db5);player.position.set(0,0,4);scene.add(player);const enemies=[],shells=[],input={f:false,b:false,l:false,r:false,fire:false};let running=false,health=100,score=0,wave=1,last=0,nextFire=0,nextEnemy=0;+const ui={score:document.getElementById("score"),wave:document.getElementById("wave"),hp:document.getElementById("hp"),overlay:document.getElementById("overlay"),copy:document.getElementById("copy"),start:document.getElementById("start")};+function spawnEnemy(){const e=tank(0xc65c49);let a=Math.random()*Math.PI*2,d=14+Math.random()*9;e.position.set(Math.sin(a)*d,0,Math.cos(a)*d);scene.add(e);enemies.push({g:e,hp:3,next:0,phase:Math.random()*6})}+function fire(from,enemy){const b=new THREE.Mesh(new THREE.SphereGeometry(.13,9,7),new THREE.MeshBasicMaterial({color:enemy?0xff7b5b:0xffec83}));const angle=from.rotation.y;b.position.copy(from.position);b.position.y=.75;b.position.x-=Math.sin(angle)*1.35;b.position.z-=Math.cos(angle)*1.35;scene.add(b);shells.push({m:b,vx:-Math.sin(angle)*(enemy?.18:.29),vz:-Math.cos(angle)*(enemy?.18:.29),enemy})}+function setupWave(){for(const e of enemies)scene.remove(e.g);enemies.length=0;for(let i=0;i<2+wave;i++)spawnEnemy();ui.wave.textContent=wave}+function lose(){running=false;ui.copy.innerHTML="The arena overwhelmed you.<br>Score: <b>"+score+"</b>";ui.start.textContent="REDEPLOY";ui.overlay.style.display="grid"}function reset(){health=100;score=0;wave=1;player.position.set(0,0,4);player.rotation.y=0;ui.score.textContent=0;ui.hp.style.width="100%";setupWave();running=true;ui.overlay.style.display="none";last=0}+function damage(){health=Math.max(0,health-12);ui.hp.style.width=health+"%";if(health===0)lose()}+function addInputs(id,key){let b=document.getElementById(id);b.addEventListener("pointerdown",e=>{e.preventDefault();input[key]=true});["pointerup","pointerleave","pointercancel"].forEach(t=>b.addEventListener(t,()=>input[key]=false))}+addInputs("forward","f");addInputs("back","b");addInputs("turnLeft","l");addInputs("turnRight","r");addInputs("fire","fire");ui.start.addEventListener("click",reset);+addEventListener("keydown",e=>{let k=e.key.toLowerCase();if(k==="w"||k==="arrowup")input.f=true;if(k==="s"||k==="arrowdown")input.b=true;if(k==="a"||k==="arrowleft")input.l=true;if(k==="d"||k==="arrowright")input.r=true;if(k===" ")input.fire=true;if(k==="enter"&&!running)reset()});addEventListener("keyup",e=>{let k=e.key.toLowerCase();if(k==="w"||k==="arrowup")input.f=false;if(k==="s"||k==="arrowdown")input.b=false;if(k==="a"||k==="arrowleft")input.l=false;if(k==="d"||k==="arrowright")input.r=false;if(k===" ")input.fire=false});+function loop(t){requestAnimationFrame(loop);let dt=Math.min(35,last?t-last:16);last=t;if(running){let rot=(input.l?-1:0)+(input.r?1:0);player.rotation.y+=rot*dt*.003;let speed=(input.f?1:0)-(input.b?1:0);player.position.x-=Math.sin(player.rotation.y)*speed*dt*.006;player.position.z-=Math.cos(player.rotation.y)*speed*dt*.006;player.position.x=Math.max(-40,Math.min(40,player.position.x));player.position.z=Math.max(-40,Math.min(40,player.position.z));if(input.fire&&t>nextFire){fire(player,false);nextFire=t+420}+for(let i=enemies.length-1;i>=0;i--){let e=enemies[i],dx=player.position.x-e.g.position.x,dz=player.position.z-e.g.position.z,dist=Math.hypot(dx,dz),goal=Math.atan2(-dx,-dz);e.g.rotation.y+=Math.atan2(Math.sin(goal-e.g.rotation.y),Math.cos(goal-e.g.rotation.y))*.07;if(dist>6){e.g.position.x-=Math.sin(e.g.rotation.y)*dt*.0018;e.g.position.z-=Math.cos(e.g.rotation.y)*dt*.0018}if(t>e.next&&dist<20){fire(e.g,true);e.next=t+950+Math.random()*650}}+for(let i=shells.length-1;i>=0;i--){let q=shells[i];q.m.position.x+=q.vx*dt;q.m.position.z+=q.vz*dt;let gone=Math.abs(q.m.position.x)>45||Math.abs(q.m.position.z)>45;if(q.enemy){if(q.m.position.distanceTo(player.position)<.85){damage();gone=true}}else{for(let j=enemies.length-1;j>=0;j--){let e=enemies[j];if(q.m.position.distanceTo(e.g.position)<.9){e.hp--;gone=true;if(e.hp<=0){scene.remove(e.g);enemies.splice(j,1);score+=50;ui.score.textContent=score}break}}}if(gone){scene.remove(q.m);shells.splice(i,1)}}if(enemies.length===0){wave++;setupWave()}let behind=new THREE.Vector3(player.position.x+Math.sin(player.rotation.y)*8,6.7,player.position.z+Math.cos(player.rotation.y)*8);cam.position.lerp(behind,.06);cam.lookAt(player.position.x-Math.sin(player.rotation.y)*5,.4,player.position.z-Math.cos(player.rotation.y)*5)}renderer.render(scene,cam)}+addEventListener("resize",()=>{cam.aspect=innerWidth/innerHeight;cam.updateProjectionMatrix();renderer.setSize(innerWidth,innerHeight)});loop(0);+</script></body></html>