🎮ArcadeLab

ToonBlock Arena

by ShadowTurtle30
186 lines6.4 KB
▶ Play
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>ToonBlock Arena</title>
<style>
*{box-sizing:border-box}
body{margin:0;background:#19213d;color:white;font-family:system-ui;text-align:center}
h1{color:#ffe66d;margin:12px}
#stats{display:flex;justify-content:center;gap:10px;flex-wrap:wrap;margin:10px}
#stats span{background:#34446d;padding:8px 14px;border-radius:12px}
canvas{width:min(94vw,600px);height:auto;border:4px solid white;border-radius:14px;touch-action:none}
button{padding:12px;margin:4px;border:0;border-radius:10px;background:#ffcf58;color:#292448;font-weight:bold;font-size:14px}
#msg{min-height:30px;color:#ffe66d;padding:8px}
</style>
</head>
<body>
<h1>⭐ TOONBLOCK ARENA ⭐</h1>
<div id="stats">
<span>❤️ Vita: <b id="hp">100</b></span>
<span>🧱 Blocchi: <b id="wood">10</b></span>
<span>👾 Mostri: <b id="left">5</b></span>
</div>
<canvas id="game" width="480" height="360"></canvas>
<div>
<button onclick="build()">🧱 Costruisci (clic sinistro)</button>
<button onclick="hit()">💥 Colpisci (clic destro)</button>
<button onclick="collect()">🌳 Raccogli (E)</button>
<button onclick="start()">🔄 Riprova</button>
</div>
<div id="msg">WASD per muoverti. Sconfiggi tutti i mostri!</div>
<script>
const c=document.getElementById('game'),g=c.getContext('2d');
const W=480,H=360;
let p,enemies,trees,walls,keys={},hp,wood,over,won,aim={x:400,y:180};
const $=id=>document.getElementById(id);
function rand(a,b){return a+Math.random()*(b-a)}
function dist(a,b){return Math.hypot(a.x-b.x,a.y-b.y)}
function say(t){$('msg').textContent=t}
function hud(){
 $('hp').textContent=hp;$('wood').textContent=wood;
 $('left').textContent=enemies.filter(e=>e.hp>0).length;
}
function start(){
 p={x:240,y:180};hp=100;wood=10;over=false;won=false;
 walls=[];trees=[];enemies=[];
 for(let i=0;i<18;i++)trees.push({x:rand(18,462),y:rand(18,342)});
 for(let i=0;i<5;i++)enemies.push({
  x:rand(30,450),y:rand(30,330),hp:3,
  color:['#ff6489','#bd83ff','#ff9f43','#56c8ff','#ffdb57'][i]
 });
 say('Pronto! Sopravvivi e sconfiggi tutti i mostri.');
 hud();
}
function blocked(x,y){
 return walls.some(b=>Math.hypot(b.x-x,b.y-y)<19)||
 trees.some(t=>Math.hypot(t.x-x,t.y-y)<13);
}
function move(dx,dy){
 if(over)return;
 let n=Math.hypot(dx,dy)||1;
 let x=Math.max(12,Math.min(W-12,p.x+dx/n*2.8));
 let y=Math.max(12,Math.min(H-12,p.y+dy/n*2.8));
 if(!blocked(x,p.y))p.x=x;
 if(!blocked(p.x,y))p.y=y;
}
function build(){
 if(over)return;
 if(wood<2){say('Raccogli legno per costruire!');return}
 let a=Math.atan2(aim.y-p.y,aim.x-p.x);
 let b={x:p.x+Math.cos(a)*32,y:p.y+Math.sin(a)*32};
 if(b.x<12||b.x>468||b.y<12||b.y>348||blocked(b.x,b.y)){
 say('Qui non puoi costruire!');return}
 walls.push(b);wood-=2;hud();say('Muro costruito!');
}
function hit(){
 if(over)return;
 let e=enemies.filter(e=>e.hp>0&&dist(e,p)<65)
 .sort((a,b)=>dist(a,p)-dist(b,p))[0];
 if(!e){say('Avvicinati a un mostro per colpirlo!');return}
 e.hp--;
 if(e.hp<=0)say('BOOM! Mostro sconfitto!');
 else say('Colpito! Continua!');
 hud();
 if(enemies.every(e=>e.hp<=0)){
 over=true;won=true;say('🏆 VITTORIA! Sei il campione!');
 }
}
function collect(){
 if(over)return;
 let i=trees.findIndex(t=>dist(t,p)<38);
 if(i<0){say('Avvicinati a un albero!');return}
 trees.splice(i,1);wood+=4;hud();say('+4 blocchi di legno!');
}
window.addEventListener('keydown',e=>{
 let k=e.key.toLowerCase();
 if(['w','a','s','d','arrowup','arrowdown','arrowleft','arrowright',' '].includes(k))e.preventDefault();
 keys[k]=true;
 if(k==='e')collect();
 if(k==='b')build();
 if(k==='f')hit();
});
window.addEventListener('keyup',e=>keys[e.key.toLowerCase()]=false);
c.addEventListener('contextmenu',e=>e.preventDefault());
function point(e){
 let r=c.getBoundingClientRect();
 aim={x:(e.clientX-r.left)*W/r.width,y:(e.clientY-r.top)*H/r.height};
}
c.addEventListener('pointermove',point);
c.addEventListener('pointerdown',e=>{
 point(e);
 if(e.pointerType==='touch'){hit();return}
 if(e.button===0)build();
 if(e.button===2)hit();
});
function rr(x,y,w,h,r,color){
 g.fillStyle=color;g.beginPath();g.roundRect(x,y,w,h,r);g.fill();
}
function hero(x,y,color,label){
 rr(x-10,y-5,20,20,6,'#44446f');
 rr(x-11,y-19,22,23,8,color);
 rr(x-7,y-15,5,7,2,'white');rr(x+3,y-15,5,7,2,'white');
 g.fillStyle='#30314d';g.fillRect(x-8,y+14,6,6);g.fillRect(x+3,y+14,6,6);
 g.fillStyle='white';g.font='bold 10px system-ui';g.textAlign='center';g.fillText(label,x,y-24);
}
function draw(){
 g.clearRect(0,0,W,H);
 for(let y=0;y<H;y+=24)for(let x=0;x<W;x+=24){
  g.fillStyle=(x/24+y/24)%2?'#8cda75':'#7ccc67';g.fillRect(x,y,24,24);
 }
 trees.forEach(t=>{
  g.fillStyle='#86502e';g.fillRect(t.x-4,t.y,8,10);
  rr(t.x-11,t.y-13,22,23,8,'#21955b');
  rr(t.x-7,t.y-17,14,13,6,'#4ad47c');
 });
 walls.forEach(b=>{
  rr(b.x-12,b.y-12,24,24,5,'#8c63df');
  rr(b.x-10,b.y-10,20,6,3,'#c4a1ff');
  g.strokeStyle='#5c399f';g.strokeRect(b.x-10,b.y-10,20,20);
 });
 enemies.forEach(e=>{
  if(e.hp<=0)return;
  rr(e.x-13,e.y-13,26,27,10,e.color);
  rr(e.x-9,e.y-19,18,13,6,e.color);
  rr(e.x-7,e.y-8,5,7,2,'white');rr(e.x+3,e.y-8,5,7,2,'white');
  g.fillStyle='#38284c';g.fillRect(e.x-4,e.y-5,3,4);g.fillRect(e.x+5,e.y-5,3,4);
  g.fillStyle='#453050';g.fillRect(e.x-12,e.y-24,24,4);
  g.fillStyle='#ffe35b';g.fillRect(e.x-12,e.y-24,24*e.hp/3,4);
 });
 hero(p.x,p.y,'#30c9ee','TU');
 if(over){
  g.fillStyle='#171a37d9';g.fillRect(0,0,W,H);
  g.fillStyle=won?'#ffe66d':'#ff8197';
  g.font='bold 30px system-ui';g.textAlign='center';
  g.fillText(won?'HAI VINTO!':'GAME OVER',W/2,H/2);
  g.fillStyle='white';g.font='16px system-ui';
  g.fillText('Premi Riprova per giocare ancora',W/2,H/2+30);
 }
}
function loop(){
 if(!over){
  move(
   (keys.d||keys.arrowright?1:0)-(keys.a||keys.arrowleft?1:0),
   (keys.s||keys.arrowdown?1:0)-(keys.w||keys.arrowup?1:0)
  );
  enemies.forEach(e=>{
   if(e.hp<=0)return;
   let d=dist(e,p);
   if(d>23){
    let dx=p.x-e.x,dy=p.y-e.y,n=Math.hypot(dx,dy)||1;
    let x=e.x+dx/n*.48,y=e.y+dy/n*.48;
    if(!blocked(x,y)){e.x=x;e.y=y}
   }else if(Math.random()<.012){
    hp=Math.max(0,hp-8);hud();
    if(hp===0){over=true;say('Sei stato sconfitto! Premi Riprova.')}
   }
  });
 }
 draw();requestAnimationFrame(loop);
}
start();loop();
</script>
</body>
</html>

Game Source: ToonBlock Arena

Creator: ShadowTurtle30

Libraries: none

Complexity: moderate (186 lines, 6.4 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: toonblock-arena-shadowturtle30-mvb60u25" to link back to the original. Then publish at arcadelab.ai/publish.