ToonBlock Arena
by ShadowTurtle30186 lines6.4 KB
<!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.