File size: 5,401 Bytes
1289656 f014153 1289656 f014153 1289656 046ea31 1289656 149c1bb 1289656 f014153 f1d61eb f014153 627df7c f014153 149c1bb 046ea31 f014153 046ea31 f014153 046ea31 f014153 046ea31 f014153 149c1bb f014153 1289656 f014153 1289656 f014153 f1d61eb 149c1bb f014153 7e9f5dd f014153 149c1bb 046ea31 149c1bb 046ea31 149c1bb f014153 149c1bb f014153 149c1bb f014153 046ea31 149c1bb 7e9f5dd f014153 149c1bb f014153 149c1bb 046ea31 149c1bb f014153 149c1bb f014153 046ea31 f014153 046ea31 7e9f5dd f014153 7e9f5dd f014153 149c1bb f014153 149c1bb 1289656 aaac8e1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>OutRun con Rivales visibles</title>
<style>
body{margin:0;overflow:hidden;background:#6dd5fa;font-family:sans-serif;touch-action:none;}
canvas{display:block;width:100vw;height:80vh;background:skyblue;}
#controls{position:fixed;bottom:0;width:100%;display:flex;justify-content:space-around;padding:10px;background:rgba(0,0,0,0.3);}
.btn{width:70px;height:70px;border-radius:50%;border:none;background:rgba(255,255,255,0.7);font-size:24px;font-weight:bold;user-select:none;}
#hud{position:fixed;top:5px;left:0;right:0;display:flex;justify-content:space-around;font-size:20px;font-weight:bold;color:white;text-shadow:2px 2px 3px black;}
</style>
</head>
<body>
<canvas id="game"></canvas>
<div id="hud">
<div id="score">SCORE: 0</div>
<div id="time">TIME: 60</div>
<div id="speed">SPEED: 0 km/h</div>
</div>
<div id="controls">
<button class="btn" id="left">⟵</button>
<button class="btn" id="right">⟶</button>
<button class="btn" id="up">⏫</button>
<button class="btn" id="down">⏬</button>
</div>
<script>
// ===== SETUP =====
const canvas=document.getElementById("game"),ctx=canvas.getContext("2d");
function resize(){canvas.width=window.innerWidth;canvas.height=window.innerHeight*0.8;}
resize();window.addEventListener("resize",resize);
let roadWidth=2000,segL=200,camD=0.84;
let playerX=0,pos=0,speed=200;
let score=0,timeLeft=60;
let keys={left:false,right:false,up:false,down:false};
let segments=[];
// carretera
for(let i=0;i<500;i++){segments.push({i,curve:Math.sin(i/30)*2,y:i*segL});}
// sprites
let palmImg=new Image(); palmImg.src="https://i.ibb.co/6Hw6yHr/palm.png";
let carImg=new Image(); carImg.src="https://i.ibb.co/VVvTqYm/car.png";
// rivales
let rivals=[];
function spawnRival(){
let lane=(Math.random()*2-1)*0.8; // carriles
let z=pos+2000+Math.random()*3000;
let spd=400+Math.random()*400;
rivals.push({x:lane,z,spd});
}
setInterval(spawnRival,3000);
// ===== INPUT =====
window.addEventListener("keydown",e=>{
if(e.key==="ArrowLeft")keys.left=true;
if(e.key==="ArrowRight")keys.right=true;
if(e.key==="ArrowUp")keys.up=true;
if(e.key==="ArrowDown")keys.down=true;
});
window.addEventListener("keyup",e=>{
if(e.key==="ArrowLeft")keys.left=false;
if(e.key==="ArrowRight")keys.right=false;
if(e.key==="ArrowUp")keys.up=false;
if(e.key==="ArrowDown")keys.down=false;
});
function bindTouch(id,key){
let el=document.getElementById(id);
el.addEventListener("touchstart",()=>keys[key]=true);
el.addEventListener("touchend",()=>keys[key]=false);
}
bindTouch("left","left"); bindTouch("right","right");
bindTouch("up","up"); bindTouch("down","down");
// ===== CORE =====
function project(p,camX,camY,camZ){
let dz=p.z-camZ; if(dz<=0.1)dz=0.1; // evita división por cero
let dx=p.x-camX,dy=p.y-camY;
let scale=camD/dz;
return {x:(1+scale*dx)*canvas.width/2,y:(1-scale*dy)*canvas.height/2,w:scale*roadWidth/2};
}
function drawSegment(p1,p2,color){
ctx.fillStyle=color.grass; ctx.fillRect(0,p2.y,canvas.width,p1.y-p2.y);
ctx.fillStyle=color.road;
ctx.beginPath();
ctx.moveTo(p1.x-p1.w,p1.y); ctx.lineTo(p1.x+p1.w,p1.y);
ctx.lineTo(p2.x+p2.w,p2.y); ctx.lineTo(p2.x-p2.w,p2.y);
ctx.fill();
}
function drawSprite(img,scale,x,y,w,h){ctx.drawImage(img,x-w*scale/2,y-h*scale,w*scale,h*scale);}
// ===== UPDATE =====
function update(dt){
pos+=speed*dt; if(pos>=segments.length*segL)pos-=segments.length*segL;
if(keys.left)playerX-=0.02;
if(keys.right)playerX+=0.02;
if(keys.up)speed+=5;
if(keys.down)speed-=5;
if(speed<0)speed=0;if(speed>2000)speed=2000;
for(let r of rivals){r.z-= (speed-r.spd)*dt;}
rivals=rivals.filter(r=>r.z>pos&&r.z<pos+8000);
timeLeft-=dt;if(timeLeft<=0){timeLeft=0;speed=0;}
score+=Math.floor(speed*dt*0.1);
document.getElementById("score").textContent="SCORE: "+score;
document.getElementById("time").textContent="TIME: "+Math.floor(timeLeft);
document.getElementById("speed").textContent="SPEED: "+Math.floor(speed/10)+" km/h";
}
// ===== RENDER =====
function render(){
ctx.clearRect(0,0,canvas.width,canvas.height);
let base=Math.floor(pos/segL),camY=1000,camZ=pos+500;
let x=0,dx=0;
for(let n=0;n<300;n++){
let seg=segments[(base+n)%segments.length];
seg.z=seg.y-pos; x+=dx; dx+=seg.curve*0.001;
let p1=project({x:x,y:0,z:seg.z},playerX*roadWidth,camY,camZ);
let p2=project({x:x+dx,y:0,z:seg.z+segL},playerX*roadWidth,camY,camZ);
let color={road:n%2?"#707070":"#696969",grass:n%2?"#10aa10":"#009900",rumble:"#fff"};
if(p1.y>=p2.y&&p2.y<canvas.height)drawSegment(p1,p2,color);
if(n%20===0&&palmImg.complete){
let s=p1.w/250;
drawSprite(palmImg,s,p1.x-p1.w*1.5,p1.y,200,200);
drawSprite(palmImg,s,p1.x+p1.w*1.5,p1.y,200,200);
}
}
// rivales visibles
for(let r of rivals){
let dz=r.z-pos; if(dz<=0)continue;
let proj=project({x:r.x*roadWidth,y:0,z:dz},playerX*roadWidth,1000,pos+500);
if(carImg.complete){
let s=proj.w/350;
drawSprite(carImg,s,proj.x,proj.y,120,60);
}
}
// auto jugador
ctx.fillStyle="red";
ctx.fillRect(canvas.width/2-20+playerX*200,canvas.height-80,40,60);
}
// ===== LOOP =====
let last=0;
function loop(ts){let dt=(ts-last)/1000;if(dt>0.05)dt=0.05;last=ts;update(dt);render();requestAnimationFrame(loop);}
requestAnimationFrame(loop);
</script>
</body>
</html>
|