<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, maximum-scale=1.0, minimum-scale=1.0, shrink-to-fit=yes">
  <title>🏰 阳光防线 · 自适应横竖屏</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    body {
      background: linear-gradient(135deg, #87CEEB 0%, #98FB98 30%, #90EE90 100%);
      min-height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
      font-family: 'Segoe UI', 'Microsoft YaHei', 'PingFang SC', sans-serif;
      padding: 10px;
      margin: 0;
      overflow-x: hidden;
    }
    .game-container {
      background: rgba(255, 255, 255, 0.25);
      border-radius: 24px;
      padding: 16px;
      box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2), 0 0 0 3px rgba(255, 255, 255, 0.5);
      backdrop-filter: blur(12px);
      width: 100%;
      max-width: 1200px;
      display: flex;
      flex-direction: column;
      align-items: center;
      position: relative;
      transition: all 0.3s ease;
    }
    .canvas-wrapper {
      width: 100%;
      position: relative;
      border-radius: 16px;
      overflow: hidden;
      box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
    }
    canvas {
      display: block;
      width: 100%;
      height: auto;
      cursor: crosshair;
      background: #7ec850;
    }
    /* 全屏按钮 */
    .fullscreen-btn {
      position: absolute;
      top: 24px;
      right: 24px;
      z-index: 10;
      width: 44px;
      height: 44px;
      border-radius: 50%;
      border: 2px solid rgba(255, 255, 255, 0.9);
      background: rgba(255, 255, 255, 0.8);
      cursor: pointer;
      font-size: 22px;
      display: flex;
      align-items: center;
      justify-content: center;
      transition: all 0.3s;
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
      backdrop-filter: blur(5px);
      color: #2d5016;
      line-height: 1;
    }
    .fullscreen-btn:hover {
      background: #ffffff;
      transform: scale(1.1);
      box-shadow: 0 6px 18px rgba(0, 0, 0, 0.3);
    }
    .panel {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-top: 14px;
      flex-wrap: wrap;
      gap: 10px;
      width: 100%;
    }
    .stats {
      display: flex;
      gap: 12px;
      font-size: clamp(14px, 2.5vw, 18px);
      font-weight: bold;
      color: #2d5016;
      flex-wrap: wrap;
    }
    .stat-item {
      background: rgba(255, 255, 255, 0.7);
      padding: 8px 14px;
      border-radius: 25px;
      border: 2px solid rgba(100, 180, 50, 0.6);
      box-shadow: 0 3px 8px rgba(0,0,0,0.1);
      display: flex;
      align-items: center;
      gap: 4px;
      white-space: nowrap;
    }
    .tower-buttons {
      display: flex;
      gap: 6px;
      flex-wrap: wrap;
    }
    .tower-btn {
      padding: 9px 13px;
      border-radius: 25px;
      border: 2px solid rgba(255, 255, 255, 0.8);
      background: rgba(255, 255, 255, 0.7);
      color: #2d5016;
      font-weight: bold;
      cursor: pointer;
      transition: all 0.3s;
      font-size: clamp(11px, 1.8vw, 14px);
      white-space: nowrap;
      box-shadow: 0 3px 8px rgba(0,0,0,0.1);
    }
    .tower-btn:hover {
      background: #c8e6a0;
      transform: translateY(-2px);
      box-shadow: 0 6px 18px rgba(0,0,0,0.2);
    }
    .tower-btn.active {
      background: #4CAF50;
      border-color: #ffffff;
      color: white;
      box-shadow: 0 0 20px rgba(76, 175, 80, 0.6);
      transform: scale(1.05);
    }
    .action-btns {
      display: flex;
      gap: 8px;
      flex-wrap: wrap;
      align-items: center;
    }
    .btn {
      padding: 9px 18px;
      border-radius: 25px;
      border: 2px solid rgba(255, 255, 255, 0.8);
      background: rgba(255, 255, 255, 0.8);
      color: #2d5016;
      font-weight: bold;
      cursor: pointer;
      transition: all 0.3s;
      font-size: clamp(12px, 2vw, 15px);
      box-shadow: 0 3px 8px rgba(0,0,0,0.1);
      white-space: nowrap;
    }
    .btn:hover {
      background: #d4edda;
      box-shadow: 0 5px 15px rgba(0,0,0,0.2);
    }
    .btn.start {
      background: #FF9800;
      border-color: #ffffff;
      color: white;
      font-weight: bold;
    }
    .btn.start:hover {
      background: #F57C00;
      box-shadow: 0 5px 20px rgba(255, 152, 0, 0.5);
    }
    .btn.range-toggle {
      background: #9C27B0;
      border-color: #ffffff;
      color: white;
      font-weight: bold;
    }
    .btn.range-toggle:hover {
      background: #7B1FA2;
      box-shadow: 0 5px 20px rgba(156, 39, 176, 0.5);
    }
    .btn.range-toggle.active-range {
      background: #E040FB;
      box-shadow: 0 0 20px rgba(224, 64, 251, 0.7);
    }
    .info-text {
      color: #3e6b27;
      font-size: clamp(10px, 1.6vw, 13px);
      margin-top: 8px;
      text-align: center;
      background: rgba(255,255,255,0.5);
      padding: 6px 16px;
      border-radius: 15px;
    }

    /* ========== 横屏布局样式 ========== */
    @media (orientation: landscape) and (min-width: 800px) {
      .game-container {
        flex-direction: row;
        align-items: stretch;
        gap: 16px;
        padding: 16px;
      }
      .canvas-wrapper {
        flex: 1;
        min-width: 0;
      }
      .game-sidebar {
        display: flex;
        flex-direction: column;
        justify-content: center;
        gap: 12px;
        width: 260px;
        min-width: 240px;
      }
      .panel {
        flex-direction: column;
        align-items: stretch;
        margin-top: 0;
        gap: 10px;
      }
      .stats {
        flex-direction: column;
        gap: 8px;
      }
      .stat-item {
        justify-content: center;
        font-size: 16px;
      }
      .tower-buttons {
        flex-direction: column;
        gap: 6px;
      }
      .tower-btn {
        text-align: center;
        font-size: 14px;
        padding: 11px 16px;
      }
      .action-btns {
        flex-direction: column;
        gap: 6px;
      }
      .btn {
        text-align: center;
        font-size: 14px;
        padding: 11px 18px;
      }
      .info-text {
        margin-top: 0;
      }
      .fullscreen-btn {
        top: 24px;
        right: 284px;
      }
    }

    /* ========== 小屏幕竖屏优化 ========== */
    @media (max-width: 600px) {
      .game-container {
        padding: 10px;
        border-radius: 16px;
      }
      .panel {
        gap: 6px;
      }
      .tower-btn {
        padding: 7px 10px;
      }
      .fullscreen-btn {
        top: 16px;
        right: 16px;
        width: 36px;
        height: 36px;
        font-size: 18px;
      }
    }
  </style>
</head>
<body>
  <div class="game-container" id="gameContainer">
    <!-- 全屏按钮 -->
    <button class="fullscreen-btn" id="fullscreenBtn" title="全屏模式">⛶</button>
    
    <!-- 游戏画布区域 -->
    <div class="canvas-wrapper">
      <canvas id="gameCanvas"></canvas>
    </div>
    
    <!-- 侧边栏(横屏时显示在右侧) -->
    <div class="game-sidebar" id="gameSidebar">
      <div class="panel">
        <div class="stats">
          <div class="stat-item">❤️ <span id="livesDisplay">20</span></div>
          <div class="stat-item">💰 <span id="moneyDisplay">400</span></div>
          <div class="stat-item">🌊 <span id="waveDisplay">1</span>/10</div>
        </div>
        <div class="tower-buttons">
          <button class="tower-btn active" data-type="arrow">🏹 箭塔 (80)</button>
          <button class="tower-btn" data-type="cannon">💣 炮塔 (150)</button>
          <button class="tower-btn" data-type="ice">❄️ 冰塔 (120)</button>
          <button class="tower-btn" data-type="lightning">⚡ 电塔 (200)</button>
        </div>
        <div class="action-btns">
          <button class="btn range-toggle active-range" id="rangeToggleBtn" title="显示/隐藏射击范围">🎯 范围</button>
          <button class="btn start" id="startWaveBtn">▶ 开始波次</button>
          <button class="btn" id="resetBtn">🔄 重新开始</button>
        </div>
      </div>
      <div class="info-text">
        💡 点击草地建造炮塔 | 点击炮塔升级 | 🎯切换范围
      </div>
    </div>
  </div>

  <script>
    (function() {
      const canvas = document.getElementById('gameCanvas');
      const ctx = canvas.getContext('2d');

      const livesDisplay = document.getElementById('livesDisplay');
      const moneyDisplay = document.getElementById('moneyDisplay');
      const waveDisplay = document.getElementById('waveDisplay');
      const rangeToggleBtn = document.getElementById('rangeToggleBtn');
      const fullscreenBtn = document.getElementById('fullscreenBtn');
      const gameContainer = document.getElementById('gameContainer');

      const GRID_SIZE = 64;
      const COLS = 10;
      const ROWS = 8;
      const MAP_W = COLS * GRID_SIZE;
      const MAP_H = ROWS * GRID_SIZE;

      canvas.width = MAP_W;
      canvas.height = MAP_H;

      let lives = 20;
      let money = 400;
      let wave = 1;
      let gameOver = false;
      let waveActive = false;
      let selectedTowerType = 'arrow';
      let showRange = true;
      let isFullscreen = false;
      let enemies = [];
      let towers = [];
      let bullets = [];
      let particles = [];
      let pathCells = [];
      let spawnPoint = {col: 0, row: 3};
      let endPoint = {col: 9, row: 4};
      let gridMap = [];

      const towerDefs = {
        arrow: {
          name: '箭塔', cost: 80, range: 2.5, damage: 20, cooldown: 18,
          color: '#2196F3', bulletColor: '#64B5F6', bulletSpeed: 8,
          upgradeCost: 60, maxLevel: 5, projectile: 'arrow', shape: 'arrow'
        },
        cannon: {
          name: '炮塔', cost: 150, range: 2.0, damage: 55, cooldown: 40,
          color: '#FF5722', bulletColor: '#FF8A65', bulletSpeed: 6,
          upgradeCost: 100, maxLevel: 4, splash: 1.2, projectile: 'cannonball', shape: 'cannon'
        },
        ice: {
          name: '冰塔', cost: 120, range: 2.3, damage: 12, cooldown: 22,
          color: '#00BCD4', bulletColor: '#80DEEA', bulletSpeed: 7,
          upgradeCost: 80, maxLevel: 5, slow: 0.5, projectile: 'ice', shape: 'ice'
        },
        lightning: {
          name: '电塔', cost: 200, range: 2.8, damage: 35, cooldown: 25,
          color: '#FFC107', bulletColor: '#FFE082', bulletSpeed: 15,
          upgradeCost: 130, maxLevel: 4, chain: 2, projectile: 'lightning', shape: 'lightning'
        }
      };

      const enemyTypes = {
        normal: {color: '#E53935', speed: 1.8, hp: 50, reward: 30, size: 14},
        fast: {color: '#FB8C00', speed: 3.2, hp: 30, reward: 25, size: 11},
        tank: {color: '#8E24AA', speed: 1.2, hp: 130, reward: 55, size: 18},
        boss: {color: '#D32F2F', speed: 1.0, hp: 400, reward: 150, size: 22}
      };

      // 全屏功能
      function toggleFullscreen() {
        if (!isFullscreen) {
          if (gameContainer.requestFullscreen) {
            gameContainer.requestFullscreen();
          } else if (gameContainer.webkitRequestFullscreen) {
            gameContainer.webkitRequestFullscreen();
          } else if (gameContainer.msRequestFullscreen) {
            gameContainer.msRequestFullscreen();
          }
        } else {
          if (document.exitFullscreen) {
            document.exitFullscreen();
          } else if (document.webkitExitFullscreen) {
            document.webkitExitFullscreen();
          } else if (document.msExitFullscreen) {
            document.msExitFullscreen();
          }
        }
      }

      function handleFullscreenChange() {
        isFullscreen = !!(
          document.fullscreenElement ||
          document.webkitFullscreenElement ||
          document.msFullscreenElement
        );
        fullscreenBtn.textContent = isFullscreen ? '✕' : '⛶';
        fullscreenBtn.title = isFullscreen ? '退出全屏' : '全屏模式';
      }

      fullscreenBtn.addEventListener('click', toggleFullscreen);
      document.addEventListener('fullscreenchange', handleFullscreenChange);
      document.addEventListener('webkitfullscreenchange', handleFullscreenChange);
      document.addEventListener('msfullscreenchange', handleFullscreenChange);

      // 范围显示切换
      rangeToggleBtn.addEventListener('click', () => {
        showRange = !showRange;
        if (showRange) {
          rangeToggleBtn.classList.add('active-range');
          rangeToggleBtn.textContent = '🎯 范围';
        } else {
          rangeToggleBtn.classList.remove('active-range');
          rangeToggleBtn.textContent = '🎯 隐藏';
        }
      });

      function initGridMap() {
        gridMap = Array(ROWS).fill().map(() => Array(COLS).fill('empty'));
      }

      function generateRandomPath() {
        const startCol = 0;
        const startRow = Math.floor(Math.random() * (ROWS - 2)) + 1;
        const endCol = COLS - 1;
        const endRow = Math.floor(Math.random() * (ROWS - 2)) + 1;
        spawnPoint = {col: startCol, row: startRow};
        endPoint = {col: endCol, row: endRow};

        let visited = new Set();
        let parent = new Map();
        let queue = [{col: startCol, row: startRow}];
        visited.add(`${startCol},${startRow}`);
        
        let found = false;
        while (queue.length > 0 && !found) {
          let current = queue.shift();
          let directions = [
            {dc: 1, dr: 0}, {dc: 0, dr: 1}, {dc: 0, dr: -1}, {dc: -1, dr: 0}
          ];
          for (let i = directions.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [directions[i], directions[j]] = [directions[j], directions[i]];
          }
          
          for (let dir of directions) {
            let nc = current.col + dir.dc;
            let nr = current.row + dir.dr;
            let key = `${nc},${nr}`;
            if (nc >= 0 && nc < COLS && nr >= 0 && nr < ROWS && !visited.has(key)) {
              visited.add(key);
              parent.set(key, `${current.col},${current.row}`);
              queue.push({col: nc, row: nr});
              if (nc === endCol && nr === endRow) {
                found = true;
                break;
              }
            }
          }
        }

        let path = [];
        let currentKey = `${endCol},${endRow}`;
        while (currentKey !== `${startCol},${startRow}`) {
          let [c, r] = currentKey.split(',').map(Number);
          path.push({col: c, row: r});
          currentKey = parent.get(currentKey);
          if (!currentKey) break;
        }
        path.push({col: startCol, row: startRow});
        path.reverse();

        let extendedPath = [...path];
        for (let i = 1; i < path.length - 1; i++) {
          if (Math.random() < 0.15) {
            let current = path[i];
            let next = path[i + 1];
            let midCol = current.col;
            let midRow = next.row;
            let key = `${midCol},${midRow}`;
            if (midCol >= 0 && midCol < COLS && midRow >= 0 && midRow < ROWS) {
              let alreadyInPath = path.some(p => p.col === midCol && p.row === midRow);
              if (!alreadyInPath) {
                extendedPath.splice(i + 1, 0, {col: midCol, row: midRow});
              }
            }
          }
        }

        let pathSet = new Set();
        let finalPath = [];
        for (let p of extendedPath) {
          let key = `${p.col},${p.row}`;
          if (!pathSet.has(key)) {
            pathSet.add(key);
            finalPath.push(p);
          }
        }
        
        pathCells = finalPath;

        for (let r = 0; r < ROWS; r++) {
          for (let c = 0; c < COLS; c++) {
            gridMap[r][c] = pathSet.has(`${c},${r}`) ? 'path' : 'empty';
          }
        }
      }

      function spawnWave(waveNum) {
        let enemyList = [];
        let count = 5 + waveNum * 3;
        for (let i = 0; i < count; i++) {
          let type = 'normal';
          let r = Math.random();
          if (waveNum >= 8 && i % 4 === 0) type = 'boss';
          else if (waveNum >= 5 && r < 0.2) type = 'tank';
          else if (waveNum >= 3 && r < 0.45) type = 'fast';
          
          let stats = enemyTypes[type];
          let hpMult = 1 + (waveNum - 1) * 0.3;
          enemyList.push({
            x: spawnPoint.col * GRID_SIZE + GRID_SIZE / 2,
            y: spawnPoint.row * GRID_SIZE + GRID_SIZE / 2,
            type: type,
            hp: Math.floor(stats.hp * hpMult),
            maxHp: Math.floor(stats.hp * hpMult),
            speed: stats.speed * 0.8,
            color: stats.color,
            size: stats.size,
            reward: stats.reward,
            pathIndex: 0,
            slowTimer: 0,
            originalSpeed: stats.speed * 0.8
          });
        }
        return enemyList.sort(() => Math.random() - 0.5);
      }

      function moveEnemy(enemy) {
        if (enemy.pathIndex >= pathCells.length) {
          lives--;
          spawnParticles(enemy.x, enemy.y, '#ff3333', 20, 4);
          return true;
        }
        let target = pathCells[enemy.pathIndex];
        let tx = target.col * GRID_SIZE + GRID_SIZE / 2;
        let ty = target.row * GRID_SIZE + GRID_SIZE / 2;
        let dx = tx - enemy.x;
        let dy = ty - enemy.y;
        let dist = Math.hypot(dx, dy);
        if (dist < 3) {
          enemy.pathIndex++;
          if (enemy.pathIndex >= pathCells.length) {
            lives--;
            spawnParticles(enemy.x, enemy.y, '#ff3333', 20, 4);
            return true;
          }
          target = pathCells[enemy.pathIndex];
          tx = target.col * GRID_SIZE + GRID_SIZE / 2;
          ty = target.row * GRID_SIZE + GRID_SIZE / 2;
          dx = tx - enemy.x;
          dy = ty - enemy.y;
          dist = Math.hypot(dx, dy);
        }
        if (dist > 0) {
          enemy.x += (dx / dist) * enemy.speed;
          enemy.y += (dy / dist) * enemy.speed;
        }
        return false;
      }

      function spawnParticles(x, y, color, count = 10, speed = 3) {
        for (let i = 0; i < count; i++) {
          let angle = Math.random() * Math.PI * 2;
          let sp = Math.random() * speed + 1;
          particles.push({
            x, y,
            vx: Math.cos(angle) * sp,
            vy: Math.sin(angle) * sp,
            life: 0.6 + Math.random() * 0.6,
            maxLife: 0.6 + Math.random() * 0.6,
            color: color,
            size: 2 + Math.random() * 3
          });
        }
      }

      function updateTowers() {
        for (let tower of towers) {
          tower.cooldownCounter = (tower.cooldownCounter || 0) - 1;
          if (tower.cooldownCounter > 0) continue;
          
          let target = null;
          let bestProgress = -1;
          for (let enemy of enemies) {
            let dx = enemy.x - (tower.col * GRID_SIZE + GRID_SIZE / 2);
            let dy = enemy.y - (tower.row * GRID_SIZE + GRID_SIZE / 2);
            let dist = Math.hypot(dx, dy) / GRID_SIZE;
            if (dist <= tower.range && enemy.hp > 0 && enemy.pathIndex > bestProgress) {
              bestProgress = enemy.pathIndex;
              target = enemy;
            }
          }
          
          if (target) {
            let def = towerDefs[tower.type];
            bullets.push({
              x: tower.col * GRID_SIZE + GRID_SIZE / 2,
              y: tower.row * GRID_SIZE + GRID_SIZE / 2,
              target: target,
              damage: tower.damage,
              speed: def.bulletSpeed,
              color: def.bulletColor,
              type: tower.type,
              splash: tower.splash || 0,
              slow: tower.slow || 0,
              chain: tower.chain || 0,
              tower: tower
            });
            tower.cooldownCounter = tower.cooldown;
          }
        }
      }

      function updateBullets() {
        for (let i = bullets.length - 1; i >= 0; i--) {
          let b = bullets[i];
          if (!b.target || b.target.hp <= 0) { bullets.splice(i, 1); continue; }
          let dx = b.target.x - b.x;
          let dy = b.target.y - b.y;
          let dist = Math.hypot(dx, dy);
          if (dist < b.speed + 4) {
            applyDamage(b, b.target);
            bullets.splice(i, 1);
          } else {
            b.x += (dx / dist) * b.speed;
            b.y += (dy / dist) * b.speed;
          }
        }
      }

      function applyDamage(bullet, enemy) {
        enemy.hp -= bullet.damage;
        spawnParticles(enemy.x, enemy.y, bullet.color, 8, 2.5);
        if (bullet.slow > 0 && enemy.slowTimer <= 0) {
          enemy.slowTimer = 35;
          enemy.speed = enemy.originalSpeed * (1 - bullet.slow);
        }
        if (bullet.splash > 0) {
          for (let e of enemies) {
            if (e === enemy || e.hp <= 0) continue;
            if (Math.hypot(e.x - enemy.x, e.y - enemy.y) / GRID_SIZE <= bullet.splash) {
              e.hp -= Math.floor(bullet.damage * 0.5);
              spawnParticles(e.x, e.y, '#ff8844', 5, 2);
            }
          }
        }
        if (bullet.chain > 0) {
          let lastTarget = enemy;
          for (let c = 0; c < bullet.chain; c++) {
            let nearest = null, minDist = GRID_SIZE * 2;
            for (let e of enemies) {
              if (e === lastTarget || e.hp <= 0) continue;
              let d = Math.hypot(e.x - lastTarget.x, e.y - lastTarget.y);
              if (d < minDist) { minDist = d; nearest = e; }
            }
            if (nearest) {
              nearest.hp -= Math.floor(bullet.damage * 0.4);
              spawnParticles(nearest.x, nearest.y, '#ffff00', 6, 2);
              lastTarget = nearest;
            } else break;
          }
        }
        if (enemy.hp <= 0) {
          money += enemy.reward;
          spawnParticles(enemy.x, enemy.y, '#ffffff', 15, 4);
        }
      }

      function upgradeTower(tower) {
        let def = towerDefs[tower.type];
        if (tower.level >= def.maxLevel) return false;
        let cost = Math.floor(def.upgradeCost * tower.level);
        if (money < cost) return false;
        money -= cost;
        tower.level++;
        tower.damage = Math.floor(def.damage * Math.pow(1.5, tower.level - 1));
        tower.range += 0.3;
        tower.cooldown = Math.max(10, def.cooldown - tower.level * 2);
        if (tower.splash) tower.splash += 0.2;
        if (tower.slow) tower.slow = Math.min(0.75, tower.slow + 0.08);
        if (tower.chain) tower.chain += (tower.level % 2 === 0 ? 1 : 0);
        spawnParticles(tower.col * GRID_SIZE + GRID_SIZE/2, tower.row * GRID_SIZE + GRID_SIZE/2, '#FFD700', 20, 4);
        return true;
      }

      function update() {
        if (gameOver) return;
        updateTowers();
        updateBullets();
        for (let i = enemies.length - 1; i >= 0; i--) {
          let enemy = enemies[i];
          if (enemy.slowTimer > 0) { enemy.slowTimer--; if (enemy.slowTimer <= 0) enemy.speed = enemy.originalSpeed; }
          if (moveEnemy(enemy) || enemy.hp <= 0) enemies.splice(i, 1);
        }
        for (let i = particles.length - 1; i >= 0; i--) {
          let p = particles[i];
          p.life -= 0.02;
          p.x += p.vx; p.y += p.vy;
          p.vx *= 0.96; p.vy *= 0.96;
          if (p.life <= 0) particles.splice(i, 1);
        }
        if (waveActive && enemies.length === 0) {
          waveActive = false;
          money += 100 + wave * 20;
          wave++;
          if (wave > 10) { alert('🎉 恭喜!你击败了所有波次!你是塔防大师!'); gameOver = true; }
          document.getElementById('startWaveBtn').disabled = false;
        }
        if (lives <= 0) { gameOver = true; lives = 0; alert('💔 游戏结束!敌人突破了防线...'); }
        updateUI();
      }

      function updateUI() {
        livesDisplay.textContent = lives;
        moneyDisplay.textContent = money;
        waveDisplay.textContent = wave + '/10';
      }

      function drawGrid() {
        for (let r = 0; r < ROWS; r++) {
          for (let c = 0; c < COLS; c++) {
            let x = c * GRID_SIZE, y = r * GRID_SIZE;
            
            if (gridMap[r][c] === 'path') {
              let gradient = ctx.createLinearGradient(x, y, x + GRID_SIZE, y + GRID_SIZE);
              gradient.addColorStop(0, '#D4A854');
              gradient.addColorStop(0.5, '#C49A3C');
              gradient.addColorStop(1, '#B8892E');
              ctx.fillStyle = gradient;
              ctx.fillRect(x, y, GRID_SIZE, GRID_SIZE);
              ctx.fillStyle = 'rgba(139, 101, 38, 0.3)';
              ctx.fillRect(x + 4, y + 4, GRID_SIZE - 8, GRID_SIZE - 8);
              ctx.strokeStyle = '#A07828';
              ctx.lineWidth = 3;
              ctx.strokeRect(x + 1, y + 1, GRID_SIZE - 2, GRID_SIZE - 2);
            } else {
              let gradient = ctx.createLinearGradient(x, y, x + GRID_SIZE, y + GRID_SIZE);
              gradient.addColorStop(0, '#66BB6A');
              gradient.addColorStop(0.5, '#4CAF50');
              gradient.addColorStop(1, '#43A047');
              ctx.fillStyle = gradient;
              ctx.fillRect(x, y, GRID_SIZE, GRID_SIZE);
              ctx.fillStyle = 'rgba(129, 199, 132, 0.4)';
              ctx.fillRect(x + 3, y + 3, GRID_SIZE - 6, GRID_SIZE - 6);
              if ((r + c) % 3 === 0) {
                ctx.fillStyle = '#FFEB3B';
                ctx.beginPath();
                ctx.arc(x + GRID_SIZE * 0.7, y + GRID_SIZE * 0.25, 3, 0, Math.PI * 2);
                ctx.fill();
              }
            }
            
            ctx.strokeStyle = 'rgba(255, 255, 255, 0.3)';
            ctx.lineWidth = 1;
            ctx.strokeRect(x, y, GRID_SIZE, GRID_SIZE);
          }
        }
        
        let sx = spawnPoint.col * GRID_SIZE + GRID_SIZE/2;
        let sy = spawnPoint.row * GRID_SIZE + GRID_SIZE/2;
        ctx.fillStyle = 'rgba(0, 200, 83, 0.4)';
        ctx.beginPath(); ctx.arc(sx, sy, 24, 0, Math.PI * 2); ctx.fill();
        ctx.fillStyle = '#00C853';
        ctx.font = 'bold 24px Arial';
        ctx.textAlign = 'center';
        ctx.fillText('🚪', sx, sy + 8);
        
        let ex = endPoint.col * GRID_SIZE + GRID_SIZE/2;
        let ey = endPoint.row * GRID_SIZE + GRID_SIZE/2;
        ctx.fillStyle = 'rgba(255, 82, 82, 0.4)';
        ctx.beginPath(); ctx.arc(ex, ey, 24, 0, Math.PI * 2); ctx.fill();
        ctx.fillText('🏠', ex, ey + 8);
      }

      function drawArrowTower(cx, cy, size, color, level) {
        ctx.fillStyle = '#5D4037';
        ctx.beginPath();
        ctx.arc(cx, cy, size * 0.7, 0, Math.PI * 2);
        ctx.fill();
        
        ctx.fillStyle = color;
        ctx.shadowColor = color;
        ctx.shadowBlur = 12;
        ctx.beginPath();
        ctx.moveTo(cx, cy - size * 1.2);
        ctx.lineTo(cx - size * 0.7, cy + size * 0.8);
        ctx.lineTo(cx + size * 0.7, cy + size * 0.8);
        ctx.closePath();
        ctx.fill();
        
        ctx.strokeStyle = '#FFFFFF';
        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.arc(cx, cy, size * 0.6, -0.8, 0.8);
        ctx.stroke();
        
        ctx.fillStyle = '#FFFFFF';
        ctx.beginPath();
        ctx.arc(cx, cy, size * 0.2, 0, Math.PI * 2);
        ctx.fill();
        
        ctx.shadowBlur = 0;
      }

      function drawCannonTower(cx, cy, size, color, level) {
        ctx.fillStyle = '#37474F';
        ctx.beginPath();
        ctx.arc(cx, cy, size * 0.8, 0, Math.PI * 2);
        ctx.fill();
        
        ctx.save();
        ctx.translate(cx, cy);
        ctx.fillStyle = color;
        ctx.shadowColor = color;
        ctx.shadowBlur = 10;
        ctx.fillRect(-size * 0.3, -size * 1.1, size * 0.6, size * 1.3);
        
        ctx.fillStyle = '#212121';
        ctx.fillRect(-size * 0.25, -size * 1.15, size * 0.5, size * 0.3);
        ctx.restore();
        
        for (let i = 0; i < 4; i++) {
          let angle = (i / 4) * Math.PI * 2;
          let rx = cx + Math.cos(angle) * size * 0.6;
          let ry = cy + Math.sin(angle) * size * 0.6;
          ctx.fillStyle = '#FFD54F';
          ctx.beginPath();
          ctx.arc(rx, ry, 3, 0, Math.PI * 2);
          ctx.fill();
        }
        
        ctx.shadowBlur = 0;
      }

      function drawIceTower(cx, cy, size, color, level) {
        ctx.fillStyle = '#B3E5FC';
        ctx.beginPath();
        for (let i = 0; i < 6; i++) {
          let angle = (i / 6) * Math.PI * 2 - Math.PI / 2;
          let px = cx + Math.cos(angle) * size * 0.8;
          let py = cy + Math.sin(angle) * size * 0.8;
          if (i === 0) ctx.moveTo(px, py);
          else ctx.lineTo(px, py);
        }
        ctx.closePath();
        ctx.fill();
        
        ctx.fillStyle = color;
        ctx.shadowColor = color;
        ctx.shadowBlur = 15;
        ctx.beginPath();
        for (let i = 0; i < 6; i++) {
          let angle = (i / 6) * Math.PI * 2 - Math.PI / 2;
          let px = cx + Math.cos(angle) * size * 0.7;
          let py = cy + Math.sin(angle) * size * 0.7;
          if (i === 0) ctx.moveTo(px, py);
          else ctx.lineTo(px, py);
          let midAngle = angle + Math.PI / 6;
          let mx = cx + Math.cos(midAngle) * size * 0.35;
          let my = cy + Math.sin(midAngle) * size * 0.35;
          ctx.lineTo(mx, my);
        }
        ctx.closePath();
        ctx.fill();
        
        ctx.fillStyle = '#FFFFFF';
        ctx.beginPath();
        ctx.arc(cx, cy, size * 0.2, 0, Math.PI * 2);
        ctx.fill();
        
        ctx.shadowBlur = 0;
      }

      function drawLightningTower(cx, cy, size, color, level) {
        ctx.fillStyle = '#FFF9C4';
        ctx.beginPath();
        ctx.moveTo(cx, cy - size * 0.9);
        ctx.lineTo(cx + size * 0.7, cy);
        ctx.lineTo(cx, cy + size * 0.9);
        ctx.lineTo(cx - size * 0.7, cy);
        ctx.closePath();
        ctx.fill();
        
        ctx.fillStyle = color;
        ctx.shadowColor = color;
        ctx.shadowBlur = 20;
        ctx.beginPath();
        ctx.moveTo(cx + size * 0.15, cy - size * 0.8);
        ctx.lineTo(cx - size * 0.4, cy + size * 0.1);
        ctx.lineTo(cx - size * 0.05, cy + size * 0.05);
        ctx.lineTo(cx - size * 0.25, cy + size * 0.8);
        ctx.lineTo(cx + size * 0.35, cy - size * 0.15);
        ctx.lineTo(cx + size * 0.0, cy - size * 0.05);
        ctx.lineTo(cx + size * 0.25, cy - size * 0.8);
        ctx.closePath();
        ctx.fill();
        
        ctx.fillStyle = '#FFFFFF';
        for (let i = 0; i < 3; i++) {
          let angle = Math.random() * Math.PI * 2;
          let dist = size * (0.5 + Math.random() * 0.4);
          ctx.beginPath();
          ctx.arc(cx + Math.cos(angle) * dist, cy + Math.sin(angle) * dist, 2, 0, Math.PI * 2);
          ctx.fill();
        }
        
        ctx.shadowBlur = 0;
      }

      function drawTowerShape(tower) {
        let cx = tower.col * GRID_SIZE + GRID_SIZE/2;
        let cy = tower.row * GRID_SIZE + GRID_SIZE/2;
        let def = towerDefs[tower.type];
        let size = 16 + tower.level * 2;
        
        if (showRange) {
          ctx.beginPath();
          ctx.arc(cx, cy, tower.range * GRID_SIZE, 0, Math.PI * 2);
          ctx.fillStyle = 'rgba(255, 255, 255, 0.12)';
          ctx.fill();
          ctx.strokeStyle = def.color;
          ctx.lineWidth = 2;
          ctx.setLineDash([5, 5]);
          ctx.stroke();
          ctx.setLineDash([]);
        }
        
        switch(def.shape) {
          case 'arrow':
            drawArrowTower(cx, cy, size, def.color, tower.level);
            break;
          case 'cannon':
            drawCannonTower(cx, cy, size, def.color, tower.level);
            break;
          case 'ice':
            drawIceTower(cx, cy, size, def.color, tower.level);
            break;
          case 'lightning':
            drawLightningTower(cx, cy, size, def.color, tower.level);
            break;
          default:
            ctx.fillStyle = def.color;
            ctx.beginPath();
            ctx.arc(cx, cy, size, 0, Math.PI * 2);
            ctx.fill();
        }
        
        ctx.fillStyle = '#FFFFFF';
        ctx.font = 'bold 13px Arial';
        ctx.textAlign = 'center';
        ctx.strokeStyle = 'rgba(0,0,0,0.6)';
        ctx.lineWidth = 2;
        ctx.strokeText('Lv' + tower.level, cx, cy - size - 8);
        ctx.fillText('Lv' + tower.level, cx, cy - size - 8);
      }

      function drawTowers() {
        for (let t of towers) {
          drawTowerShape(t);
        }
      }

      function drawEnemies() {
        for (let e of enemies) {
          ctx.save();
          ctx.shadowColor = 'rgba(0,0,0,0.4)';
          ctx.shadowBlur = 6;
          ctx.fillStyle = e.color;
          ctx.beginPath();
          ctx.arc(e.x, e.y, e.size, 0, Math.PI * 2);
          ctx.fill();
          ctx.fillStyle = 'rgba(255,255,255,0.3)';
          ctx.arc(e.x - 2, e.y - 2, e.size * 0.5, 0, Math.PI * 2);
          ctx.fill();
          
          let hpPercent = e.hp / e.maxHp;
          ctx.shadowBlur = 0;
          ctx.fillStyle = '#333';
          ctx.fillRect(e.x - 14, e.y - e.size - 10, 28, 6);
          ctx.fillStyle = hpPercent > 0.5 ? '#4CAF50' : hpPercent > 0.25 ? '#FF9800' : '#f44336';
          ctx.fillRect(e.x - 14, e.y - e.size - 10, 28 * hpPercent, 6);
          ctx.restore();
        }
      }

      function drawBullets() {
        for (let b of bullets) {
          ctx.shadowColor = b.color;
          ctx.shadowBlur = 10;
          ctx.fillStyle = b.color;
          ctx.beginPath();
          ctx.arc(b.x, b.y, 5, 0, Math.PI * 2);
          ctx.fill();
          ctx.fillStyle = '#fff';
          ctx.arc(b.x - 1, b.y - 1, 2, 0, Math.PI * 2);
          ctx.fill();
        }
        ctx.shadowBlur = 0;
      }

      function drawParticles() {
        for (let p of particles) {
          ctx.globalAlpha = p.life * 0.9;
          ctx.fillStyle = p.color;
          ctx.beginPath();
          ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
          ctx.fill();
        }
        ctx.globalAlpha = 1;
      }

      function drawAll() {
        ctx.clearRect(0, 0, MAP_W, MAP_H);
        drawGrid();
        drawTowers();
        drawEnemies();
        drawBullets();
        drawParticles();
        if (gameOver) {
          ctx.fillStyle = 'rgba(0,0,0,0.6)';
          ctx.fillRect(0, 0, MAP_W, MAP_H);
          ctx.fillStyle = '#ffffff';
          ctx.font = 'bold 42px Arial';
          ctx.textAlign = 'center';
          ctx.fillText('游戏结束', MAP_W/2, MAP_H/2);
        }
      }

      canvas.addEventListener('click', (e) => {
        if (gameOver) return;
        const rect = canvas.getBoundingClientRect();
        const scaleX = MAP_W / rect.width;
        const scaleY = MAP_H / rect.height;
        const mx = (e.clientX - rect.left) * scaleX;
        const my = (e.clientY - rect.top) * scaleY;
        const col = Math.floor(mx / GRID_SIZE);
        const row = Math.floor(my / GRID_SIZE);
        if (col < 0 || col >= COLS || row < 0 || row >= ROWS) return;
        
        let clickedTower = towers.find(t => t.col === col && t.row === row);
        if (clickedTower) {
          let def = towerDefs[clickedTower.type];
          let cost = Math.floor(def.upgradeCost * clickedTower.level);
          if (clickedTower.level >= def.maxLevel) { alert('已达到最高等级!'); return; }
          if (confirm(`升级 ${def.name} 到 Lv${clickedTower.level + 1}?\n费用:${cost} 金币`)) {
            if (!upgradeTower(clickedTower)) alert('金币不足!');
          }
          return;
        }
        
        if (gridMap[row][col] !== 'empty') { alert('不能在这里建造!'); return; }
        let def = towerDefs[selectedTowerType];
        if (money < def.cost) { alert('金币不足!'); return; }
        
        money -= def.cost;
        towers.push({
          col, row, type: selectedTowerType, level: 1,
          damage: def.damage, range: def.range, cooldown: def.cooldown,
          cooldownCounter: 0, splash: def.splash || 0, slow: def.slow || 0, chain: def.chain || 0
        });
        gridMap[row][col] = 'tower';
        spawnParticles(col * GRID_SIZE + GRID_SIZE/2, row * GRID_SIZE + GRID_SIZE/2, '#aaddff', 12, 3);
      });

      canvas.addEventListener('contextmenu', (e) => {
        e.preventDefault();
        selectedTowerType = null;
        document.querySelectorAll('.tower-btn').forEach(b => b.classList.remove('active'));
      });

      document.querySelectorAll('.tower-btn').forEach(btn => {
        btn.addEventListener('click', function() {
          document.querySelectorAll('.tower-btn').forEach(b => b.classList.remove('active'));
          this.classList.add('active');
          selectedTowerType = this.dataset.type;
        });
      });

      document.getElementById('startWaveBtn').addEventListener('click', () => {
        if (gameOver || waveActive || wave > 10) return;
        waveActive = true;
        enemies.push(...spawnWave(wave));
        document.getElementById('startWaveBtn').disabled = true;
      });

      document.getElementById('resetBtn').addEventListener('click', resetGame);

      function resetGame() {
        lives = 20; money = 400; wave = 1;
        gameOver = false; waveActive = false;
        enemies = []; towers = []; bullets = []; particles = [];
        selectedTowerType = 'arrow';
        showRange = true;
        rangeToggleBtn.classList.add('active-range');
        rangeToggleBtn.textContent = '🎯 范围';
        document.querySelectorAll('.tower-btn').forEach(b => b.classList.remove('active'));
        document.querySelector('.tower-btn[data-type="arrow"]').classList.add('active');
        document.getElementById('startWaveBtn').disabled = false;
        initGridMap();
        generateRandomPath();
        updateUI();
      }

      function gameLoop() {
        update();
        drawAll();
        requestAnimationFrame(gameLoop);
      }

      initGridMap();
      generateRandomPath();
      updateUI();
      gameLoop();
    })();
  </script>
</body>
</html>