Meta Description" name="description" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Boss Balanceado</title>
<style>
body { margin:0; overflow:hidden; background:black; }
canvas { display:block; margin:auto; background:#111; }
/* JOYSTICK MΓS GRANDE π₯ */
#joystick {
position:absolute; bottom:30px; left:30px;
width:160px; height:160px;
background:rgba(255,255,255,0.1);
border-radius:50%; touch-action:none;
}
#stick {
width:70px; height:70px;
background:rgba(255,255,255,0.5);
border-radius:50%;
position:absolute; top:45px; left:45px;
}
/* DISPARO */
#shoot {
position:absolute; bottom:40px; right:40px;
width:100px; height:100px;
background:rgba(255,0,0,0.5);
border-radius:50%; touch-action:none;
}
</style>
</head>
<body>
<canvas id="game" width="900" height="500"></canvas>
<div id="joystick"><div id="stick"></div></div>
<div id="shoot"></div>
<script>
const canvas = document.getElementById("game");
const ctx = canvas.getContext("2d");
let state="menu";
// π₯ VIDA BALANCEADA (~1 MIN)
let player={ x:100,y:250,size:30,hp:12 };
let boss={ x:650,y:180,size:120,hp:600,maxHp:600,phase:1 };
let bullets=[];
let bossBullets=[];
// JOYSTICK GRANDE
let joy=document.getElementById("joystick");
let stick=document.getElementById("stick");
let joyData={x:0,y:0};
joy.addEventListener("touchmove", e=>{
let r=joy.getBoundingClientRect();
let t=e.touches[0];
let dx=t.clientX-(r.left+80);
let dy=t.clientY-(r.top+80);
let d=Math.sqrt(dx*dx+dy*dy);
let m=70;
if(d>m){ dx=dx/d*m; dy=dy/d*m; }
stick.style.left=(dx+45)+"px";
stick.style.top=(dy+45)+"px";
joyData.x=dx/m;
joyData.y=dy/m;
});
joy.addEventListener("touchend", ()=>{
joyData={x:0,y:0};
stick.style.left="45px";
stick.style.top="45px";
});
// DISPARO
let shooting=false;
document.getElementById("shoot").ontouchstart=()=>shooting=true;
document.getElementById("shoot").ontouchend=()=>shooting=false;
// START
canvas.addEventListener("touchstart", ()=>{
if(state==="menu") state="game";
});
let shootTimer=0;
let bossTimer=0;
// UPDATE
function update(){
if(state!=="game") return;
// movimiento
player.x+=joyData.x*5;
player.y+=joyData.y*5;
player.x=Math.max(0,Math.min(900-player.size,player.x));
player.y=Math.max(0,Math.min(500-player.size,player.y));
// DISPARO PLAYER
shootTimer++;
if(shooting && shootTimer>6){
shootTimer=0;
bullets.push({x:player.x+30,y:player.y+12});
}
// π₯ DISPARO BOSS ALEATORIO
bossTimer++;
if(bossTimer>35){
bossTimer=0;
for(let i=0;i<5+boss.phase;i++){
let angle=Math.random()*Math.PI*2;
bossBullets.push({
x:boss.x+60,
y:boss.y+60,
dx:Math.cos(angle)*(2+boss.phase*0.3),
dy:Math.sin(angle)*(2+boss.phase*0.3)
});
}
}
// BALAS PLAYER
for(let i=bullets.length-1;i>=0;i--){
let b=bullets[i];
b.x+=8;
if(b.x>900){ bullets.splice(i,1); continue; }
if(
b.x<boss.x+boss.size &&
b.x+6>boss.x &&
b.y<boss.y+boss.size &&
b.y+6>boss.y
){
boss.hp-=2;
bullets.splice(i,1);
}
}
// BALAS BOSS
for(let i=bossBullets.length-1;i>=0;i--){
let b=bossBullets[i];
b.x+=b.dx;
b.y+=b.dy;
if(
b.x<player.x+player.size &&
b.x+6>player.x &&
b.y<player.y+player.size &&
b.y+6>player.y
){
player.hp--;
bossBullets.splice(i,1);
continue;
}
if(b.x<0||b.x>900||b.y<0||b.y>500){
bossBullets.splice(i,1);
}
}
// fases
boss.phase = Math.min(10, 1 + Math.floor((1 - boss.hp / boss.maxHp) * 10));
if(player.hp<=0){
alert("Perdiste π");
location.reload();
}
if(boss.hp<=0){
alert("GANASTE ππ₯");
location.reload();
}
}
// DRAW
function draw(){
ctx.clearRect(0,0,900,500);
if(state==="menu"){
ctx.fillStyle="white";
ctx.font="40px Arial";
ctx.fillText("TOCA PARA EMPEZAR",250,250);
return;
}
ctx.fillStyle="white";
ctx.beginPath();
ctx.arc(player.x+15,player.y+15,15,0,Math.PI*2);
ctx.fill();
let colors=["red","orange","yellow","green","blue","purple","pink","cyan","white","gold"];
ctx.fillStyle=colors[boss.phase-1];
ctx.fillRect(boss.x,boss.y,boss.size,boss.size);
ctx.fillStyle="gray";
ctx.fillRect(200,20,500,20);
ctx.fillStyle="green";
ctx.fillRect(200,20,(boss.hp/boss.maxHp)*500,20);
ctx.fillStyle="yellow";
bullets.forEach(b=>ctx.fillRect(b.x,b.y,6,6));
ctx.fillStyle="cyan";
bossBullets.forEach(b=>ctx.fillRect(b.x,b.y,6,6));
ctx.fillStyle="white";
ctx.fillText("HP: "+player.hp,20,30);
ctx.fillText("FASE: "+boss.phase,20,60);
}
function loop(){
update();
draw();
requestAnimationFrame(loop);
}
loop();
</script>
</body>
</html1
1
5KB
5KB
107.0ms
124.0ms
108.0ms