@joaobarrosfranca · 8/12/2026, 3:58:20 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>Rooftop Rumble 3D</title>-<style>-*{box-sizing:border-box}html,body{margin:0;height:100%;overflow:hidden;background:#241a4e;font-family:system-ui,-apple-system,sans-serif;touch-action:none}canvas{display:block}.barbox{position:fixed;z-index:5;top:19px;width:43%;color:#fff;text-shadow:0 2px 5px #000}.barbox.left{left:16px}.barbox.right{right:16px;text-align:right}.name{font-size:11px;font-weight:950;letter-spacing:1.8px;margin-bottom:5px}.bar{height:13px;background:#1b1236;border:2px solid #fff9;transform:skewX(-12deg);overflow:hidden}.right .bar{transform:skewX(12deg)}.fill{height:100%;width:100%;background:linear-gradient(90deg,#53ffe2,#c7ff72);transition:width .2s}.right .fill{margin-left:auto;background:linear-gradient(90deg,#ffd76a,#ff5b87)}#round{position:fixed;z-index:5;top:20px;left:50%;transform:translateX(-50%);color:#fff5be;text-shadow:0 2px 7px #000;font-weight:1000;font-size:15px;letter-spacing:1.2px}.controls{position:fixed;z-index:6;left:0;right:0;bottom:max(17px,env(safe-area-inset-bottom));padding:0 14px;display:flex;justify-content:space-between;align-items:end}.move,.attacks{display:flex;gap:9px}.controls button{border:2px solid #fff8;color:#fff;font-weight:950;cursor:pointer;box-shadow:0 4px 10px #1c113d88}.move button{width:53px;height:53px;border-radius:16px;background:#5247a5bb;font-size:24px}.attacks button{width:64px;height:64px;border-radius:50%;font-size:11px;letter-spacing:.4px}.punch{background:#ec5c95}.kick{background:#f5a93d}.controls button:active{transform:scale(.94);filter:brightness(1.2)}#cover{position:fixed;z-index:10;inset:0;display:grid;place-items:center;text-align:center;padding:26px;color:white;background:radial-gradient(circle at 50% 15%,#f88a7666,transparent 32%),linear-gradient(150deg,#261549e8,#601f64e5 57%,#fa744aab)}#card{max-width:320px}.tag{font-size:11px;letter-spacing:4px;font-weight:950;color:#ffc45d}.title{font-size:51px;font-weight:1000;line-height:.84;letter-spacing:-3px;margin:17px 0 20px;text-transform:uppercase;text-shadow:4px 4px 0 #29164a}.title span{color:#65f3e1}.copy{font-size:16px;line-height:1.5;color:#f7eeff;margin-bottom:26px}#start{border:3px solid #fff1c6;border-radius:6px;background:#faad3e;color:#391b50;padding:15px 28px;font-size:14px;font-weight:1000;letter-spacing:1px;cursor:pointer;box-shadow:0 5px 0 #99394d}#start:active{transform:translateY(3px);box-shadow:0 2px 0 #99394d}.hint{font-size:12px;color:#fff2d0;margin-top:18px}-</style></head><body>-<div class="barbox left"><div class="name">KITE</div><div class="bar"><div id="playerHp" class="fill"></div></div></div><div id="round">ROUND 1</div><div class="barbox right"><div class="name">VOLT</div><div class="bar"><div id="enemyHp" class="fill"></div></div></div>-<div class="controls"><div class="move"><button id="left" aria-label="Move left">←</button><button id="right" aria-label="Move right">→</button></div><div class="attacks"><button id="punch" class="punch">PUNCH</button><button id="kick" class="kick">KICK</button></div></div>-<div id="cover"><div id="card"><div class="tag">ORIGINAL 3D FIGHTING</div><div class="title">ROOFTOP<br><span>RUMBLE</span></div><div id="copy" class="copy">Kite versus Volt. Close the distance, strike first, and own the skyline.</div><button id="start" type="button">FIGHT!</button><div class="hint">Move with arrows · Punch or kick with the buttons</div></div></div>+<!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:#17112c;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;display:flex;justify-content:space-between;padding:16px;color:#fff;pointer-events:none;text-shadow:0 2px 5px #000}.fighter{width:40%}.fighter.r{text-align:right}.name{font-size:10px;font-weight:900;letter-spacing:2px}.bar{margin-top:5px;height:15px;border:2px solid #fff;background:#211535;transform:skewX(-12deg)}.r .bar{transform:skewX(12deg)}.fill{height:100%;width:100%;background:linear-gradient(90deg,#71f3ce,#d5ff6a);transition:width .15s}.r .fill{margin-left:auto;background:linear-gradient(90deg,#ffc35c,#f55289)}#round{position:fixed;z-index:3;top:19px;left:50%;transform:translateX(-50%);font-weight:1000;color:#ffdf72;text-shadow:0 2px 6px #000;font-size:13px;letter-spacing:1px}.controls{position:fixed;z-index:4;left:0;right:0;bottom:15px;padding:0 13px;display:flex;justify-content:space-between;align-items:end}.move,.acts{display:flex;gap:7px}.controls button{border:2px solid #fff9;color:white;font-weight:950;box-shadow:0 4px 10px #0008;cursor:pointer}.move button{width:49px;height:49px;border-radius:14px;background:#463e8d;font-size:21px}.acts{flex-wrap:wrap;justify-content:flex-end;width:160px}.acts button{width:48px;height:48px;border-radius:50%;font-size:9px}.p{background:#e25288}.k{background:#ec9a3b}.x{background:#7659dc}.b{background:#4776b9}.controls button:active{transform:scale(.94)}#overlay{position:fixed;z-index:8;inset:0;display:grid;place-items:center;text-align:center;padding:25px;background:radial-gradient(circle at 50% 15%,#f17d8466,transparent 35%),linear-gradient(145deg,#1a103be8,#5b1b61e8 57%,#e36452c8);color:#fff}#card{max-width:320px}.tag{font-size:11px;font-weight:950;letter-spacing:4px;color:#ffd461}.title{font-size:51px;line-height:.82;font-weight:1000;letter-spacing:-3px;text-shadow:4px 4px #27133e;margin:15px}.title span{color:#67f2dd}.copy{font-size:15px;line-height:1.5}.start{padding:14px 28px;border:3px solid #fff1bb;background:#f3a23c;color:#371849;font-weight:1000;border-radius:5px;box-shadow:0 4px #9b394a;cursor:pointer}.tip{font-size:11px;color:#fff1cc;margin-top:16px}+</style></head><body><div class="hud"><div class="fighter"><div class="name">KITE</div><div class="bar"><div id="pHp" class="fill"></div></div></div><div id="round">FIGHT!</div><div class="fighter r"><div class="name">VOLT</div><div class="bar"><div id="eHp" class="fill"></div></div></div></div><div class="controls"><div class="move"><button id="left">←</button><button id="right">→</button></div><div class="acts"><button id="punch" class="p">PUNCH</button><button id="kick" class="k">KICK</button><button id="power" class="x">POWER</button><button id="guard" class="b">GUARD</button></div></div><div id="overlay"><div id="card"><div class="tag">3D ARCADE FIGHTING</div><div class="title">ROOFTOP<br><span>RUMBLE</span></div><p id="copy" class="copy">Read Volt's stance, close the gap, then punch, kick or launch a power burst. Guard blocks most damage.</p><button id="start" class="start">FIGHT!</button><div class="tip">A/D move · J punch · K kick · L power · S guard · W jump</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(0x2a1a59);scene.fog=new THREE.Fog(0x2a1a59,13,35);-const camera=new THREE.PerspectiveCamera(58,innerWidth/innerHeight,.1,100);camera.position.set(0,4.2,10.3);camera.lookAt(0,1.5,0);-const renderer=new THREE.WebGLRenderer({antialias:true});renderer.setPixelRatio(Math.min(devicePixelRatio,2));renderer.setSize(innerWidth,innerHeight);renderer.outputColorSpace=THREE.SRGBColorSpace;renderer.shadowMap.enabled=true;document.body.appendChild(renderer.domElement);-scene.add(new THREE.HemisphereLight(0xc4b9ff,0x1b153b,2.3));const moon=new THREE.DirectionalLight(0xffc36a,2.2);moon.position.set(-4,10,5);moon.castShadow=true;scene.add(moon);const pink=new THREE.PointLight(0xff4b99,18,16);pink.position.set(4,3,1);scene.add(pink);-const roof=new THREE.Mesh(new THREE.BoxGeometry(13,.6,7),new THREE.MeshStandardMaterial({color:0x313058,roughness:.82}));roof.position.y=-.3;roof.receiveShadow=true;scene.add(roof);-const edge=new THREE.Mesh(new THREE.BoxGeometry(13,.25,.18),new THREE.MeshStandardMaterial({color:0xf4a03e,emissive:0xa84919,emissiveIntensity:1.4}));edge.position.set(0,.05,-3.4);scene.add(edge);-for(let i=0;i<22;i++){const h=2+Math.random()*8,w=.8+Math.random()*1.4;const b=new THREE.Mesh(new THREE.BoxGeometry(w,h,w),new THREE.MeshStandardMaterial({color:0x201949,emissive:0x120d36,roughness:.65}));b.position.set((Math.random()-.5)*24,-.1+h/2,-8-Math.random()*15);scene.add(b);for(let y=.5;y<h;y+=.8){const win=new THREE.Mesh(new THREE.BoxGeometry(w*.58,.08,.03),new THREE.MeshBasicMaterial({color:Math.random()<.45?0xffa94d:0x5eece0}));win.position.set(b.position.x,y,b.position.z+w/2+.02);scene.add(win)}}-function makeFighter(bodyColor,gloveColor){const g=new THREE.Group(),mat=new THREE.MeshStandardMaterial({color:bodyColor,roughness:.48,metalness:.1}),skin=new THREE.MeshStandardMaterial({color:0xf0a27f,roughness:.65}),glove=new THREE.MeshStandardMaterial({color:gloveColor,roughness:.34,metalness:.15});const torso=new THREE.Mesh(new THREE.BoxGeometry(.78,1.05,.43),mat);torso.position.y=1.55;torso.castShadow=true;g.add(torso);const head=new THREE.Mesh(new THREE.SphereGeometry(.38,15,12),skin);head.position.y=2.36;head.castShadow=true;g.add(head);const hair=new THREE.Mesh(new THREE.SphereGeometry(.41,10,7),new THREE.MeshStandardMaterial({color:0x1b1530,roughness:.8}));hair.scale.y=.42;hair.position.y=2.63;g.add(hair);const arms=[];[-1,1].forEach(side=>{const arm=new THREE.Group(),upper=new THREE.Mesh(new THREE.BoxGeometry(.24,.74,.24),mat),hand=new THREE.Mesh(new THREE.SphereGeometry(.22,10,8),glove);upper.position.y=-.29;hand.position.y=-.72;arm.add(upper,hand);arm.position.set(side*.54,1.91,0);arm.rotation.z=side*-.22;g.add(arm);arms.push(arm)});[-1,1].forEach(side=>{const leg=new THREE.Mesh(new THREE.BoxGeometry(.28,.94,.3),mat);leg.position.set(side*.22,.57,0);leg.castShadow=true;g.add(leg)});return {g,arms}}+const scene=new THREE.Scene(),cam=new THREE.PerspectiveCamera(55,innerWidth/innerHeight,.1,80),r=new THREE.WebGLRenderer({antialias:true});r.setSize(innerWidth,innerHeight);r.setPixelRatio(Math.min(devicePixelRatio,2));r.outputColorSpace=THREE.SRGBColorSpace;document.body.appendChild(r.domElement);cam.position.set(0,3.2,10);cam.lookAt(0,1.2,0);scene.background=new THREE.Color(0x21144a);scene.fog=new THREE.Fog(0x21144a,10,35);scene.add(new THREE.HemisphereLight(0xbccaff,0x170d2c,2.4));let sun=new THREE.DirectionalLight(0xffbf7b,2.2);sun.position.set(-5,9,6);scene.add(sun);let floor=new THREE.Mesh(new THREE.BoxGeometry(13,.4,5),new THREE.MeshStandardMaterial({color:0x34345b,roughness:.85}));floor.position.y=-.2;scene.add(floor);for(let i=0;i<16;i++){let h=2+Math.random()*7,b=new THREE.Mesh(new THREE.BoxGeometry(1.3,h,1.2),new THREE.MeshStandardMaterial({color:i%2?0x291b57:0x442766}));b.position.set((Math.random()-.5)*22,h/2,-7-Math.random()*12);scene.add(b)}+function makeFighter(color,glove){let g=new THREE.Group(),mat=new THREE.MeshStandardMaterial({color,roughness:.4}),skin=new THREE.MeshStandardMaterial({color:0xf2a17c}),gm=new THREE.MeshStandardMaterial({color:glove,roughness:.28}),dark=new THREE.MeshStandardMaterial({color:0x20152f});let torso=new THREE.Mesh(new THREE.BoxGeometry(.75,1,.42),mat);torso.position.y=1.35;g.add(torso);let head=new THREE.Mesh(new THREE.SphereGeometry(.36,14,10),skin);head.position.y=2.16;g.add(head);let hair=new THREE.Mesh(new THREE.SphereGeometry(.39,12,8),dark);hair.scale.y=.38;hair.position.y=2.43;g.add(hair);let arms=[];[-1,1].forEach(s=>{let a=new THREE.Group(),u=new THREE.Mesh(new THREE.BoxGeometry(.22,.68,.22),mat),h=new THREE.Mesh(new THREE.SphereGeometry(.2,10,8),gm);u.position.y=-.28;h.position.y=-.66;a.add(u,h);a.position.set(s*.52,1.72,0);a.rotation.z=s*-.18;g.add(a);arms.push(a)});[-1,1].forEach(s=>{let leg=new THREE.Mesh(new THREE.BoxGeometry(.24,.68,.27),mat);leg.position.set(s*.2,.38,0);g.add(leg)});scene.add(g);return {g,arms,hp:100,act:"idle",timer:0,guard:false,vy:0,hit:0}}+const P=makeFighter(0x49d9c5,0xffc64f),E=makeFighter(0xef6f95,0xa971ef);P.g.position.x=-2.3;E.g.position.x=2.3;E.g.rotation.y=Math.PI;+const ui={p:document.getElementById("pHp"),e:document.getElementById("eHp"),round:document.getElementById("round"),overlay:document.getElementById("overlay"),copy:document.getElementById("copy"),start:document.getElementById("start")};let running=false,dir=0,guard=false,last=0,enemyThink=0;</script></body></html>