/* DSES CZ原创水印 */
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>霓虹突围 - HTML5 枪战游戏</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap');

        body {
            margin: 0;
            overflow: hidden;
            background-color: #0f172a;
            font-family: 'Orbitron', sans-serif;
            user-select: none;
        }

        #game-container {
            position: relative;
            width: 100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        canvas {
            box-shadow: 0 0 50px rgba(0, 255, 255, 0.1);
            border: 2px solid #334155;
            background: radial-gradient(circle at center, #1e293b 0%, #0f172a 100%);
            cursor: crosshair;
        }

        .ui-layer {
            position: absolute;
            pointer-events: none;
            width: 100%;
            height: 100%;
            top: 0;
            left: 0;
        }

        .hud-panel {
            pointer-events: auto;
            backdrop-filter: blur(4px);
            background: rgba(15, 23, 42, 0.8);
            border: 1px solid rgba(56, 189, 248, 0.3);
            box-shadow: 0 0 15px rgba(56, 189, 248, 0.1);
        }

        .health-bar-fill {
            transition: width 0.2s ease-out, background-color 0.2s;
        }

        /* 动画效果 */
        @keyframes pulse-red {
            0% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4); }
            70% { box-shadow: 0 0 0 10px rgba(239, 68, 68, 0); }
            100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0); }
        }

        .damage-effect {
            animation: pulse-red 0.5s infinite;
        }

        .hidden { display: none !important; }
        
        /* 准星样式 */
        #crosshair {
            position: fixed;
            pointer-events: none;
            z-index: 50;
            transform: translate(-50%, -50%);
            mix-blend-mode: difference;
        }
    </style>
</head>
<body>

<div id="game-container">
    <canvas id="gameCanvas"></canvas>
    
    <!-- 准星 -->
    <div id="crosshair">
        <svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
            <circle cx="20" cy="20" r="18" stroke="#0ea5e9" stroke-width="2" stroke-opacity="0.8"/>
            <circle cx="20" cy="20" r="2" fill="#0ea5e9"/>
            <line x1="20" y1="5" x2="20" y2="12" stroke="#0ea5e9" stroke-width="2"/>
            <line x1="20" y1="28" x2="20" y2="35" stroke="#0ea5e9" stroke-width="2"/>
            <line x1="5" y1="20" x2="12" y2="20" stroke="#0ea5e9" stroke-width="2"/>
            <line x1="28" y1="20" x2="35" y2="20" stroke="#0ea5e9" stroke-width="2"/>
        </svg>
    </div>

    <!-- UI 层 -->
    <div class="ui-layer flex flex-col justify-between p-6">
        <!-- 顶部 HUD -->
        <div class="flex justify-between items-start w-full max-w-6xl mx-auto">
            <div class="hud-panel rounded-lg p-4 flex flex-col gap-2 min-w-[200px]">
                <div class="flex justify-between text-cyan-400 text-sm font-bold tracking-wider">
                    <span>HP</span>
                    <span id="hp-text">100/100</span>
                </div>
                <div class="w-full h-3 bg-slate-700 rounded-full overflow-hidden">
                    <div id="health-bar" class="health-bar-fill h-full bg-gradient-to-r from-cyan-500 to-blue-600 w-full"></div>
                </div>
                <div class="flex justify-between text-yellow-400 text-xs mt-1">
                    <span>SCORE</span>
                    <span id="score-text" class="font-mono text-lg">0</span>
                </div>
            </div>

            <div class="hud-panel rounded-lg p-3 text-right">
                <div class="text-slate-400 text-xs uppercase tracking-widest mb-1">Wave</div>
                <div id="wave-text" class="text-2xl font-bold text-white">1</div>
            </div>
        </div>

        <!-- 底部 HUD -->
        <div class="flex justify-between items-end w-full max-w-6xl mx-auto">
            <div class="hud-panel rounded-lg p-3 text-slate-300 text-xs">
                <div class="flex items-center gap-2 mb-1"><i class="fas fa-keyboard text-cyan-500"></i> WASD 移动</div>
                <div class="flex items-center gap-2"><i class="fas fa-mouse text-cyan-500"></i> 鼠标瞄准/射击</div>
                <div class="flex items-center gap-2 mt-1"><i class="fas fa-r text-cyan-500"></i> R 换弹</div>
            </div>
            
            <div class="hud-panel rounded-lg p-4 flex flex-col items-end">
                <div class="text-slate-400 text-xs uppercase tracking-widest mb-1">Ammo</div>
                <div class="flex items-baseline gap-2">
                    <span id="ammo-current" class="text-4xl font-bold text-white font-mono">20</span>
                    <span class="text-slate-500 text-xl">/</span>
                    <span id="ammo-reserve" class="text-xl text-slate-400 font-mono">∞</span>
                </div>
                <div id="reload-indicator" class="hidden text-yellow-400 text-xs font-bold animate-pulse mt-1">RELOADING...</div>
            </div>
        </div>
    </div>

    <!-- 开始/结束 菜单 -->
    <div id="menu-overlay" class="absolute inset-0 bg-slate-900/90 backdrop-blur-sm flex items-center justify-center z-50">
        <div class="bg-slate-800 border border-cyan-500/30 p-8 rounded-2xl shadow-2xl max-w-md w-full text-center relative overflow-hidden">
            <div class="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-transparent via-cyan-500 to-transparent"></div>
            
            <h1 class="text-5xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 to-blue-600 mb-2 tracking-tighter">NEON STRIKE</h1>
            <p class="text-slate-400 mb-8 text-sm">生存下去,消灭所有威胁</p>
            
            <div id="start-screen">
                <button id="start-btn" class="w-full py-4 bg-cyan-600 hover:bg-cyan-500 text-white font-bold rounded-lg transition-all transform hover:scale-105 shadow-lg shadow-cyan-500/20 mb-4 group">
                    <i class="fas fa-play mr-2 group-hover:animate-pulse"></i> 开始游戏
                </button>
                <div class="text-xs text-slate-500 mt-4">最高分: <span id="high-score-display" class="text-cyan-400">0</span></div>
            </div>

            <div id="game-over-screen" class="hidden">
                <div class="text-red-500 text-6xl mb-2"><i class="fas fa-skull"></i></div>
                <h2 class="text-3xl text-white font-bold mb-2">任务失败</h2>
                <p class="text-slate-300 mb-6">最终得分: <span id="final-score" class="text-yellow-400 font-mono text-xl">0</span></p>
                <button id="restart-btn" class="w-full py-4 bg-slate-700 hover:bg-slate-600 text-white font-bold rounded-lg transition-all border border-slate-600 hover:border-cyan-500">
                    <i class="fas fa-redo mr-2"></i> 再次挑战
                </button>
            </div>
        </div>
    </div>
</div>

<script>
/**
 * 游戏核心逻辑
 * 采用 Canvas API 进行渲染,RequestAnimationFrame 驱动循环
 */

// --- 配置与常量 ---
const CONFIG = {
    PLAYER_SPEED: 4,
    PLAYER_HP: 100,
    BULLET_SPEED: 12,
    ENEMY_BASE_SPEED: 1.5,
    FIRE_RATE: 150, // ms
    RELOAD_TIME: 1500, // ms
    MAG_SIZE: 20,
    COLORS: {
        PLAYER: '#0ea5e9', // Sky 500
        ENEMY: '#ef4444',  // Red 500
        BULLET: '#facc15', // Yellow 400
        PARTICLE: ['#facc15', '#f87171', '#ffffff']
    }
};

// --- 游戏状态管理 ---
const state = {
    isPlaying: false,
    score: 0,
    wave: 1,
    lastTime: 0,
    keys: {},
    mouse: { x: 0, y: 0, down: false },
    camera: { x: 0, y: 0 },
    entities: {
        player: null,
        bullets: [],
        enemies: [],
        particles: [],
        texts: []
    },
    stats: {
        hp: CONFIG.PLAYER_HP,
        ammo: CONFIG.MAG_SIZE,
        isReloading: false,
        lastShot: 0
    }
};

// --- DOM 元素 ---
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const ui = {
    hpBar: document.getElementById('health-bar'),
    hpText: document.getElementById('hp-text'),
    score: document.getElementById('score-text'),
    wave: document.getElementById('wave-text'),
    ammoCur: document.getElementById('ammo-current'),
    ammoRes: document.getElementById('ammo-reserve'),
    reloadInd: document.getElementById('reload-indicator'),
    menu: document.getElementById('menu-overlay'),
    startScreen: document.getElementById('start-screen'),
    gameOverScreen: document.getElementById('game-over-screen'),
    finalScore: document.getElementById('final-score'),
    highScore: document.getElementById('high-score-display'),
    crosshair: document.getElementById('crosshair')
};

// --- 初始化 Canvas ---
function resize() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
}
window.addEventListener('resize', resize);
resize();

// --- 输入处理 ---
window.addEventListener('keydown', e => {
    state.keys[e.code] = true;
    if (e.code === 'KeyR' && state.isPlaying) reloadWeapon();
});
window.addEventListener('keyup', e => state.keys[e.code] = false);
window.addEventListener('mousemove', e => {
    state.mouse.x = e.clientX;
    state.mouse.y = e.clientY;
    // 更新自定义准星位置
    ui.crosshair.style.left = e.clientX + 'px';
    ui.crosshair.style.top = e.clientY + 'px';
});
window.addEventListener('mousedown', () => state.mouse.down = true);
window.addEventListener('mouseup', () => state.mouse.down = false);

// --- 类定义 ---

class Player {
    constructor() {
        this.x = canvas.width / 2;
        this.y = canvas.height / 2;
        this.radius = 15;
        this.angle = 0;
    }

    update(dt) {
        // 移动
        let dx = 0, dy = 0;
        if (state.keys['KeyW'] || state.keys['ArrowUp']) dy -= 1;
        if (state.keys['KeyS'] || state.keys['ArrowDown']) dy += 1;
        if (state.keys['KeyA'] || state.keys['ArrowLeft']) dx -= 1;
        if (state.keys['KeyD'] || state.keys['ArrowRight']) dx += 1;

        // 归一化向量
        if (dx !== 0 || dy !== 0) {
            const len = Math.sqrt(dx*dx + dy*dy);
            dx /= len;
            dy /= len;
            this.x += dx * CONFIG.PLAYER_SPEED;
            this.y += dy * CONFIG.PLAYER_SPEED;
        }

        // 边界限制
        this.x = Math.max(this.radius, Math.min(canvas.width - this.radius, this.x));
        this.y = Math.max(this.radius, Math.min(canvas.height - this.radius, this.y));

        // 计算朝向角度
        this.angle = Math.atan2(state.mouse.y - this.y, state.mouse.x - this.x);

        // 射击逻辑
        if (state.mouse.down && !state.stats.isReloading && state.stats.ammo > 0) {
            const now = Date.now();
            if (now - state.stats.lastShot > CONFIG.FIRE_RATE) {
                shoot();
                state.stats.lastShot = now;
            }
        } else if (state.mouse.down && state.stats.ammo <= 0 && !state.stats.isReloading) {
            reloadWeapon();
        }
    }

    draw() {
        ctx.save();
        ctx.translate(this.x, this.y);
        ctx.rotate(this.angle);

        // 身体
        ctx.beginPath();
        ctx.arc(0, 0, this.radius, 0, Math.PI * 2);
        ctx.fillStyle = CONFIG.COLORS.PLAYER;
        ctx.fill();
        ctx.shadowBlur = 15;
        ctx.shadowColor = CONFIG.COLORS.PLAYER;
        ctx.fill();
        ctx.shadowBlur = 0;

        // 枪管
        ctx.fillStyle = '#334155';
        ctx.fillRect(0, -5, 25, 10);

        ctx.restore();
    }
}

class Bullet {
    constructor(x, y, angle) {
        this.x = x;
        this.y = y;
        this.vx = Math.cos(angle) * CONFIG.BULLET_SPEED;
        this.vy = Math.sin(angle) * CONFIG.BULLET_SPEED;
        this.radius = 3;
        this.active = true;
    }

    update() {
        this.x += this.vx;
        this.y += this.vy;

        // 出界移除
        if (this.x < 0 || this.x > canvas.width || this.y < 0 || this.y > canvas.height) {
            this.active = false;
        }
    }

    draw() {
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
        ctx.fillStyle = CONFIG.COLORS.BULLET;
        ctx.fill();
        
        // 拖尾效果
        ctx.beginPath();
        ctx.moveTo(this.x, this.y);
        ctx.lineTo(this.x - this.vx * 2, this.y - this.vy * 2);
        ctx.strokeStyle = `rgba(250, 204, 21, 0.3)`;
        ctx.lineWidth = 2;
        ctx.stroke();
    }
}

class Enemy {
    constructor(wave) {
        // 随机生成在屏幕边缘外
        const side = Math.floor(Math.random() * 4);
        if (side === 0) { this.x = Math.random() * canvas.width; this.y = -30; } // Top
        else if (side === 1) { this.x = canvas.width + 30; this.y = Math.random() * canvas.height; } // Right
        else if (side === 2) { this.x = Math.random() * canvas.width; this.y = canvas.height + 30; } // Bottom
        else { this.x = -30; this.y = Math.random() * canvas.height; } // Left

        this.radius = 12 + Math.random() * 8;
        this.speed = CONFIG.ENEMY_BASE_SPEED + (wave * 0.1) + Math.random();
        this.hp = 1 + Math.floor(wave / 3);
        this.active = true;
        this.color = CONFIG.COLORS.ENEMY;
    }

    update(player) {
        const angle = Math.atan2(player.y - this.y, player.x - this.x);
        this.x += Math.cos(angle) * this.speed;
        this.y += Math.sin(angle) * this.speed;
    }

    draw() {
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
        ctx.fillStyle = this.color;
        ctx.fill();
        
        // 简单的眼睛指示方向
        /*
        ctx.fillStyle = 'black';
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.radius/2, 0, Math.PI*2);
        ctx.fill();
        */
    }
}

class Particle {
    constructor(x, y, color) {
        this.x = x;
        this.y = y;
        const angle = Math.random() * Math.PI * 2;
        const speed = Math.random() * 3 + 1;
        this.vx = Math.cos(angle) * speed;
        this.vy = Math.sin(angle) * speed;
        this.life = 1.0;
        this.decay = Math.random() * 0.03 + 0.02;
        this.color = color;
        this.size = Math.random() * 3 + 1;
    }

    update() {
        this.x += this.vx;
        this.y += this.vy;
        this.life -= this.decay;
    }

    draw() {
        ctx.globalAlpha = this.life;
        ctx.fillStyle = this.color;
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
        ctx.fill();
        ctx.globalAlpha = 1.0;
    }
}

class FloatingText {
    constructor(x, y, text, color) {
        this.x = x;
        this.y = y;
        this.text = text;
        this.color = color;
        this.life = 1.0;
        this.vy = -1;
    }
    update() {
        this.y += this.vy;
        this.life -= 0.02;
    }
    draw() {
        ctx.globalAlpha = this.life;
        ctx.fillStyle = this.color;
        ctx.font = "bold 16px Orbitron";
        ctx.fillText(this.text, this.x, this.y);
        ctx.globalAlpha = 1.0;
    }
}

// --- 游戏功能函数 ---

function initGame() {
    state.entities.player = new Player();
    state.entities.bullets = [];
    state.entities.enemies = [];
    state.entities.particles = [];
    state.entities.texts = [];
    state.score = 0;
    state.wave = 1;
    state.stats.hp = CONFIG.PLAYER_HP;
    state.stats.ammo = CONFIG.MAG_SIZE;
    state.stats.isReloading = false;
    state.isPlaying = true;
    
    updateUI();
    ui.menu.classList.add('hidden');
    ui.startScreen.classList.add('hidden');
    ui.gameOverScreen.classList.add('hidden');
    
    // 启动敌人生成器
    spawnEnemyLoop();
    
    requestAnimationFrame(gameLoop);
}

function gameOver() {
    state.isPlaying = false;
    ui.menu.classList.remove('hidden');
    ui.gameOverScreen.classList.remove('hidden');
    ui.finalScore.innerText = state.score;
    
    // 更新最高分
    const highScore = localStorage.getItem('neonStrikeHighScore') || 0;
    if (state.score > highScore) {
        localStorage.setItem('neonStrikeHighScore', state.score);
        ui.highScore.innerText = state.score;
    }
}

function shoot() {
    if (state.stats.ammo > 0) {
        state.stats.ammo--;
        // 枪口位置
        const p = state.entities.player;
        const muzzleDist = 25;
        const bx = p.x + Math.cos(p.angle) * muzzleDist;
        const by = p.y + Math.sin(p.angle) * muzzleDist;
        
        // 添加后坐力抖动
        state.camera.x = (Math.random() - 0.5) * 4;
        state.camera.y = (Math.random() - 0.5) * 4;
        setTimeout(() => { state.camera.x = 0; state.camera.y = 0; }, 50);

        state.entities.bullets.push(new Bullet(bx, by, p.angle + (Math.random()-0.5)*0.1)); // 轻微散射
        updateUI();
    }
}

function reloadWeapon() {
    if (state.stats.isReloading || state.stats.ammo === CONFIG.MAG_SIZE) return;
    state.stats.isReloading = true;
    ui.reloadInd.classList.remove('hidden');
    
    setTimeout(() => {
        state.stats.ammo = CONFIG.MAG_SIZE;
        state.stats.isReloading = false;
        ui.reloadInd.classList.add('hidden');
        updateUI();
    }, CONFIG.RELOAD_TIME);
}

let enemySpawnTimer = null;
function spawnEnemyLoop() {
    if (!state.isPlaying) return;
    
    // 随着波次增加,生成速度加快
    const spawnRate = Math.max(500, 2000 - (state.wave * 100));
    
    state.entities.enemies.push(new Enemy(state.wave));
    
    enemySpawnTimer = setTimeout(spawnEnemyLoop, spawnRate);
}

function createExplosion(x, y, count = 8) {
    for(let i=0; i<count; i++) {
        state.entities.particles.push(new Particle(x, y, CONFIG.COLORS.PARTICLE[Math.floor(Math.random()*CONFIG.COLORS.PARTICLE.length)]));
    }
}

function checkCollisions() {
    const player = state.entities.player;
    const bullets = state.entities.bullets;
    const enemies = state.entities.enemies;

    // 子弹击中敌人
    for (let i = bullets.length - 1; i >= 0; i--) {
        const b = bullets[i];
        let hit = false;
        for (let j = enemies.length - 1; j >= 0; j--) {
            const e = enemies[j];
            const dist = Math.hypot(b.x - e.x, b.y - e.y);
            if (dist < e.radius + b.radius) {
                // 击中
                e.hp--;
                hit = true;
                createExplosion(b.x, b.y, 3);
                if (e.hp <= 0) {
                    e.active = false;
                    state.score += 10 * state.wave;
                    createExplosion(e.x, e.y, 10);
                    state.entities.texts.push(new FloatingText(e.x, e.y, "+" + (10*state.wave), "#facc15"));
                    
                    // 波次逻辑:每100分升一波
                    if (state.score > state.wave * 100) {
                        state.wave++;
                        state.entities.texts.push(new FloatingText(canvas.width/2, canvas.height/2 - 50, "WAVE " + state.wave, "#0ea5e9"));
                        // 回血奖励
                        state.stats.hp = Math.min(CONFIG.PLAYER_HP, state.stats.hp + 10);
                    }
                }
                break; 
            }
        }
        if (hit) b.active = false;
    }

    // 敌人接触玩家
    for (let e of enemies) {
        const dist = Math.hypot(player.x - e.x, player.y - e.y);
        if (dist < player.radius + e.radius) {
            state.stats.hp -= 1; // 持续伤害
            createExplosion((player.x+e.x)/2, (player.y+e.y)/2, 1);
            // 屏幕红闪
            document.body.classList.add('damage-effect');
            setTimeout(() => document.body.classList.remove('damage-effect'), 200);
            
            if (state.stats.hp <= 0) {
                gameOver();
            }
        }
    }
}

function updateUI() {
    ui.hpText.innerText = `${Math.ceil(state.stats.hp)}/${CONFIG.PLAYER_HP}`;
    ui.hpBar.style.width = `${(state.stats.hp / CONFIG.PLAYER_HP) * 100}%`;
    
    // 血量低时变红
    if (state.stats.hp < 30) {
        ui.hpBar.className = "health-bar-fill h-full bg-red-600 w-full";
    } else {
        ui.hpBar.className = "health-bar-fill h-full bg-gradient-to-r from-cyan-500 to-blue-600 w-full";
    }

    ui.score.innerText = state.score;
    ui.wave.innerText = state.wave;
    ui.ammoCur.innerText = state.stats.ammo;
    
    if (state.stats.ammo === 0) {
        ui.ammoCur.classList.add('text-red-500');
    } else {
        ui.ammoCur.classList.remove('text-red-500');
    }
}

// --- 主循环 ---
function gameLoop(timestamp) {
    if (!state.isPlaying) return;

    // 清空画布
    ctx.fillStyle = '#0f172a'; // 背景色覆盖,防止拖影
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    
    // 应用相机抖动
    ctx.save();
    ctx.translate(state.camera.x, state.camera.y);

    // 绘制网格背景 (装饰)
    ctx.strokeStyle = '#1e293b';
    ctx.lineWidth = 1;
    ctx.beginPath();
    for(let x=0; x<canvas.width; x+=50) { ctx.moveTo(x,0); ctx.lineTo(x,canvas.height); }
    for(let y=0; y<canvas.height; y+=50) { ctx.moveTo(0,y); ctx.lineTo(canvas.width,y); }
    ctx.stroke();

    // 更新实体
    state.entities.player.update();
    
    state.entities.bullets.forEach(b => b.update());
    state.entities.bullets = state.entities.bullets.filter(b => b.active);
    
    state.entities.enemies.forEach(e => e.update(state.entities.player));
    state.entities.enemies = state.entities.enemies.filter(e => e.active);
    
    state.entities.particles.forEach(p => p.update());
    state.entities.particles = state.entities.particles.filter(p => p.life > 0);

    state.entities.texts.forEach(t => t.update());
    state.entities.texts = state.entities.texts.filter(t => t.life > 0);

    checkCollisions();
    updateUI();

    // 绘制实体
    state.entities.bullets.forEach(b => b.draw());
    state.entities.enemies.forEach(e => e.draw());
    state.entities.player.draw();
    state.entities.particles.forEach(p => p.draw());
    state.entities.texts.forEach(t => t.draw());

    ctx.restore();

    requestAnimationFrame(gameLoop);
}

// --- 事件绑定 ---
document.getElementById('start-btn').addEventListener('click', initGame);
document.getElementById('restart-btn').addEventListener('click', initGame);

// 加载最高分
const savedHigh = localStorage.getItem('neonStrikeHighScore');
if(savedHigh) ui.highScore.innerText = savedHigh;

</script>
</body>
</html>