🎮ArcadeLab

🌌 CMB GALAXY WAR - نبرد کهکشانی تابش زمینه

by ElectricCobra60
638 lines23.1 KB
▶ Play
<!DOCTYPE html>
<html lang="fa">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <title>🌌 CMB GALAXY WAR - نبرد کهکشانی تابش زمینه</title>
    <style>
        * {
            user-select: none;
            touch-action: none;
        }

        body {
            margin: 0;
            min-height: 100vh;
            background: linear-gradient(135deg, #000000 0%, #0a0a2a 100%);
            display: flex;
            justify-content: center;
            align-items: center;
            font-family: 'Orbitron', 'Courier New', monospace;
            padding: 15px;
            overflow: hidden;
            position: fixed;
            width: 100%;
            height: 100%;
        }

        @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&display=swap');

        .game-wrapper {
            max-width: 900px;
            width: 100%;
            position: relative;
        }

        canvas {
            display: block;
            width: 100%;
            height: auto;
            background: radial-gradient(ellipse at center, #0a0a2a 0%, #000000 100%);
            border-radius: 30px;
            box-shadow: 0 0 40px rgba(0, 255, 255, 0.5), 0 0 20px rgba(255, 0, 255, 0.3);
            cursor: none;
            touch-action: none;
        }

        .hud {
            display: flex;
            justify-content: space-between;
            align-items: center;
            background: rgba(0, 0, 0, 0.85);
            backdrop-filter: blur(15px);
            padding: 12px 20px;
            border-radius: 50px;
            margin-bottom: 15px;
            border: 1px solid rgba(0, 255, 255, 0.5);
            flex-wrap: wrap;
            gap: 10px;
        }

        .stat-card {
            background: rgba(0,0,0,0.6);
            padding: 5px 15px;
            border-radius: 30px;
            text-align: center;
            border-left: 3px solid cyan;
        }

        .stat-card span {
            font-size: 0.65rem;
            color: #88aaff;
        }

        .stat-card div {
            font-size: 1.4rem;
            font-weight: bold;
            color: #ffd700;
            text-shadow: 0 0 5px orange;
        }

        .hearts {
            display: flex;
            gap: 8px;
            font-size: 1.8rem;
        }

        button {
            background: linear-gradient(135deg, #ff416c, #ff4b2b);
            border: none;
            padding: 8px 18px;
            border-radius: 30px;
            font-family: 'Orbitron', monospace;
            font-weight: bold;
            font-size: 0.8rem;
            color: white;
            cursor: pointer;
            transition: all 0.2s;
        }

        button:active {
            transform: scale(0.95);
        }

        .upgrade-panel {
            position: fixed;
            bottom: 20px;
            right: 20px;
            background: rgba(0,0,0,0.9);
            backdrop-filter: blur(10px);
            padding: 15px;
            border-radius: 25px;
            border: 1px solid gold;
            min-width: 180px;
            z-index: 100;
            font-size: 0.7rem;
        }

        .upgrade-panel h4 {
            margin: 0 0 10px 0;
            color: gold;
        }

        .upgrade-item {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin: 8px 0;
            gap: 10px;
        }

        .upgrade-item button {
            padding: 4px 12px;
            font-size: 0.7rem;
            background: #2c3e66;
        }

        .damage-number {
            position: absolute;
            pointer-events: none;
            font-weight: bold;
            font-size: 1.2rem;
            animation: floatUp 0.6s ease-out forwards;
            z-index: 200;
            text-shadow: 0 0 5px red;
        }

        @keyframes floatUp {
            0% { opacity: 1; transform: translateY(0px) scale(0.8); }
            100% { opacity: 0; transform: translateY(-60px) scale(1.3); }
        }

        .game-over-modal {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: rgba(0,0,0,0.98);
            padding: 30px;
            border-radius: 50px;
            text-align: center;
            border: 3px solid cyan;
            z-index: 300;
            min-width: 280px;
            backdrop-filter: blur(20px);
        }

        .hidden {
            display: none;
        }

        @media (max-width: 700px) {
            .upgrade-panel { display: none; }
            .stat-card div { font-size: 1rem; }
            .hearts { font-size: 1.2rem; }
        }
    </style>
</head>
<body>
<div class="game-wrapper">
    <div class="hud">
        <div class="stat-card">🔫 <span>امتیاز</span><div id="scoreVal">0</div></div>
        <div class="stat-card">🏆 <span>رکورد</span><div id="highScoreVal">0</div></div>
        <div class="hearts" id="heartsDisplay">❤️ ❤️ ❤️ ❤️ ❤️</div>
        <div class="stat-card">⚡ <span>نابودی</span><div id="killCountVal">0</div></div>
        <div class="stat-card">💰 <span>اعتبار</span><div id="moneyVal">0</div></div>
    </div>
    
    <canvas id="gameCanvas" width="800" height="550"></canvas>
    
    <div style="display: flex; gap: 10px; margin-top: 12px; justify-content: center;">
        <button id="restartGameBtn">🌌 بازی جدید</button>
        <button id="toggleUpgradeBtn" style="background: linear-gradient(135deg, #f0a500, #f08000);">⭐ ارتقاها</button>
    </div>
    
    <div class="upgrade-panel hidden" id="upgradePanel">
        <h4>⭐ فروشگاه کهکشانی</h4>
        <div class="upgrade-item">⚡ قدرت شلیک <button id="upgradeDmg">+ (💰50)</button></div>
        <div class="upgrade-item">💨 سرعت شلیک <button id="upgradeSpeed">+ (💰80)</button></div>
        <div class="upgrade-item">❤️ جان اضافه <button id="upgradeLife">+ (💰120)</button></div>
        <div class="upgrade-item">💀 بحرانی <button id="upgradeCrit">+ (💰100)</button></div>
        <div style="margin-top:10px; font-size:0.7rem; color:cyan;">هر آپگرید 10% قوی‌تر</div>
    </div>
    
    <div id="gameOverModal" class="game-over-modal hidden">
        <h2>💀 GAME OVER 💀</h2>
        <p id="finalStats"></p>
        <button id="playAgainModalBtn">🔥 بازی دوباره</button>
    </div>
</div>

<script>
    const canvas = document.getElementById('gameCanvas');
    const ctx = canvas.getContext('2d');
    
    canvas.width = 800;
    canvas.height = 550;
    
    // ========== وضعیت بازی ==========
    let gameRunning = true;
    let animationId;
    
    // بازیکن
    let player = {
        x: canvas.width/2,
        y: canvas.height - 60,
        radius: 18,
        lives: 5,
        maxLives: 5
    };
    
    // آمار
    let score = 0;
    let highScore = localStorage.getItem('cmbGalaxyHigh') ? parseInt(localStorage.getItem('cmbGalaxyHigh')) : 0;
    let killCount = 0;
    let money = 0;
    
    // آپگریدها (به درصد)
    let upgrades = {
        damage: 1.0,    // ضریب آسیب
        fireRate: 1.0,  // سرعت شلیک
        critChance: 0.1,// شانس بحرانی
        extraLives: 0
    };
    
    // ارتقا هزینه‌ها
    let upgradeCost = { dmg: 50, speed: 80, life: 120, crit: 100 };
    
    // دشمنان
    let enemies = [];
    let bullets = [];
    let particles = [];
    let explosions = [];
    
    let lastShot = 0;
    let shootDelay = 250; // ms
    
    // باس فایت
    let boss = null;
    let bossActive = false;
    let nextBossScore = 200;
    
    // ستاره‌ها
    let stars = [];
    for(let i=0;i<200;i++) stars.push({ x:Math.random()*canvas.width, y:Math.random()*canvas.height, size:1+Math.random()*2 });
    
    // المان‌ها
    const scoreVal = document.getElementById('scoreVal');
    const highScoreVal = document.getElementById('highScoreVal');
    const heartsDisplay = document.getElementById('heartsDisplay');
    const killCountVal = document.getElementById('killCountVal');
    const moneyVal = document.getElementById('moneyVal');
    const restartBtn = document.getElementById('restartGameBtn');
    const toggleUpgradeBtn = document.getElementById('toggleUpgradeBtn');
    const upgradePanel = document.getElementById('upgradePanel');
    const gameOverModal = document.getElementById('gameOverModal');
    const playAgainModalBtn = document.getElementById('playAgainModalBtn');
    const finalStats = document.getElementById('finalStats');
    
    highScoreVal.innerText = highScore;
    
    // ========== کلاس دشمن ==========
    class Enemy {
        constructor(x, y, type, hp = 1) {
            this.x = x;
            this.y = y;
            this.type = type; // normal, fast, tank
            this.radius = 22;
            this.hp = hp;
            this.maxHp = hp;
            this.speedY = 1.2 + Math.random() * 1.5;
            this.speedX = (Math.random() - 0.5) * 0.8;
            if(type === 'fast') { this.speedY = 2.5; this.hp = 1; this.radius = 16; }
            if(type === 'tank') { this.speedY = 0.7; this.hp = 3; this.radius = 30; }
        }
        
        update() {
            this.y += this.speedY;
            this.x += this.speedX;
            if(this.x - this.radius < 0) this.x = this.radius;
            if(this.x + this.radius > canvas.width) this.x = canvas.width - this.radius;
            return this.y + this.radius > canvas.height;
        }
        
        draw() {
            const gradient = ctx.createRadialGradient(this.x-5, this.y-5, 5, this.x, this.y, this.radius);
            if(this.type === 'fast') gradient.addColorStop(0, '#ff8844'), gradient.addColorStop(1, '#dd2200');
            else if(this.type === 'tank') gradient.addColorStop(0, '#8855cc'), gradient.addColorStop(1, '#441188');
            else gradient.addColorStop(0, '#44aaff'), gradient.addColorStop(1, '#1155aa');
            ctx.beginPath();
            ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2);
            ctx.fillStyle = gradient;
            ctx.fill();
            ctx.fillStyle = 'white';
            ctx.font = "bold 16px monospace";
            let icon = this.type === 'fast' ? '⚡' : (this.type === 'tank' ? '🛡️' : '👾');
            ctx.fillText(icon, this.x-12, this.y+8);
            if(this.hp > 1) {
                ctx.fillStyle = 'red';
                ctx.fillRect(this.x-15, this.y-18, 30, 5);
                ctx.fillStyle = '#0f0';
                ctx.fillRect(this.x-15, this.y-18, 30 * (this.hp/this.maxHp), 5);
            }
        }
        
        takeDamage(amount) {
            let finalDmg = amount * upgrades.damage;
            if(Math.random() < upgrades.critChance) {
                finalDmg *= 2;
                this.showDamage((finalDmg).toFixed(0), true);
            } else this.showDamage(finalDmg.toFixed(0), false);
            this.hp -= finalDmg;
            return this.hp <= 0;
        }
        
        showDamage(dmg, isCrit) {
            const div = document.createElement('div');
            div.className = 'damage-number';
            div.innerText = isCrit ? `💥 ${dmg} CRIT!` : `${dmg}`;
            div.style.color = isCrit ? '#ffaa00' : '#ff6666';
            div.style.left = (this.x + canvas.getBoundingClientRect().left) + 'px';
            div.style.top = (this.y + canvas.getBoundingClientRect().top) + 'px';
            div.style.position = 'fixed';
            document.body.appendChild(div);
            setTimeout(() => div.remove(), 500);
        }
    }
    
    // گلوله
    class Bullet {
        constructor(x, y) {
            this.x = x;
            this.y = y;
            this.radius = 5;
            this.speed = -6;
        }
        update() {
            this.y += this.speed;
            return this.y + this.radius < 0;
        }
        draw() {
            ctx.fillStyle = '#ffff00';
            ctx.shadowBlur = 10;
            ctx.beginPath();
            ctx.arc(this.x, this.y, 5, 0, Math.PI*2);
            ctx.fill();
            ctx.fillStyle = 'orange';
            ctx.beginPath();
            ctx.arc(this.x, this.y, 3, 0, Math.PI*2);
            ctx.fill();
            ctx.shadowBlur = 0;
        }
    }
    
    // پارتیکل انفجار
    function addExplosion(x,y) {
        for(let i=0;i<8;i++) particles.push({ x:x+ (Math.random()-0.5)*15, y:y+ (Math.random()-0.5)*15, life:1, size:3+Math.random()*4 });
    }
    
    // حرکت سفینه با موس/لمس
    function movePlayer(e) {
        if(!gameRunning) return;
        const rect = canvas.getBoundingClientRect();
        const scaleX = canvas.width / rect.width;
        let clientX;
        if(e.touches) clientX = e.touches[0].clientX;
        else clientX = e.clientX;
        let canvasX = (clientX - rect.left) * scaleX;
        canvasX = Math.min(Math.max(canvasX, player.radius+10), canvas.width - player.radius-10);
        player.x = canvasX;
    }
    
    // شلیک
    function shoot() {
        if(!gameRunning) return;
        let now = Date.now();
        let delay = shootDelay / upgrades.fireRate;
        if(now - lastShot > delay) {
            bullets.push(new Bullet(player.x, player.y-10));
            lastShot = now;
        }
    }
    
    // اسپاون دشمن
    function spawnEnemy() {
        if(!gameRunning) return;
        if(bossActive) return;
        let rand = Math.random();
        let type = 'normal';
        if(score > 300) type = rand<0.4 ? 'normal' : (rand<0.7 ? 'fast' : 'tank');
        else if(score > 100) type = rand<0.6 ? 'normal' : (rand<0.8 ? 'fast' : 'tank');
        let hp = (type === 'tank') ? 2 + Math.floor(score/300) : 1;
        let enemy = new Enemy(30 + Math.random()*(canvas.width-60), -30, type, hp);
        enemies.push(enemy);
    }
    
    // آپدیت بازی
    function updateGame() {
        if(!gameRunning) return;
        
        // اسپاون اتوماتیک
        if(Math.random() < 0.02 + score/5000 && enemies.length < 12 && !bossActive) spawnEnemy();
        
        // باس فایت
        if(score >= nextBossScore && !bossActive && !boss) {
            bossActive = true;
            boss = { x: canvas.width/2, y: 70, radius: 45, hp: 25 + Math.floor(score/50), maxHp: 25 + Math.floor(score/50), type: 'boss', moveDir: 1 };
            enemies = enemies.filter(e => e.y < canvas.height-100);
        }
        
        // آپدیت دشمنان
        for(let i=0;i<enemies.length;i++) {
            let isOut = enemies[i].update();
            if(isOut) { enemies.splice(i,1); i--; continue; }
            // برخورد با بازیکن
            let dist = Math.hypot(player.x - enemies[i].x, player.y - enemies[i].y);
            if(dist < player.radius + enemies[i].radius) {
                player.lives--;
                addExplosion(player.x, player.y);
                updateHearts();
                enemies.splice(i,1);
                if(player.lives <= 0) endGame();
                i--;
            }
        }
        
        // آپدیت باس
        if(boss) {
            boss.x += 2 * boss.moveDir;
            if(boss.x - boss.radius < 20) boss.moveDir = 1;
            if(boss.x + boss.radius > canvas.width-20) boss.moveDir = -1;
            ctx.beginPath();
            ctx.arc(boss.x, boss.y, boss.radius, 0, Math.PI*2);
            ctx.fillStyle = '#aa33ff';
            ctx.fill();
            ctx.fillStyle = 'white';
            ctx.font = "bold 20px monospace";
            ctx.fillText('👾 BOSS', boss.x-40, boss.y-10);
            ctx.fillStyle = 'red';
            ctx.fillRect(boss.x-50, boss.y-35, 100, 10);
            ctx.fillStyle = 'lime';
            ctx.fillRect(boss.x-50, boss.y-35, 100 * (boss.hp/boss.maxHp), 10);
            
            // برخورد باس با بازیکن
            if(Math.hypot(player.x - boss.x, player.y - boss.y) < player.radius + boss.radius) {
                player.lives -= 2;
                updateHearts();
                if(player.lives <= 0) endGame();
                boss.hp -= 5;
                addExplosion(boss.x, boss.y);
            }
        }
        
        // گلوله‌ها و برخورد
        for(let i=0;i<bullets.length;i++) {
            if(bullets[i].update()) { bullets.splice(i,1); i--; continue; }
            let hit = false;
            // برخورد با دشمنان
            for(let j=0;j<enemies.length;j++) {
                if(Math.hypot(bullets[i].x - enemies[j].x, bullets[i].y - enemies[j].y) < bullets[i].radius + enemies[j].radius) {
                    let dead = enemies[j].takeDamage(10);
                    bullets.splice(i,1);
                    if(dead) {
                        let reward = 10 + (enemies[j].type === 'tank' ? 15 : 0);
                        score += reward;
                        money += reward;
                        killCount++;
                        addExplosion(enemies[j].x, enemies[j].y);
                        enemies.splice(j,1);
                        updateUI();
                    }
                    hit = true;
                    break;
                }
            }
            if(hit) { i--; continue; }
            // برخورد با باس
            if(boss && Math.hypot(bullets[i].x - boss.x, bullets[i].y - boss.y) < bullets[i].radius + boss.radius) {
                let dmg = 12;
                boss.hp -= dmg * upgrades.damage;
                bullets.splice(i,1);
                if(boss.hp <= 0) {
                    let bonus = 100;
                    score += bonus;
                    money += bonus;
                    boss = null;
                    bossActive = false;
                    nextBossScore = score + 200;
                    addExplosion(boss.x, boss.y);
                    updateUI();
                }
                i--;
            }
        }
        
        // پارتیکل‌ها
        for(let i=0;i<particles.length;i++) {
            particles[i].life -= 0.05;
            if(particles[i].life <= 0) particles.splice(i,1);
        }
        
        // آپدیت UI
        if(score > highScore) { highScore = score; localStorage.setItem('cmbGalaxyHigh', highScore); highScoreVal.innerText = highScore; }
        scoreVal.innerText = score;
        moneyVal.innerText = money;
        killCountVal.innerText = killCount;
    }
    
    function updateHearts() {
        let str = '';
        for(let i=0;i<player.lives;i++) str += '❤️ ';
        for(let i=player.lives;i<player.maxLives+upgrades.extraLives;i++) str += '🖤 ';
        heartsDisplay.innerHTML = str;
    }
    
    function updateUI() {
        scoreVal.innerText = score;
        moneyVal.innerText = money;
        killCountVal.innerText = killCount;
        if(score > highScore) { highScore = score; highScoreVal.innerText = highScore; localStorage.setItem('cmbGalaxyHigh', highScore); }
        updateHearts();
    }
    
    function draw() {
        ctx.clearRect(0,0,canvas.width,canvas.height);
        // ستاره‌ها
        for(let s of stars) { ctx.fillStyle = `rgba(255,255,200,${0.5+Math.random()*0.5})`; ctx.fillRect(s.x,s.y,s.size,s.size); }
        // سفینه بازیکن
        ctx.shadowBlur = 12;
        ctx.fillStyle = '#00ccff';
        ctx.beginPath();
        ctx.moveTo(player.x, player.y-18);
        ctx.lineTo(player.x-18, player.y+8);
        ctx.lineTo(player.x-8, player.y+4);
        ctx.lineTo(player.x-8, player.y+14);
        ctx.lineTo(player.x, player.y+10);
        ctx.lineTo(player.x+8, player.y+14);
        ctx.lineTo(player.x+8, player.y+4);
        ctx.lineTo(player.x+18, player.y+8);
        ctx.fill();
        ctx.fillStyle = '#ffffff';
        ctx.beginPath();
        ctx.arc(player.x, player.y-6, 5, 0, Math.PI*2);
        ctx.fill();
        ctx.shadowBlur = 0;
        
        for(let b of bullets) b.draw();
        for(let e of enemies) e.draw();
        for(let p of particles) { ctx.fillStyle = `rgba(255,100,0,${p.life})`; ctx.fillRect(p.x,p.y,p.size,p.size); }
        if(boss) {}
        ctx.font = "bold 14px Orbitron";
        ctx.fillStyle = "#aaffff";
        ctx.fillText("🔫 هدف‌گیری اتوماتیک → حرکت کن و شلیک کن", 20, 40);
    }
    
    let spawnInterval;
    function startGameLoop() {
        if(spawnInterval) clearInterval(spawnInterval);
        spawnInterval = setInterval(() => { if(gameRunning && !bossActive) spawnEnemy(); }, 1000);
        function frame() {
            if(!gameRunning) return;
            updateGame();
            draw();
            requestAnimationFrame(frame);
        }
        frame();
    }
    
    function endGame() {
        gameRunning = false;
        if(spawnInterval) clearInterval(spawnInterval);
        finalStats.innerText = `امتیاز: ${score}\nنابودی: ${killCount}\nباس‌ها: ${Math.floor(score/200)}`;
        gameOverModal.classList.remove('hidden');
    }
    
    function restart() {
        gameRunning = true;
        score = 0;
        killCount = 0;
        money = 0;
        player.lives = 5 + upgrades.extraLives;
        player.maxLives = 5 + upgrades.extraLives;
        enemies = [];
        bullets = [];
        particles = [];
        boss = null;
        bossActive = false;
        nextBossScore = 200;
        updateUI();
        gameOverModal.classList.add('hidden');
        if(spawnInterval) clearInterval(spawnInterval);
        spawnInterval = setInterval(() => { if(gameRunning && !bossActive) spawnEnemy(); }, 1000);
    }
    
    // ارتقاها
    function upgradeDamage() { if(money>=upgradeCost.dmg) { money-=upgradeCost.dmg; upgrades.damage += 0.15; upgradeCost.dmg = Math.floor(upgradeCost.dmg * 1.4); moneyVal.innerText=money; } }
    function upgradeFireSpeed() { if(money>=upgradeCost.speed) { money-=upgradeCost.speed; upgrades.fireRate += 0.2; upgradeCost.speed = Math.floor(upgradeCost.speed * 1.4); moneyVal.innerText=money; } }
    function upgradeLife() { if(money>=upgradeCost.life) { money-=upgradeCost.life; upgrades.extraLives++; player.maxLives = 5+upgrades.extraLives; player.lives = player.maxLives; upgradeCost.life = Math.floor(upgradeCost.life * 1.5); updateHearts(); moneyVal.innerText=money; } }
    function upgradeCrit() { if(money>=upgradeCost.crit) { money-=upgradeCost.crit; upgrades.critChance = Math.min(0.55, upgrades.critChance+0.07); upgradeCost.crit = Math.floor(upgradeCost.crit * 1.4); moneyVal.innerText=money; } }
    
    document.getElementById('upgradeDmg').onclick = upgradeDamage;
    document.getElementById('upgradeSpeed').onclick = upgradeFireSpeed;
    document.getElementById('upgradeLife').onclick = upgradeLife;
    document.getElementById('upgradeCrit').onclick = upgradeCrit;
    
    canvas.addEventListener('mousemove', movePlayer);
    canvas.addEventListener('touchmove', movePlayer);
    canvas.addEventListener('click', () => shoot());
    canvas.addEventListener('touchstart', (e) => { e.preventDefault(); shoot(); });
    restartBtn.onclick = () => restart();
    playAgainModalBtn.onclick = () => restart();
    toggleUpgradeBtn.onclick = () => upgradePanel.classList.toggle('hidden');
    
    setInterval(() => { if(gameRunning) shoot(); }, 100);
    startGameLoop();
    updateHearts();
</script>
</body>
</html>

Game Source: 🌌 CMB GALAXY WAR - نبرد کهکشانی تابش زمینه

Creator: ElectricCobra60

Libraries: none

Complexity: complex (638 lines, 23.1 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: cmb-galaxy-war-electriccobra60" to link back to the original. Then publish at arcadelab.ai/publish.