@joaobarrosfranca · 8/12/2026, 3:19:22 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>Skyline Shift 3D</title>+<style>+*{box-sizing:border-box}html,body{margin:0;width:100%;height:100%;overflow:hidden;background:#050718;font-family:system-ui,-apple-system,sans-serif;touch-action:none}canvas{display:block;width:100%;height:100%}#hud{position:fixed;z-index:4;inset:0 0 auto;padding:calc(18px + env(safe-area-inset-top)) 19px 10px;display:flex;justify-content:space-between;pointer-events:none;color:#fff;text-shadow:0 2px 9px #000}.label{font-size:10px;font-weight:900;letter-spacing:2px;color:#b6c6ff}.value{font-size:31px;font-weight:950;line-height:1}.right{text-align:right}#screen{position:fixed;z-index:9;inset:0;display:grid;place-items:center;padding:28px;text-align:center;background:linear-gradient(#07092492,#070924ec);color:#fff}#card{max-width:310px}.eyebrow{font-weight:950;letter-spacing:4px;font-size:13px;color:#72efff;text-shadow:0 0 18px #20dfff}.title{font-size:50px;line-height:.88;letter-spacing:-2.5px;font-weight:1000;margin:15px 0 18px;background:linear-gradient(135deg,#fff,#80a2ff 55%,#f77cdc);-webkit-background-clip:text;color:transparent}.copy{font-size:16px;line-height:1.5;color:#d4dcff;margin:0 0 25px}button{border:0;border-radius:999px;padding:16px 30px;color:#fff;background:linear-gradient(90deg,#405dff,#e54fc6);font-weight:950;font-size:15px;letter-spacing:.6px;box-shadow:0 8px 30px #5e58ff88;cursor:pointer}button:active{transform:scale(.96)}.hint{margin-top:17px;font-size:12px;color:#aebae8}+</style>+</head>+<body>+<div id="hud"><div><div class="label">DISTANCE</div><div id="score" class="value">0</div></div><div class="right"><div class="label">BEST</div><div id="best" class="value">0</div></div></div>+<div id="screen"><div id="card"><div class="eyebrow">SKYLINE SHIFT</div><div class="title">RUSH<br>THE VOID</div><p id="copy" class="copy">Shift lanes to dodge the towers and collect light cores.</p><button id="play" type="button">START RUN</button><div class="hint">Swipe left / right · or use A / D</div></div></div>+<script type="module">+import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js";++const scoreEl=document.querySelector("#score"),bestEl=document.querySelector("#best"),screen=document.querySelector("#screen"),play=document.querySelector("#play"),copy=document.querySelector("#copy");+const scene=new THREE.Scene();+scene.background=new THREE.Color(0x06081d);+scene.fog=new THREE.Fog(0x06081d,15,54);+const camera=new THREE.PerspectiveCamera(60,innerWidth/innerHeight,.1,100);+camera.position.set(0,5.3,10.5); camera.lookAt(0,0,-10);+const renderer=new THREE.WebGLRenderer({antialias:true,alpha:false});+renderer.setPixelRatio(Math.min(devicePixelRatio,2));renderer.setSize(innerWidth,innerHeight);renderer.outputColorSpace=THREE.SRGBColorSpace;document.body.appendChild(renderer.domElement);+const hemi=new THREE.HemisphereLight(0x9aacff,0x0c1130,2.2);scene.add(hemi);+const key=new THREE.DirectionalLight(0x96efff,3.2);key.position.set(4,8,5);scene.add(key);+const magenta=new THREE.PointLight(0xff4fc6,22,16);magenta.position.set(-5,2,1);scene.add(magenta);+const cyan=new THREE.PointLight(0x2beaff,16,22);cyan.position.set(4,3,-10);scene.add(cyan);++const lanes=[-2.15,0,2.15];+const road=new THREE.Mesh(new THREE.PlaneGeometry(7.5,100),new THREE.MeshStandardMaterial({color:0x101945,metalness:.55,roughness:.42}));+road.rotation.x=-Math.PI/2;road.position.z=-35;scene.add(road);+const grid=new THREE.GridHelper(100,40,0x4d63ce,0x20295c);grid.position.y=.015;grid.position.z=-35;grid.material.opacity=.42;grid.material.transparent=true;scene.add(grid);+const railMat=new THREE.MeshStandardMaterial({color:0x6a54ff,emissive:0x30208a,emissiveIntensity:1.8,metalness:.65,roughness:.25});+[-3.75,3.75].forEach(x=>{const rail=new THREE.Mesh(new THREE.BoxGeometry(.08,.09,100),railMat);rail.position.set(x,.09,-35);scene.add(rail)});+const skyline=new THREE.Group();scene.add(skyline);+for(let i=0;i<42;i++){const h=2+Math.random()*9,w=.7+Math.random()*1.8,d=.7+Math.random()*1.8;const m=new THREE.Mesh(new THREE.BoxGeometry(w,h,d),new THREE.MeshStandardMaterial({color:new THREE.Color().setHSL(.62+Math.random()*.12,.7,.17+Math.random()*.14),emissive:0x111c50,emissiveIntensity:.75,roughness:.55}));m.position.set((Math.random()<.5?-1:1)*(5+Math.random()*4),h/2,-Math.random()*58);skyline.add(m)}+const player=new THREE.Group();scene.add(player);+const body=new THREE.Mesh(new THREE.SphereGeometry(.63,24,18),new THREE.MeshStandardMaterial({color:0x82f5ff,emissive:0x216eff,emissiveIntensity:1.6,metalness:.7,roughness:.17}));player.add(body);+const ring=new THREE.Mesh(new THREE.TorusGeometry(.82,.06,8,28),new THREE.MeshBasicMaterial({color:0xff63d5}));ring.rotation.x=Math.PI/2;ring.position.y=-.59;player.add(ring);+const playerLight=new THREE.PointLight(0x5ff5ff,8,7);player.add(playerLight);player.position.set(0,.78,2.2);++let lane=1,running=false,score=0,best=0,objects=[],last=0,nextSpawn=0,swipeX=0;+bestEl.textContent=best;+function move(dir){if(!running)return;lane=Math.max(0,Math.min(2,lane+dir))}+function makeTower(){+ const g=new THREE.Group(),height=1.5+Math.random()*2.9;+ const cube=new THREE.Mesh(new THREE.BoxGeometry(1.25,height,1.25),new THREE.MeshStandardMaterial({color:0xff4e8d,emissive:0x76102e,emissiveIntensity:1.1,metalness:.5,roughness:.3}));+ cube.position.y=height/2;g.add(cube);+ const top=new THREE.Mesh(new THREE.BoxGeometry(1.42,.12,1.42),new THREE.MeshBasicMaterial({color:0xffb1d3}));top.position.y=height+.08;g.add(top);+ g.position.set(lanes[Math.floor(Math.random()*3)],0,-42);scene.add(g);objects.push({g,type:"tower",passed:false});+}+function makeCore(){+ const g=new THREE.Group(),orb=new THREE.Mesh(new THREE.IcosahedronGeometry(.38,2),new THREE.MeshStandardMaterial({color:0xffff9b,emissive:0xffd941,emissiveIntensity:2.8,metalness:.4,roughness:.15}));+ const halo=new THREE.Mesh(new THREE.TorusGeometry(.58,.035,8,22),new THREE.MeshBasicMaterial({color:0xffff81,transparent:true,opacity:.8}));halo.rotation.x=Math.PI/2;g.add(orb,halo);g.position.set(lanes[Math.floor(Math.random()*3)],1.1,-42);scene.add(g);objects.push({g,type:"core",passed:false});+}+function clearObjects(){objects.forEach(o=>scene.remove(o.g));objects=[]}+function endRun(){+ running=false;if(score>best){best=score;bestEl.textContent=best}+ copy.innerHTML="You travelled <b>"+score+"</b> metres.<br>Swipe or use A / D to shift lanes.";+ play.textContent="RUN AGAIN";screen.style.display="grid";clearObjects();+}+function begin(){+ clearObjects();score=0;scoreEl.textContent="0";lane=1;running=true;last=0;nextSpawn=0;screen.style.display="none";play.textContent="START RUN";+}+function animate(time){+ requestAnimationFrame(animate);+ const dt=Math.min(38,last?time-last:16);last=time;+ if(running){+ const pace=.042+Math.min(score,150)/5000;+ player.position.x+= (lanes[lane]-player.position.x)*Math.min(1,dt*.012);+ player.rotation.z=(lanes[lane]-player.position.x)*-.16;+ body.rotation.y+=dt*.006;ring.rotation.z+=dt*.004;+ skyline.children.forEach(b=>{b.position.z+=pace*dt;if(b.position.z>13)b.position.z-=60});+ if(time>nextSpawn){Math.random()<.3?makeCore():makeTower();nextSpawn=time+Math.max(420,790-score*2)}+ const playerX=player.position.x;+ for(let i=objects.length-1;i>=0;i--){+ const o=objects[i];o.g.position.z+=pace*dt;+ if(o.type==="core"){o.g.rotation.y+=dt*.006;o.g.children[1].rotation.z+=dt*.005}+ if(o.g.position.z>1.25&&o.g.position.z<3.3&&Math.abs(o.g.position.x-playerX)<.76){+ if(o.type==="core"){score+=12;scoreEl.textContent=score;scene.remove(o.g);objects.splice(i,1);continue}+ endRun();break;+ }+ if(o.g.position.z>11){scene.remove(o.g);objects.splice(i,1);if(o.type==="tower"){score++;scoreEl.textContent=score}}+ }+ camera.position.x+=(player.position.x*.18-camera.position.x)*.03;camera.lookAt(player.position.x*.16,.65,-9);+ }+ renderer.render(scene,camera);+}+play.addEventListener("click",e=>{e.stopPropagation();begin()});+window.addEventListener("keydown",e=>{const k=e.key.toLowerCase();if(k==="arrowleft"||k==="a"){e.preventDefault();move(-1)}if(k==="arrowright"||k==="d"){e.preventDefault();move(1)}if((k===" "||k==="enter")&&!running){e.preventDefault();begin()}});+renderer.domElement.addEventListener("pointerdown",e=>{swipeX=e.clientX});+renderer.domElement.addEventListener("pointerup",e=>{const d=e.clientX-swipeX;if(d>25)move(1);if(d<-25)move(-1)});+addEventListener("resize",()=>{camera.aspect=innerWidth/innerHeight;camera.updateProjectionMatrix();renderer.setSize(innerWidth,innerHeight)});+animate(0);+</script></body></html>