<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<title>🐾 زوبا ایرانی | نبرد قهرمانان | تمام لمسی</title>
<style>
*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent;}
body{
background:#0a0f08;
display:flex;justify-content:center;align-items:center;
height:100vh;overflow:hidden;
font-family:'Segoe UI',Tahoma,sans-serif;
touch-action:manipulation;
user-select:none;-webkit-user-select:none;
position:fixed;width:100%;
}
#game-wrapper{
position:relative;
width:100%;max-width:450px;
aspect-ratio:9/16;max-height:100vh;
border:3px solid #ffb020;
border-radius:20px;overflow:hidden;
box-shadow:0 0 50px rgba(255,140,0,0.5);
background:#2d5a1e;
}
canvas{display:block;width:100%;height:100%;}
#ui-layer{
position:absolute;top:8px;left:8px;right:8px;
display:flex;justify-content:space-between;
pointer-events:none;z-index:10;gap:6px;
}
.ui-box{
background:rgba(0,0,0,0.7);border:2px solid #e6a817;
border-radius:12px;padding:5px 10px;color:#ffd966;
font-weight:bold;font-size:13px;backdrop-filter:blur(4px);
text-align:center;min-width:65px;
}
.hp-outer{width:100%;height:6px;background:#331111;border-radius:8px;margin-top:3px;overflow:hidden;border:1px solid #a33;}
.hp-inner{height:100%;width:100%;background:linear-gradient(90deg,#f22,#f77);border-radius:8px;transition:width 0.2s;}
#hero-select{
position:absolute;top:0;left:0;width:100%;height:100%;
background:rgba(0,0,0,0.93);z-index:50;
display:flex;flex-direction:column;align-items:center;
justify-content:center;color:#ffcc44;overflow-y:auto;padding:20px;
}
#hero-select h2{font-size:22px;margin-bottom:4px;text-shadow:0 0 20px #ff8800;}
.hero-grid{display:flex;flex-wrap:wrap;gap:10px;justify-content:center;max-width:380px;margin-top:8px;}
.hero-card{
width:110px;height:140px;background:rgba(20,20,20,0.85);
border:3px solid #5a4a2a;border-radius:20px;
display:flex;flex-direction:column;align-items:center;
justify-content:center;cursor:pointer;transition:all 0.2s;
color:#ddd;font-weight:bold;font-size:12px;gap:5px;
}
.hero-card.selected{border-color:#ffcc00;box-shadow:0 0 30px #ffaa00;background:rgba(40,30,10,0.9);transform:scale(1.05);}
.hero-emoji{font-size:38px;}
.hero-stats{font-size:8px;color:#aaa;line-height:1.3;text-align:center;}
#start-btn{
margin-top:15px;padding:10px 40px;font-size:17px;
background:#ffaa00;border:none;border-radius:30px;
color:#0a0a0a;font-weight:bold;cursor:pointer;
box-shadow:0 0 25px #ff8800;
}
#mobile-controls{
position:absolute;bottom:20px;left:0;right:0;
z-index:20;display:flex;justify-content:space-between;
padding:0 15px;pointer-events:none;
}
#joystick-container{
width:90px;height:90px;pointer-events:auto;
position:relative;
}
#joystick-base{
width:90px;height:90px;border-radius:50%;
background:rgba(255,255,255,0.2);border:3px solid #ffbb44;
position:relative;backdrop-filter:blur(5px);
}
#joystick-thumb{
width:40px;height:40px;border-radius:50%;
background:rgba(255,200,80,0.8);
position:absolute;top:25px;left:25px;
transition:0.05s;pointer-events:none;
}
#right-buttons{
display:flex;flex-direction:column;gap:12px;pointer-events:auto;align-items:center;
}
#btn-special{
width:60px;height:60px;border-radius:50%;
background:rgba(138,43,226,0.5);border:3px solid #bb88ff;
font-size:26px;display:flex;align-items:center;justify-content:center;
backdrop-filter:blur(5px);color:white;
}
#btn-shoot{
width:70px;height:70px;border-radius:50%;
background:rgba(255,80,20,0.5);border:3px solid #ff8844;
font-size:30px;display:flex;align-items:center;justify-content:center;
backdrop-filter:blur(5px);color:white;
}
.cooldown-indicator{
position:absolute;font-size:20px;color:#fff;text-shadow:0 0 10px #000;
pointer-events:none;
}
#gameover-screen{
position:absolute;top:0;left:0;width:100%;height:100%;
background:rgba(0,0,0,0.85);z-index:40;
display:none;flex-direction:column;align-items:center;
justify-content:center;color:#ffd966;font-size:24px;font-weight:bold;
}
#gameover-screen button{
margin-top:18px;padding:10px 30px;font-size:17px;
background:#ffaa00;border:none;border-radius:30px;
font-weight:bold;cursor:pointer;
}
</style>
</head>
<body>
<div id="game-wrapper">
<canvas id="gameCanvas"></canvas>
<div id="ui-layer">
<div class="ui-box">⭐ <span id="scoreDisp">0</span><br>💀 <span id="killDisp">0</span></div>
<div class="ui-box" style="width:115px;">❤️ <span id="hpText">120</span>
<div class="hp-outer"><div class="hp-inner" id="hpFill"></div></div>
</div>
<div class="ui-box">⚡ <span id="specialDisp">آماده</span></div>
</div>
<div id="hero-select">
<h2>🐾 قهرمانت رو انتخاب کن</h2>
<div style="font-size:11px;color:#cca;margin-bottom:6px;">هر قهرمان قدرت منحصربهفرد داره</div>
<div class="hero-grid" id="heroGrid"></div>
<button id="start-btn">🎮 شروع نبرد!</button>
</div>
<div id="mobile-controls">
<div id="joystick-container">
<div id="joystick-base">
<div id="joystick-thumb"></div>
</div>
</div>
<div id="right-buttons">
<div id="btn-special">⚡</div>
<div id="btn-shoot">🔫</div>
</div>
</div>
<div id="gameover-screen">
<span>💔 شکست خوردی!</span>
<span style="font-size:14px;margin-top:5px;" id="finalScore"></span>
<button id="restartBtn">🔄 دوباره</button>
</div>
</div>
(function(){
const canvas=document.getElementById('gameCanvas');
const ctx=canvas.getContext('2d');
const W=450,H=800;
canvas.width=W;canvas.height=H;
const scoreDisp=document.getElementById('scoreDisp');
const killDisp=document.getElementById('killDisp');
const hpFill=document.getElementById('hpFill');
const hpText=document.getElementById('hpText');
const specialDisp=document.getElementById('specialDisp');
const heroSelectDiv=document.getElementById('hero-select');
const heroGrid=document.getElementById('heroGrid');
const startBtn=document.getElementById('start-btn');
const gameoverScreen=document.getElementById('gameover-screen');
const finalScoreSpan=document.getElementById('finalScore');
const restartBtn=document.getElementById('restartBtn');
const joyThumb=document.getElementById('joystick-thumb');
const joyBase=document.getElementById('joystick-base');
const btnSpecial=document.getElementById('btn-special');
const btnShoot=document.getElementById('btn-shoot');
let gameRunning=false,gameOver=false;
let score=0,kills=0;
let player,enemies=[],bullets=[],enemyBullets=[];
let enemySpawnTimer=0;
const MAP_W=2000,MAP_H=2000;
let bushes=[],walls=[],waters=[];
// Generate map
for(let i=0;i<120;i++) bushes.push({x:Math.random()*MAP_W,y:Math.random()*MAP_H,r:25+Math.random()*35});
for(let i=0;i<50;i++) walls.push({x:Math.random()*MAP_W,y:Math.random()*MAP_H,w:50+Math.random()*80,h:25+Math.random()*35});
for(let i=0;i<15;i++) waters.push({x:Math.random()*MAP_W,y:Math.random()*MAP_H,r:60+Math.random()*90});
const ALL_HEROES={
lion:{name:'شیر',emoji:'🦁',hp:130,speed:3.5,fireRate:15,damage:20,color:'#e6a817',
special:'غرش',specialCD:180,specialDesc:'دشمنان نزدیک میلرزند و کند میشوند'},
cheetah:{name:'یوزپلنگ',emoji:'🐆',hp:90,speed:6.2,fireRate:10,damage:14,color:'#e6b800',
special:'دوی سریع',specialCD:120,specialDesc:'سرعت ۲ برابر برای ۳ ثانیه'},
fox:{name:'روباه',emoji:'🦊',hp:100,speed:5.0,fireRate:9,damage:13,color:'#ff8844',
special:'فریب',specialCD:150,specialDesc:'دشمنان ۲ ثانیه گیج میشوند'},
turtle:{name:'لاکپشت',emoji:'🐢',hp:200,speed:2.0,fireRate:20,damage:25,color:'#66aa44',
special:'سپر لاکی',specialCD:200,specialDesc:'۳ ثانیه آسیب نمیبینی'},
monkey:{name:'میمون',emoji:'🐵',hp:95,speed:5.5,fireRate:8,damage:12,color:'#cc8844',
special:'موز پرتاب',specialCD:100,specialDesc:'پرتاب ۳ موز انفجاری'},
deer:{name:'گوزن',emoji:'🦌',hp:110,speed:4.8,fireRate:11,damage:16,color:'#bb7733',
special:'ضربه شاخ',specialCD:140,specialDesc:'پرتاب دشمنان نزدیک به عقب'},
eagle:{name:'عقاب',emoji:'🦅',hp:85,speed:5.8,fireRate:10,damage:18,color:'#ddcc88',
special:'پرواز',specialCD:160,specialDesc:'از روی موانع میپری'},
croc:{name:'تمساح',emoji:'🐊',hp:150,speed:3.0,fireRate:16,damage:28,color:'#558844',
special:'آرواره مرگ',specialCD:190,specialDesc:'گاز مرگبار به نزدیکترین دشمن'},
gorilla:{name:'گوریل',emoji:'🦍',hp:140,speed:3.8,fireRate:14,damage:22,color:'#776655',
special:'مشت زمین',specialCD:170,specialDesc:'ضربه به همه دشمنان اطراف'}
};
let selectedHero='lion';
let heroData=ALL_HEROES[selectedHero];
let specialCooldown=0;
function buildHeroCards(){
heroGrid='';
Object.entries(ALL_HEROES).forEach(([key,h])=>{
const card=document.createElement('div');
card.className='hero-card'+(key===selectedHero?' selected':'');
card=`<div class="hero-emoji">${h.emoji}</div><div>${h.name}</div>
<div class="hero-stats">❤️${h.hp} ⚡${h.speed} 💥${h.damage}<br>✨${h.special}</div>`;
card.addEventListener('click',()=>{
document.querySelectorAll('.hero-card').forEach(c=>c.classList.remove('selected'));
card.classList.add('selected');
selectedHero=key;
heroData=ALL_HEROES[key];
});
heroGrid(card);
});
}
buildHeroCards();
// Joystick handling
let joystick={dx:0,dy:0,active:false};
let joyId=null;
joyBase.addEventListener('touchstart',(e)=>{
e.preventDefault();joyId=e.changedTouches[0].identifier;joystick.active=true;
});
joyBase.addEventListener('touchmove',(e)=>{
e.preventDefault();
for(let t of e.changedTouches){
if(t.identifier===joyId){
const rect=joyBase.getBoundingClientRect();
const cx=rect.left+rect.width/2,cy=rect.top+rect.height/2;
let dx=t.clientX-cx,dy=t.clientY-cy;
const dist=Math.sqrt(dx*dx+dy*dy);
const maxDist=35;
if(dist>maxDist){dx=dx/dist*maxDist;dy=dy/dist*maxDist;}
joystick.dx=dx/maxDist;joystick.dy=dy/maxDist;
joyThumb.style.left=(25+dx)+'px';joyThumb.style.top=(25+dy)+'px';
}
}
});
joyBase.addEventListener('touchend',(e)=>{
for(let t of e.changedTouches){
if(t.identifier===joyId){joystick.active=false;joystick.dx=0;joystick.dy=0;
joyThumb.style.left='25px';joyThumb.style.top='25px';joyId=null;}
}
});
let shootDown=false;
btnShoot.addEventListener('touchstart',(e)=>{e.preventDefault();shootDown=true;});
btnShoot.addEventListener('touchend',()=>shootDown=false);
btnShoot.addEventListener('touchcancel',()=>shootDown=false);
btnSpecial.addEventListener('touchstart',(e)=>{
e.preventDefault();
if(specialCooldown<=0 && gameRunning && !gameOver) activateSpecial();
});
function activateSpecial(){
specialCooldown=heroData.specialCD;
const p=player;
switch(selectedHero){
case 'lion': // غرش - کند کردن دشمنان نزدیک
enemies.forEach(e=>{
const d=Math.hypot(e.x-p.x,e.y-p.y);
if(d<180){e.slowed=60;e.speed*=0.4;}
});
break;
case 'cheetah': // دوی سریع
p.speedBoost=60;p.speed*=2.2;
break;
case 'fox': // فریب - گیج کردن
enemies.forEach(e=>{
if(Math.hypot(e.x-p.x,e.y-p.y)<200)e.confused=60;
});
break;
case 'turtle': // سپر
p.shield=90;
break;
case 'monkey': // موز انفجاری
for(let i=0;i<3;i++){
setTimeout(()=>{
const t=enemies[Math.floor(Math.random()*enemies.length)];
if(t){t.hp-=25;if(t.hp<=0)killEnemy(t);}
},i*150);
}
break;
case 'deer': // پرتاب
enemies.forEach(e=>{
if(Math.hypot(e.x-p.x,e.y-p.y)<150){
const a=Math.atan2(e.y-p.y,e.x-p.x);
e.x+=Math.cos(a)*120;e.y+=Math.sin(a)*120;
e.hp-=15;if(e.hp<=0)killEnemy(e);
}
});
break;
case 'eagle': // پرش
p.zJump=30;p.zVel=-8;
break;
case 'croc':
const closest=enemies.reduce((a,b)=>Math.hypot(a.x-p.x,a.y-p.y)<Math.hypot(b.x-p.x,b.y-p.y)?a:b,enemies[0]);
if(closest&&Math.hypot(closest.x-p.x,closest.y-p.y)<130){closest.hp-=40;if(closest.hp<=0)killEnemy(closest);}
break;
case 'gorilla':
enemies.forEach(e=>{if(Math.hypot(e.x-p.x,e.y-p.y)<170){e.hp-=20;if(e.hp<=0)killEnemy(e);}});
break;
}
}
function initGame(){
heroData=ALL_HEROES[selectedHero];
player={
x:MAP_W/2,y:MAP_H/2,radius:18,
hp:heroData.hp,maxHp:heroData.hp,
speed:heroData.speed,fireRate:heroData.fireRate,
damage:heroData.damage,fireCooldown:0,
speedBoost:0,shield:0,zJump:0,zVel:0
};
enemies=[];bullets=[];enemyBullets=[];
score=0;kills=0;specialCooldown=0;
enemySpawnTimer=0;gameOver=false;gameRunning=true;
gameoverScreen.style.display='none';heroSelectDiv.style.display='none';
updateUI();
}
function spawnEnemy(){
const a=Math.random()*Math.PI*2,d=450+Math.random()*350;
let ex=player.x+Math.cos(a)*d,ey=player.y+Math.sin(a)*d;
ex=Math.max(40,Math.min(MAP_W-40,ex));
ey=Math.max(40,Math.min(MAP_H-40,ey));
const types=['gorilla','croc','fox_bot','deer_bot'];
const t=types[Math.floor(Math.random()*types.length)];
const stats={gorilla:{hp:70,sp:1.5,dmg:12,rad:18},croc:{hp:55,sp:2.2,dmg:9,rad:16},
fox_bot:{hp:45,sp:2.8,dmg:7,rad:15},deer_bot:{hp:50,sp:2.5,dmg:8,rad:17}};
enemies.push({
x:ex,y:ey,radius:stats[t].rad,hp:stats[t].hp,maxHp:stats[t].hp,
speed:stats[t].sp,damage:stats[t].dmg,type:t,fireCooldown:0,
slowed:0,confused:0
});
}
function killEnemy(e){
const idx=enemies.indexOf(e);
if(idx>-1)enemies.splice(idx,1);
kills++;score+=10;
}
function updateUI(){
scoreDisp.textContent=score;killDisp.textContent=kills;
hpFill.style.width=(player.hp/player.maxHp*100)+'%';
hpText.textContent=Math.ceil(player.hp);
specialDisp.textContent=specialCooldown>0?Math.ceil(specialCooldown/60)+'s':'⚡آماده';
}
function update(){
if(!gameRunning||gameOver)return;
// Player movement
let mx=joystick.dx*heroData.speed*(player.speedBoost>0?2.2:1);
let my=joystick.dy*heroData.speed*(player.speedBoost>0?2.2:1);
if(player.zJump>0){my-=4;player.zJump--;}
player.x=Math.max(20,Math.min(MAP_W-20,player.x+mx));
player.y=Math.max(20,Math.min(MAP_H-20,player.y+my));
if(player.speedBoost>0)player.speedBoost--;
if(player.shield>0)player.shield--;
if(specialCooldown>0)specialCooldown--;
// Auto-target nearest enemy for shooting
let nearestEnemy=null,nearestDist=250;
enemies.forEach(e=>{
const d=Math.hypot(e.x-player.x,e.y-player.y);
if(d<nearestDist){nearestDist=d;nearestEnemy=e;}
});
// Shooting
if(player.fireCooldown>0)player.fireCooldown--;
if(shootDown && player.fireCooldown<=0 && nearestEnemy){
const a=Math.atan2(nearestEnemy.y-player.y,nearestEnemy.x-player.x);
bullets.push({x:player.x,y:player.y,vx:Math.cos(a)*9,vy:Math.sin(a)*9,damage:heroData.damage});
player.fireCooldown=heroData.fireRate;
}
// Bullets
bullets.forEach(b=>{b.x+=b.vx;b.y+=b.vy;});
bullets=bullets.filter(b=>b.x>0&&b.x<MAP_W&&b.y>0&&b.y<MAP_H);
enemyBullets.forEach(b=>{b.x+=b.vx;b.y+=b.vy;});
enemyBullets=enemyBullets.filter(b=>b.x>0&&b.x<MAP_W&&b.y>0&&b.y<MAP_H);
// Bullet-enemy collision
bullets.forEach(b=>{
enemies.forEach(e=>{
if(Math.hypot(b.x-e.x,b.y-e.y)<e.radius+5){
e.hp-=b.damage;b.hit=true;
if(e.hp<=0)killEnemy(e);
}
});
});
bullets=bullets.filter(b=>!b.hit);
// Enemy bullet-player collision
enemyBullets.forEach(b=>{
if(Math.hypot(b.x-player.x,b.y-player.y)<player.radius+5){
if(player.shield<=0)player.hp-=b.damage||8;
b.hit=true;
}
});
enemyBullets=enemyBullets.filter(b=>!b.hit);
// Enemy AI
enemies.forEach(e=>{
if(e.slowed>0){e.slowed--;if(e.slowed===0)e.speed*=2.5;}
if(e.confused>0){e.confused--;return;}
const dx=player.x-e.x,dy=player.y-e.y,dist=Math.hypot(dx,dy);
if(dist>5){e.x+=dx/dist*e.speed;e.y+=dy/dist*e.speed;}
if(e.fireCooldown>0)e.fireCooldown--;
if(dist<300 && e.fireCooldown<=0 && Math.random()<0.02){
const a=Math.atan2(player.y-e.y,player.x-e.x);
enemyBullets.push({x:e.x,y:e.y,vx:Math.cos(a)*7,vy:Math.sin(a)*7,damage:e.damage});
e.fireCooldown=25;
}
});
// Spawn
enemySpawnTimer--;
if(enemySpawnTimer<=0 && enemies.length<12){
spawnEnemy();enemySpawnTimer=70+Math.random()*50;
}
if(player.hp<=0){gameOver=true;gameRunning=false;gameoverScreen.style.display='flex';
finalScoreSpan.textContent='⭐ '+score+' 💀 '+kills;}
updateUI();
}
function draw(){
ctx.clearRect(0,0,W,H);
const camX=player.x-W/2,camY=player.y-H/2;
ctx.save();ctx.translate(-camX,-camY);
// Grass bg
ctx.fillStyle='#4a8c3f';ctx.fillRect(0,0,MAP_W,MAP_H);
// Grid
ctx.strokeStyle='#3a7030';ctx.lineWidth=1;
for(let i=0;i<MAP_W;i+=80){ctx.beginPath();ctx.moveTo(i,0);ctx.lineTo(i,MAP_H);ctx.stroke();}
for(let i=0;i<MAP_H;i