游戏开发微信小程序--工具箱之父

小程序工具箱之父已更新

Page({
  data: {
    score: 0,
    lives: 3,
    gameOver: false,
    playerVisible: true,
    level: 1,
    petType: 'cat',
    speedBuff: 1,
    coins: 0,
    friends: [],
    achievements: [],
    currentPetFrame: 0, // 当前宠物动画帧
    scoreMultiplier: 1,  // 得分倍率
    gameSpeed: 1,       // 游戏速度
    doubleBullets: false,  // 双发子弹状态
    bossAppeared: false,  // 是否出现过Boss
    season: 'spring',  // 当前季节:spring, summer, autumn, winter
    seasonEffect: 1,   // 季节对速度的影响
  },

  onLoad() {
    this.initGame();
  },

  async initGame() {
    // 等待画布初始化完成
    await this.initCanvas();
    // 加载图片资源
    await this.loadImages();
    // 开始游戏
    this.setupGame();
    this.gameLoop();
  },

  initCanvas() {
    return new Promise((resolve) => {
      const query = wx.createSelectorQuery();
      query.select('#gameCanvas')
        .fields({ node: true, size: true })
        .exec((res) => {
          const canvas = res[0].node;
          const ctx = canvas.getContext('2d');

          // 设置画布大小
          const dpr = wx.getSystemInfoSync().pixelRatio;
          canvas.width = res[0].width * dpr;
          canvas.height = res[0].height * dpr;
          ctx.scale(dpr, dpr);

          this.canvas = canvas;
          this.ctx = ctx;
          this.canvasWidth = res[0].width;
          this.canvasHeight = res[0].height;

          resolve();
        });
    });
  },

  async loadImages() {
    const imageList = {
      // 玩家角色动画帧
      pet_frame1: '/images/pet/cat_run1.png',
      pet_frame2: '/images/pet/cat_run2.png',
      pet_frame3: '/images/pet/cat_run3.png',
      pet_frame4: '/images/pet/cat_run4.png',
      // 敌人图片
      enemy_normal: '/images/enemies/enemy1.png',
      enemy_fast: '/images/enemies/enemy2.png',
      enemy_boss: '/images/enemies/enemy3.png',
      // 特效图片
      explosion: '/images/effects/explosion.png',
      bullet: '/images/effects/bullet.png',
      // 道具图片
      magnet: '/images/items/magnet.png',
      spring: '/images/items/spring.png',
      coin: '/images/items/coin.png',
      coin_spin1: '/images/items/coin_spin1.png',
      coin_spin2: '/images/items/coin_spin2.png',
      coin_spin3: '/images/items/coin_spin3.png',
      coin_spin4: '/images/items/coin_spin4.png',
    };

    try {
      this.images = {};
      const loadPromises = Object.entries(imageList).map(([key, path]) => {
        return new Promise((resolve, reject) => {
          const img = this.canvas.createImage();
          img.onload = () => {
            this.images[key] = img;
            resolve();
          };
          img.onerror = (err) => {
            console.error(`Failed to load image: ${path}`, err);
            reject(err);
          };
          img.src = path;
        });
      });

      await Promise.all(loadPromises);
      console.log('All images loaded successfully');
    } catch (error) {
      console.error('Error loading images:', error);
      wx.showToast({
        title: '资源加载失败',
        icon: 'none'
      });
    }
  },

  setupGame() {
    // 修改玩家对象,添加动画相关属性
    this.player = {
      x: this.canvasWidth / 2,
      y: this.canvasHeight - 60,
      width: 80,  // 调整尺寸以适应图片
      height: 80,
      speed: 5 * this.data.speedBuff,
      frameCount: 4,
      frameInterval: 100, // 动画帧间隔(毫秒)
      lastFrameUpdate: Date.now(),
      isMoving: false,
      direction: 1, // 1表示向右,-1表示向左
    };

    // 游戏道具系统
    this.items = [];
    this.itemTypes = {
      MAGNET: 'magnet',
      SPRING: 'spring',
      COIN: 'coin'
    };

    // 天气系统
    this.weather = {
      type: 'sunny',
      effect: 1
    };

    this.bullets = [];
    this.enemies = [];
    this.lastEnemySpawn = Date.now();
    this.enemySpawnInterval = 1000;
    this.baseEnemySpeed = 2;
    this.lastLevelUp = Date.now();
    this.levelUpInterval = 20000;

    // 触摸控制相关
    this.touchStartX = 0;
    this.isTouching = false;

    // 初始化季节
    this.lastSeasonChange = Date.now();
    this.seasonDuration = 60000; // 每个季节持续60秒
    this.initSeason();
  },

  initSeason() {
    const seasons = ['spring', 'summer', 'autumn', 'winter'];
    const randomSeason = seasons[Math.floor(Math.random() * seasons.length)];
    this.changeSeason(randomSeason);
  },

  updateSeason() {
    const now = Date.now();
    if (now - this.lastSeasonChange > this.seasonDuration) {
      this.lastSeasonChange = now;
      const seasons = ['spring', 'summer', 'autumn', 'winter'];
      const currentIndex = seasons.indexOf(this.data.season);
      const nextIndex = (currentIndex + 1) % seasons.length;
      this.changeSeason(seasons[nextIndex]);
    }
  },

  changeSeason(newSeason) {
    // 设置季节效果
    let seasonEffect = 1;
    switch(newSeason) {
      case 'spring':
        seasonEffect = 1.2;  // 春季速度提升
        break;
      case 'summer':
        seasonEffect = 1.5;  // 夏季速度最快
        break;
      case 'autumn':
        seasonEffect = 0.8;  // 秋季速度降低
        break;
      case 'winter':
        seasonEffect = 0.6;  // 冬季速度最慢
        break;
    }

    this.setData({
      season: newSeason,
      seasonEffect: seasonEffect
    });

    // 更新游戏速度
    this.updateGameSpeed(this.data.gameSpeed * seasonEffect);

    // 显示季节变化提示
    this.showSeasonChangeEffect(newSeason);
  },

  showSeasonChangeEffect(season) {
    const seasonNames = {
      spring: '春天',
      summer: '夏天',
      autumn: '秋天',
      winter: '冬天'
    };

    const seasonEffects = {
      spring: '万物复苏,速度提升!',
      summer: '炎炎夏日,速度最快!',
      autumn: '秋高气爽,速度放缓。',
      winter: '寒冬降临,速度减慢...'
    };

    wx.showToast({
      title: `${seasonNames[season]}来临!`,
      icon: 'none',
      duration: 2000
    });

    // 创建季节变化特效
    this.createSeasonTransitionEffect(season);
  },

  createSeasonTransitionEffect(season) {
    const ctx = this.ctx;
    let alpha = 1;
    const duration = 90;
    let frame = 0;

    const seasonColors = {
      spring: { primary: '#FFB7C5', secondary: '#98FB98' },  // 粉色和嫩绿色
      summer: { primary: '#FFD700', secondary: '#87CEEB' },  // 金色和天蓝色
      autumn: { primary: '#FFA500', secondary: '#8B4513' },  // 橙色和棕色
      winter: { primary: '#F0FFFF', secondary: '#B0E0E6' }   // 白色和粉蓝色
    };

    const animate = () => {
      if (frame >= duration) return;

      ctx.save();
      const color = seasonColors[season];
      
      // 创建渐变效果
      const gradient = ctx.createRadialGradient(
        this.canvasWidth/2, this.canvasHeight/2, 0,
        this.canvasWidth/2, this.canvasHeight/2, this.canvasWidth
      );

      gradient.addColorStop(0, `rgba(${this.hexToRgb(color.primary)}, ${alpha * 0.3})`);
      gradient.addColorStop(1, `rgba(${this.hexToRgb(color.secondary)}, 0)`);

      ctx.fillStyle = gradient;
      ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);

      ctx.restore();

      alpha = Math.max(0, 1 - frame/duration);
      frame++;
      this.canvas.requestAnimationFrame(animate);
    };

    this.canvas.requestAnimationFrame(animate);
  },

  hexToRgb(hex) {
    const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
    return result ? 
      `${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}` : 
      '255, 255, 255';
  },

  drawSeasonEffect(ctx) {
    switch(this.data.season) {
      case 'spring':
        this.drawSpringEffect(ctx);
        break;
      case 'summer':
        this.drawSummerEffect(ctx);
        break;
      case 'autumn':
        this.drawAutumnEffect(ctx);
        break;
      case 'winter':
        this.drawWinterEffect(ctx);
        break;
    }
  },

  drawSpringEffect(ctx) {
    // 绘制飘落的花瓣
    for (let i = 0; i < 20; i++) {
      ctx.save();
      ctx.fillStyle = '#FFB7C5';
      ctx.translate(
        Math.random() * this.canvasWidth,
        Math.random() * this.canvasHeight
      );
      ctx.rotate(Math.random() * Math.PI * 2);
      
      // 绘制花瓣形状
      ctx.beginPath();
      ctx.ellipse(0, 0, 5, 3, 0, 0, Math.PI * 2);
      ctx.fill();
      ctx.restore();
    }
  },

  drawSummerEffect(ctx) {
    // 绘制阳光效果
    const time = Date.now() / 1000;
    for (let i = 0; i < 10; i++) {
      ctx.save();
      const x = Math.random() * this.canvasWidth;
      const y = Math.random() * this.canvasHeight;
      const size = 20 + Math.sin(time + i) * 10;
      
      const gradient = ctx.createRadialGradient(x, y, 0, x, y, size);
      gradient.addColorStop(0, 'rgba(255, 215, 0, 0.2)');
      gradient.addColorStop(1, 'rgba(255, 215, 0, 0)');
      
      ctx.fillStyle = gradient;
      ctx.beginPath();
      ctx.arc(x, y, size, 0, Math.PI * 2);
      ctx.fill();
      ctx.restore();
    }
  },

  drawAutumnEffect(ctx) {
    // 绘制飘落的枫叶
    for (let i = 0; i < 15; i++) {
      ctx.save();
      ctx.fillStyle = `rgb(${200 + Math.random() * 55}, ${100 + Math.random() * 50}, 0)`;
      ctx.translate(
        Math.random() * this.canvasWidth,
        Math.random() * this.canvasHeight
      );
      ctx.rotate(Math.random() * Math.PI * 2);
      
      // 绘制枫叶形状
      this.drawMapleLeaf(ctx, 0, 0, 10);
      ctx.restore();
    }
  },

  drawWinterEffect(ctx) {
    // 绘制雪花
    for (let i = 0; i < 50; i++) {
      ctx.save();
      ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
      const x = Math.random() * this.canvasWidth;
      const y = Math.random() * this.canvasHeight;
      const size = 1 + Math.random() * 3;
      
      ctx.beginPath();
      ctx.arc(x, y, size, 0, Math.PI * 2);
      ctx.fill();
      ctx.restore();
    }
  },

  drawMapleLeaf(ctx, x, y, size) {
    ctx.beginPath();
    ctx.moveTo(x, y - size);
    for (let i = 0; i < 5; i++) {
      const angle = (Math.PI * 2 / 5) * i - Math.PI / 2;
      ctx.lineTo(
        x + Math.cos(angle) * size,
        y + Math.sin(angle) * size
      );
      const subAngle = angle + Math.PI * 2 / 10;
      ctx.lineTo(
        x + Math.cos(subAngle) * (size * 0.5),
        y + Math.sin(subAngle) * (size * 0.5)
      );
    }
    ctx.closePath();
    ctx.fill();
  },

  onTouchStart(e) {
    const touch = e.touches[0];
    this.touchStartX = touch.clientX;
    this.isTouching = true;

    // 发射子弹
    this.shoot();
  },

  onTouchMove(e) {
    if (!this.isTouching) return;
    const touch = e.touches[0];
    const moveX = touch.clientX - this.touchStartX;
    this.touchStartX = touch.clientX;

    // 设置移动方向
    this.player.direction = moveX > 0 ? 1 : -1;
    this.player.isMoving = true;

    // 移动飞机
    this.player.x = Math.max(0, Math.min(this.canvasWidth - this.player.width,
      this.player.x + moveX));
  },

  onTouchEnd() {
    this.isTouching = false;
    this.player.isMoving = false;
  },

  shoot() {
    if (this.data.gameOver) return;

    if (this.data.doubleBullets) {
      // 发射双发子弹
      const bulletSpacing = 20; // 子弹间距
      this.bullets.push({
        x: this.player.x + this.player.width / 2 - bulletSpacing/2 - 2.5,
        y: this.player.y,
        width: 5,
        height: 10,
        speed: 7
      });
      this.bullets.push({
        x: this.player.x + this.player.width / 2 + bulletSpacing/2 - 2.5,
        y: this.player.y,
        width: 5,
        height: 10,
        speed: 7
      });
    } else {
      // 发射单发子弹
      this.bullets.push({
        x: this.player.x + this.player.width / 2 - 2.5,
        y: this.player.y,
        width: 5,
        height: 10,
        speed: 7
      });
    }
  },

  spawnEnemy() {
    const now = Date.now();
    if (now - this.lastEnemySpawn > this.enemySpawnInterval) {
      // 检查是否需要生成Boss
      if (this.data.level >= 10 && !this.data.bossAppeared) {
        this.spawnBoss();
        return;
      }

      const enemyCount = Math.min(3, Math.floor(this.data.level / 5) + 1);
      
      for (let i = 0; i < enemyCount; i++) {
        const speedVariation = (Math.random() - 0.5) * 0.5;
        const baseSpeed = this.baseEnemySpeed + speedVariation;
        
        // 根据等级决定敌人类型
        const isFastEnemy = this.data.level >= 5 && Math.random() < 0.3;
        const enemySpeed = isFastEnemy ? baseSpeed * 1.5 : baseSpeed;
        
        // 根据敌人类型设置不同的尺寸
        const enemySize = isFastEnemy ? 50 : 60; // 快速敌人稍小,普通敌人更大
        
        this.enemies.push({
          x: Math.random() * (this.canvasWidth - enemySize),
          y: -enemySize - (i * (enemySize + 20)), // 增加间距防止重叠
          width: enemySize,
          height: enemySize,
          speed: enemySpeed * this.data.gameSpeed,
          baseSpeed: enemySpeed,
          isFastEnemy: isFastEnemy,
          rotation: 0,
          health: isFastEnemy ? 2 : 3  // 快速敌人2点生命值,普通敌人3点生命值
        });
      }
      this.lastEnemySpawn = now;
    }
  },

  spawnBoss() {
    const bossSize = 120;  // Boss尺寸增大到120
    this.enemies.push({
      x: this.canvasWidth / 2 - bossSize / 2,
      y: -bossSize,
      width: bossSize,
      height: bossSize,
      speed: this.baseEnemySpeed * 0.5,
      baseSpeed: this.baseEnemySpeed * 0.5,
      isBoss: true,
      health: 50,
      maxHealth: 50,
      rotation: 0,
      lastAttack: 0,
      attackInterval: 2000,
      phase: 1
    });

    this.setData({
      bossAppeared: true
    });

    // 显示Boss警告
    this.createBossWarning();
  },

  createBossWarning() {
    const ctx = this.ctx;
    let alpha = 1;
    const duration = 120;
    let frame = 0;

    const animate = () => {
      if (frame >= duration) return;

      ctx.save();
      // 创建紫色警告光环
      const gradient = ctx.createRadialGradient(
        this.canvasWidth/2, this.canvasHeight/2, 0,
        this.canvasWidth/2, this.canvasHeight/2, this.canvasWidth
      );

      const warningAlpha = Math.abs(Math.sin(frame * 0.1)) * 0.3 * alpha;
      gradient.addColorStop(0, `rgba(128, 0, 128, 0)`);
      gradient.addColorStop(0.5, `rgba(128, 0, 128, ${warningAlpha})`);
      gradient.addColorStop(1, `rgba(128, 0, 128, 0)`);

      ctx.fillStyle = gradient;
      ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);

      // 添加Boss警告文字
      ctx.font = 'bold 48px Arial';
      ctx.textAlign = 'center';
      ctx.fillStyle = `rgba(255, 0, 255, ${alpha})`;
      ctx.fillText('⚠ BOSS来袭 ⚠', this.canvasWidth/2, this.canvasHeight/2);
      ctx.font = '28px Arial';
      ctx.fillText('准备迎接终极挑战!', this.canvasWidth/2, this.canvasHeight/2 + 50);

      ctx.restore();

      alpha = Math.max(0, 1 - frame/duration);
      frame++;
      this.canvas.requestAnimationFrame(animate);
    };

    this.canvas.requestAnimationFrame(animate);
  },

  spawnItem() {
    if (Math.random() < 0.1) {
      const itemType = this.getRandomItemType();
      this.items.push({
        type: itemType,
        x: Math.random() * (this.canvasWidth - 40),
        y: -40,
        width: 40,  // 增大道具尺寸
        height: 40,
        speed: 2,
        createdAt: Date.now() // 添加创建时间用于动画
      });
    }
  },

  getRandomItemType() {
    // 降低金币生成概率
    const rand = Math.random();
    if (rand < 0.4) {  // 降低到40%概率生成金币
      return this.itemTypes.COIN;
    } else if (rand < 0.7) {  // 30%概率生成弹簧
      return this.itemTypes.SPRING;
    } else {  // 30%概率生成磁铁
      return this.itemTypes.MAGNET;
    }
  },

  updateWeather() {
    const now = Date.now();
    if (now - this.lastWeatherChange > 30000) {
      this.lastWeatherChange = now;
      if (Math.random() < 0.3) {
        this.changeWeather();
      }
    }
  },

  changeWeather() {
    const weathers = ['sunny', 'rainy', 'snowy'];
    const newWeather = weathers[Math.floor(Math.random() * weathers.length)];
    this.weather = {
      type: newWeather,
      effect: newWeather === 'rainy' ? 0.8 : newWeather === 'snowy' ? 0.7 : 1
    };
  },

  updatePlayerAnimation() {
    const now = Date.now();
    if (now - this.player.lastFrameUpdate > this.player.frameInterval) {
      this.setData({
        currentPetFrame: (this.data.currentPetFrame + 1) % this.player.frameCount
      });
      this.player.lastFrameUpdate = now;
    }
  },

  update() {
    if (this.data.gameOver) return;

    this.checkLevelUp();
    this.updateWeather();
    this.spawnItem();

    // 更新季节
    this.updateSeason();

    // 更新子弹位置
    this.bullets = this.bullets.filter(bullet => {
      bullet.y -= bullet.speed;
      return bullet.y > 0;
    });

    // 更新敌人位置和碰撞检测
    this.enemies = this.enemies.filter(enemy => {
      enemy.y += enemy.speed;

      // Boss特殊行为
      if (enemy.isBoss) {
        this.updateBoss(enemy);
      }

      // 检查子弹碰撞
      for (let i = 0; i < this.bullets.length; i++) {
        const bullet = this.bullets[i];
        if (this.checkCollision(bullet, enemy)) {
          this.bullets.splice(i, 1);
          
          // 减少敌人生命值
          enemy.health--;
          
          if (enemy.health <= 0) {
            // 计算得分
            const score = enemy.isBoss ? 1000 : (enemy.isFastEnemy ? 20 : 10);
            this.setData({
              score: this.data.score + (score * this.data.scoreMultiplier)
            });
            
            // 创建爆炸效果
            this.createExplosion(
              enemy.x + enemy.width/2, 
              enemy.y + enemy.height/2,
              enemy.isBoss ? '#800080' : '#ff0000'
            );
            
            // Boss死亡特效
            if (enemy.isBoss) {
              this.createBossDeathEffect(enemy);
            }
            
            return false;
          } else if (enemy.isBoss) {
            // Boss受伤效果
            this.createBossDamageEffect(enemy);
          }
          return true;
        }
      }

      // 检查玩家碰撞
      if (this.data.playerVisible && this.checkCollision(this.player, enemy)) {
        this.setData({
          lives: this.data.lives - 1,
          playerVisible: false
        });
        
        // 创建爆炸效果
        this.createExplosion(this.player.x, this.player.y);
        
        // 1.5秒后重生玩家(如果还有生命值)
        setTimeout(() => {
          if (this.data.lives > 0) {
            this.setData({
              playerVisible: true
            });
            // 重置玩家位置到底部中间
            this.player.x = this.canvasWidth / 2 - this.player.width / 2;
          } else {
            this.endGame();
          }
        }, 1500);
        
        return false;
      }

      return enemy.y < this.canvasHeight;
    });

    // 如果磁铁效果激活,吸取附近的金币
    if (this.magnetActive) {
      this.updateMagnetEffect();
    }

    // 更新道具
    this.items = this.items.filter(item => {
      item.y += item.speed;
      
      // 检查与玩家的碰撞
      if (this.checkCollision(this.player, item)) {
        this.collectItem(item);
        return false;
      }
      
      return item.y < this.canvasHeight;
    });

    // 更新玩家动画
    if (this.player.isMoving) {
      this.updatePlayerAnimation();
    }

    // 更新敌人旋转
    this.enemies.forEach(enemy => {
      enemy.rotation = (enemy.rotation || 0) + 0.05;
    });

    this.spawnEnemy();
  },

  createExplosion(x, y, color = '#ffa500') {
    // 使用爆炸图片替代粒子效果
    const ctx = this.ctx;
    const explosionImg = this.images.explosion;
    if (!explosionImg) return;

    let frame = 0;
    const totalFrames = 8; // 爆炸动画的总帧数
    const frameWidth = explosionImg.width / totalFrames;
    const frameHeight = explosionImg.height;
    const size = 100; // 爆炸效果的大小

    const animate = () => {
      if (frame >= totalFrames) return;

      ctx.drawImage(
        explosionImg,
        frame * frameWidth, 0, frameWidth, frameHeight,
        x - size/2, y - size/2, size, size
      );

      frame++;
      this.canvas.requestAnimationFrame(animate);
    };

    this.canvas.requestAnimationFrame(animate);
  },

  draw() {
    const ctx = this.ctx;
    ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);

    ctx.fillStyle = '#fff';
    ctx.font = '20px Arial';
    ctx.fillText(`等级: ${this.data.level}`, this.canvasWidth - 100, 30);

    // 只在玩家可见时绘制玩家
    if (this.data.playerVisible) {
      const frameKey = `pet_frame${this.data.currentPetFrame + 1}`;
      const img = this.images[frameKey];
      if (img) {
        ctx.save();
        if (this.player.direction === -1) {
          // 如果向左移动,翻转图片
          ctx.scale(-1, 1);
          ctx.drawImage(img, 
            -this.player.x - this.player.width, 
            this.player.y, 
            this.player.width, 
            this.player.height
          );
        } else {
          ctx.drawImage(img, 
            this.player.x, 
            this.player.y, 
            this.player.width, 
            this.player.height
          );
        }
        ctx.restore();
      }
    }

    // 绘制子弹
    ctx.fillStyle = '#fff';
    this.bullets.forEach(bullet => {
      if (this.images.bullet) {
        ctx.drawImage(this.images.bullet,
          bullet.x, bullet.y, bullet.width, bullet.height);
      }
    });

    // 绘制敌人
    this.enemies.forEach(enemy => {
      const enemyImg = this.getEnemyImage(enemy);
      if (enemyImg) {
        ctx.save();
        ctx.translate(enemy.x + enemy.width/2, enemy.y + enemy.height/2);
        ctx.rotate(enemy.rotation || 0);
        
        // 如果是Boss,绘制血条
        if (enemy.isBoss) {
          this.drawBossHealthBar(ctx, enemy);
        }
        
        ctx.drawImage(enemyImg,
          -enemy.width/2, -enemy.height/2,
          enemy.width, enemy.height
        );
        ctx.restore();
      }
    });

    // 绘制道具
    this.items.forEach(item => {
      this.drawItem(ctx, item);
    });

    // 绘制天气效果
    this.drawWeather(ctx);

    // 如果磁铁效果激活,绘制磁场范围
    if (this.magnetActive) {
      this.drawMagnetField(ctx, this.player);
    }

    // 如果有加速效果,只显示视觉效果而不显示具体数值
    if (this.data.gameSpeed > 1) {
      ctx.save();
      // 添加速度线效果
      const speedLines = 10;
      const lineLength = 50;
      for (let i = 0; i < speedLines; i++) {
        const x = Math.random() * this.canvasWidth;
        const y = Math.random() * this.canvasHeight;
        ctx.beginPath();
        ctx.moveTo(x, y);
        ctx.lineTo(x - lineLength, y);
        ctx.strokeStyle = `rgba(255, 255, 255, ${Math.random() * 0.3})`;
        ctx.lineWidth = 2;
        ctx.stroke();
      }

      // 添加屏幕边缘的速度光晕
      const gradient = ctx.createLinearGradient(0, 0, this.canvasWidth, 0);
      gradient.addColorStop(0, 'rgba(255, 215, 0, 0.2)');
      gradient.addColorStop(0.2, 'rgba(255, 215, 0, 0)');
      gradient.addColorStop(0.8, 'rgba(255, 215, 0, 0)');
      gradient.addColorStop(1, 'rgba(255, 215, 0, 0.2)');
      
      ctx.fillStyle = gradient;
      ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);
      ctx.restore();
    }

    // 绘制季节效果
    this.drawSeasonEffect(ctx);
  },

  drawWeather(ctx) {
    if (this.weather.type === 'rainy') {
      // 绘制雨滴效果
      for (let i = 0; i < 50; i++) {
        ctx.beginPath();
        ctx.strokeStyle = 'rgba(155, 155, 255, 0.5)';
        ctx.moveTo(Math.random() * this.canvasWidth, Math.random() * this.canvasHeight);
        ctx.lineTo(Math.random() * this.canvasWidth, Math.random() * this.canvasHeight + 10);
        ctx.stroke();
      }
    } else if (this.weather.type === 'snowy') {
      // 绘制雪花效果
      ctx.fillStyle = 'white';
      for (let i = 0; i < 30; i++) {
        ctx.beginPath();
        ctx.arc(Math.random() * this.canvasWidth, Math.random() * this.canvasHeight, 2, 0, Math.PI * 2);
        ctx.fill();
      }
    }
  },

  gameLoop() {
    this.update();
    this.draw();
    if (!this.data.gameOver) {
      // 使用 canvas 的 requestAnimationFrame
      this.canvas.requestAnimationFrame(() => {
        this.gameLoop();
      });
    }
  },

  checkCollision(rect1, rect2) {
    return rect1.x < rect2.x + rect2.width &&
           rect1.x + rect1.width > rect2.x &&
           rect1.y < rect2.y + rect2.height &&
           rect1.y + rect1.height > rect2.y;
  },

  endGame() {
    this.setData({
      gameOver: true
    });
  },

  restartGame() {
    this.setData({
      score: 0,
      lives: 3,
      gameOver: false,
      playerVisible: true,
      level: 1,
      coins: 0,
      doubleBullets: false,  // 重置子弹状态
      bossAppeared: false,  // 重置Boss出现状态
    });
    this.setupGame();
    this.gameLoop();
  },

  checkLevelUp() {
    const now = Date.now();
    if (now - this.lastLevelUp >= this.levelUpInterval) {
      this.lastLevelUp = now;
      
      const newLevel = this.data.level + 1;
      this.enemySpawnInterval = Math.max(300, this.enemySpawnInterval - 100);
      this.baseEnemySpeed += 0.2;
      
      this.setData({
        level: newLevel
      });

      // 在达到5级时显示提示
      if (newLevel === 5) {
        wx.showToast({
          title: '警告:快速敌人出现!',
          icon: 'none',
          duration: 3000
        });
        
        // 添加特殊的警告效果
        this.createWarningEffect();
      }
    }
  },

  collectItem(item) {
    switch(item.type) {
      case this.itemTypes.MAGNET:
        this.activateMagnet();
        break;
      case this.itemTypes.SPRING:
        this.activateSpring();
        break;
      case this.itemTypes.COIN:
        this.collectCoin();
        break;
    }
  },

  onShareAppMessage() {
    const shareTypes = ['help', 'invite', 'achievement'];
    const shareType = shareTypes[Math.floor(Math.random() * shareTypes.length)];
    
    return {
      title: this.getShareTitle(shareType),
      imageUrl: this.getShareImage(shareType),
      path: `/pages/game/game?type=${shareType}&from=${this.data.userId}`,
      success: () => {
        if (shareType === 'help') {
          this.addSpeedBuff();
        }
      }
    };
  },

  checkAchievements() {
    const newAchievements = [];
    
    if (this.data.score > 1000 && !this.hasAchievement('score_1000')) {
      newAchievements.push({
        id: 'score_1000',
        name: '分数达人',
        desc: '单局得分超过1000'
      });
    }
    
    if (newAchievements.length > 0) {
      this.setData({
        achievements: [...this.data.achievements, ...newAchievements]
      });
      this.showAchievementNotification(newAchievements);
    }
  },

  drawItem(ctx, item) {
    let img;
    switch(item.type) {
      case this.itemTypes.MAGNET:
        img = this.images.magnet;
        break;
        
      case this.itemTypes.SPRING:
        img = this.images.spring;
        break;
        
      case this.itemTypes.COIN:
        // 金币旋转动画
        const coinFrame = Math.floor(Date.now() / 100) % 4 + 1;
        img = this.images[`coin_spin${coinFrame}`];
        break;
    }

    if (img) {
      // 添加浮动效果
      const floatOffset = Math.sin(Date.now() / 300) * 5;
      
      // 添加发光效果
      ctx.save();
      ctx.shadowColor = this.getItemGlowColor(item.type);
      ctx.shadowBlur = 15;
      
      ctx.drawImage(img,
        item.x, item.y + floatOffset,
        item.width, item.height
      );
      
      // 如果是磁铁,添加磁场效果
      if (item.type === this.itemTypes.MAGNET) {
        this.drawMagnetField(ctx, item);
      }
      
      // 如果是弹簧道具,添加特殊的视觉效果
      if (item.type === this.itemTypes.SPRING) {
        ctx.save();
        // 添加上升箭头效果
        const arrowHeight = 15;
        const centerX = item.x + item.width/2;
        ctx.beginPath();
        ctx.moveTo(centerX, item.y - arrowHeight);
        ctx.lineTo(centerX - 10, item.y - arrowHeight + 10);
        ctx.lineTo(centerX + 10, item.y - arrowHeight + 10);
        ctx.closePath();
        ctx.fillStyle = '#FFD700';
        ctx.fill();
        ctx.restore();
      }
      
      ctx.restore();
    }
  },

  getItemGlowColor(type) {
    switch(type) {
      case this.itemTypes.MAGNET:
        return '#4169E1';
      case this.itemTypes.SPRING:
        return '#FFD700';
      case this.itemTypes.COIN:
        return '#FFA500';
      default:
        return '#FFFFFF';
    }
  },

  drawMagnetField(ctx, item) {
    // 绘制磁场波纹效果
    const time = Date.now() / 1000;
    const maxRadius = 30;
    const waves = 2;

    for (let i = 0; i < waves; i++) {
      const phase = (time + i/waves) % 1;
      const radius = phase * maxRadius;
      const alpha = 1 - phase;

      ctx.beginPath();
      ctx.arc(
        item.x + item.width/2,
        item.y + item.height/2,
        radius,
        0, Math.PI * 2
      );
      ctx.strokeStyle = `rgba(65, 105, 225, ${alpha * 0.5})`;
      ctx.lineWidth = 2;
      ctx.stroke();
    }

    // 如果是玩家的磁场效果,绘制范围指示器
    if (this.magnetActive) {
      ctx.beginPath();
      ctx.arc(
        this.player.x + this.player.width/2,
        this.player.y + this.player.height/2,
        150, // 磁铁吸取范围
        0, Math.PI * 2
      );
      ctx.strokeStyle = 'rgba(65, 105, 225, 0.2)';
      ctx.lineWidth = 1;
      ctx.stroke();
    }
  },

  activateMagnet() {
    // 激活磁铁效果
    this.magnetActive = true;
    this.magnetEndTime = Date.now() + 10000; // 记录结束时间用于显示倒计时
    
    // 10秒后取消磁铁效果
    setTimeout(() => {
      this.magnetActive = false;
    }, 10000);
  },

  activateSpring() {
    // 激活弹簧效果,提升游戏速度和得分倍率
    this.setData({
      scoreMultiplier: 2,    // 双倍得分
      gameSpeed: 1.5        // 1.5倍速
    });

    // 更新所有移动速度
    this.updateGameSpeed(1.5);
    
    // 显示加速效果提示
    wx.showToast({
      title: '游戏加速!双倍得分!',
      icon: 'none',
      duration: 2000
    });
    
    // 10秒后恢复正常
    setTimeout(() => {
      this.setData({
        scoreMultiplier: 1,
        gameSpeed: 1
      });
      this.updateGameSpeed(1);
    }, 10000);
  },

  updateGameSpeed(speed) {
    // 更新玩家速度
    this.player.speed = 5 * this.data.speedBuff * speed;
    
    // 更新敌人速度
    this.enemies.forEach(enemy => {
      enemy.speed = enemy.baseSpeed * speed;
    });
    
    // 更新子弹速度
    this.bullets.forEach(bullet => {
      bullet.speed = 7 * speed;
    });
    
    // 更新道具下落速度
    this.items.forEach(item => {
      item.speed = 2 * speed;
    });
  },

  collectCoin() {
    const newCoins = this.data.coins + 1;
    this.setData({
      coins: newCoins
    });
    
    // 检查金币相关成就和升级
    if (newCoins >= 100 && !this.hasAchievement('coin_collector')) {
      this.unlockAchievement('coin_collector', '金币收藏家', '收集100枚金币');
    }

    // 检查是否达到双发子弹条件
    if (newCoins >= 1000 && !this.data.doubleBullets) {
      this.upgradeTodoubleBullets();
    }
  },

  getShareTitle(type) {
    switch(type) {
      case 'help':
        return `来帮我加速!我在《萌宠冲刺团》中获得了 ${this.data.score} 分!`;
      case 'invite':
        return '来和我一起玩《萌宠冲刺团》吧!';
      case 'achievement':
        const latestAchievement = this.data.achievements[this.data.achievements.length - 1];
        return `我在《萌宠冲刺团》中解锁了"${latestAchievement?.name || '新成就'}"!`;
      default:
        return '来玩《萌宠冲刺团》吧!';
    }
  },

  getShareImage(type) {
    // 根据分享类型返回不同的分享图片
    const images = {
      help: '/images/share_help.png',
      invite: '/images/share_invite.png',
      achievement: '/images/share_achievement.png'
    };
    return images[type] || '/images/share_default.png';
  },

  addSpeedBuff() {
    // 增加速度buff
    this.setData({
      speedBuff: Math.min(2, this.data.speedBuff + 0.2) // 最多提升到2倍速
    });
    
    // 更新玩家速度
    this.player.speed = 5 * this.data.speedBuff;
    
    // 30秒后buff消失
    setTimeout(() => {
      this.setData({
        speedBuff: Math.max(1, this.data.speedBuff - 0.2)
      });
      this.player.speed = 5 * this.data.speedBuff;
    }, 30000);
  },

  hasAchievement(id) {
    return this.data.achievements.some(a => a.id === id);
  },

  unlockAchievement(id, name, desc) {
    if (!this.hasAchievement(id)) {
      const newAchievement = { id, name, desc };
      this.setData({
        achievements: [...this.data.achievements, newAchievement]
      });
      this.showAchievementNotification([newAchievement]);
    }
  },

  showAchievementNotification(achievements) {
    achievements.forEach(achievement => {
      wx.showToast({
        title: `解锁成就:${achievement.name}`,
        icon: 'none',
        duration: 3000
      });
    });
  },

  getEnemyImage(enemy) {
    // 根据敌人类型返回不同的图片
    if (enemy.isFastEnemy) {
      return this.images.enemy_fast;
    } else if (enemy.isBoss) {
      return this.images.enemy_boss;
    }
    return this.images.enemy_normal;
  },

  updateMagnetEffect() {
    const magnetRange = 150; // 磁铁吸取范围
    const attractionSpeed = 5; // 吸取速度

    this.items = this.items.filter(item => {
      if (item.type === this.itemTypes.COIN) {
        // 计算金币到玩家的距离
        const dx = (this.player.x + this.player.width/2) - (item.x + item.width/2);
        const dy = (this.player.y + this.player.height/2) - (item.y + item.height/2);
        const distance = Math.sqrt(dx * dx + dy * dy);

        if (distance < magnetRange) {
          // 在范围内,将金币吸向玩家
          const angle = Math.atan2(dy, dx);
          item.x += Math.cos(angle) * attractionSpeed;
          item.y += Math.sin(angle) * attractionSpeed;

          // 如果金币非常接近玩家,直接收集
          if (distance < 20) {
            this.collectCoin();
            return false;
          }
        }
      }
      return true;
    });
  },

  upgradeTodoubleBullets() {
    this.setData({
      doubleBullets: true
    });

    // 显示升级提示
    wx.showToast({
      title: '武器升级:双发子弹!',
      icon: 'none',
      duration: 3000
    });

    // 添加视觉特效
    this.createUpgradeEffect();
  },

  createUpgradeEffect() {
    const ctx = this.ctx;
    let alpha = 1;
    const duration = 60; // 动画帧数
    let frame = 0;

    const animate = () => {
      if (frame >= duration) return;

      ctx.save();
      // 创建发光环
      const gradient = ctx.createRadialGradient(
        this.player.x + this.player.width/2,
        this.player.y + this.player.height/2,
        0,
        this.player.x + this.player.width/2,
        this.player.y + this.player.height/2,
        100
      );

      gradient.addColorStop(0, `rgba(255, 215, 0, ${alpha})`);
      gradient.addColorStop(1, 'rgba(255, 215, 0, 0)');

      ctx.fillStyle = gradient;
      ctx.beginPath();
      ctx.arc(
        this.player.x + this.player.width/2,
        this.player.y + this.player.height/2,
        100,
        0, Math.PI * 2
      );
      ctx.fill();

      // 绘制上升的星星
      for (let i = 0; i < 5; i++) {
        const angle = (Math.PI * 2 / 5) * i + frame * 0.1;
        const radius = 50 + frame;
        const x = this.player.x + this.player.width/2 + Math.cos(angle) * radius;
        const y = this.player.y + this.player.height/2 + Math.sin(angle) * radius;

        ctx.fillStyle = `rgba(255, 255, 0, ${1 - frame/duration})`;
        this.drawStar(ctx, x, y, 5, 10, 5);
      }

      ctx.restore();

      alpha = 1 - frame/duration;
      frame++;
      this.canvas.requestAnimationFrame(animate);
    };

    this.canvas.requestAnimationFrame(animate);
  },

  drawStar(ctx, cx, cy, spikes, outerRadius, innerRadius) {
    let rot = Math.PI / 2 * 3;
    let x = cx;
    let y = cy;
    let step = Math.PI / spikes;

    ctx.beginPath();
    ctx.moveTo(cx, cy - outerRadius);

    for (let i = 0; i < spikes; i++) {
      x = cx + Math.cos(rot) * outerRadius;
      y = cy + Math.sin(rot) * outerRadius;
      ctx.lineTo(x, y);
      rot += step;

      x = cx + Math.cos(rot) * innerRadius;
      y = cy + Math.sin(rot) * innerRadius;
      ctx.lineTo(x, y);
      rot += step;
    }

    ctx.lineTo(cx, cy - outerRadius);
    ctx.closePath();
    ctx.fill();
  },

  createWarningEffect() {
    const ctx = this.ctx;
    let alpha = 1;
    const duration = 90; // 动画持续更长
    let frame = 0;

    const animate = () => {
      if (frame >= duration) return;

      ctx.save();
      // 创建红色警告光环
      const gradient = ctx.createRadialGradient(
        this.canvasWidth/2, this.canvasHeight/2, 0,
        this.canvasWidth/2, this.canvasHeight/2, this.canvasWidth
      );

      const warningAlpha = Math.abs(Math.sin(frame * 0.1)) * 0.3 * alpha;
      gradient.addColorStop(0, `rgba(255, 0, 0, 0)`);
      gradient.addColorStop(0.5, `rgba(255, 0, 0, ${warningAlpha})`);
      gradient.addColorStop(1, `rgba(255, 0, 0, 0)`);

      ctx.fillStyle = gradient;
      ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);

      // 添加警告文字
      ctx.font = 'bold 36px Arial';
      ctx.textAlign = 'center';
      ctx.fillStyle = `rgba(255, 0, 0, ${alpha})`;
      ctx.fillText('⚠ 警告 ⚠', this.canvasWidth/2, this.canvasHeight/2);
      ctx.font = '24px Arial';
      ctx.fillText('快速敌人来袭!', this.canvasWidth/2, this.canvasHeight/2 + 40);

      ctx.restore();

      alpha = Math.max(0, 1 - frame/duration);
      frame++;
      this.canvas.requestAnimationFrame(animate);
    };

    this.canvas.requestAnimationFrame(animate);
  },

  updateBoss(boss) {
    const now = Date.now();
    
    // Boss攻击逻辑
    if (now - boss.lastAttack > boss.attackInterval) {
      boss.lastAttack = now;
      
      // 根据Boss血量决定攻击模式
      if (boss.health > boss.maxHealth * 0.7) {
        // 第一阶段:散射攻击
        this.bossShotgunAttack(boss);
      } else if (boss.health > boss.maxHealth * 0.3) {
        // 第二阶段:激光攻击
        this.bossLaserAttack(boss);
      } else {
        // 第三阶段:狂暴模式
        this.bossRageAttack(boss);
      }
    }
  },

  drawBossHealthBar(ctx, boss) {
    const barWidth = boss.width * 1.2;
    const barHeight = 10;
    const x = -barWidth/2;
    const y = -boss.height/2 - 20;
    
    // 血条背景
    ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
    ctx.fillRect(x, y, barWidth, barHeight);
    
    // 血条
    const healthPercent = boss.health / boss.maxHealth;
    const gradient = ctx.createLinearGradient(x, y, x + barWidth, y);
    gradient.addColorStop(0, '#ff0000');
    gradient.addColorStop(0.5, '#ff6600');
    gradient.addColorStop(1, '#ffff00');
    
    ctx.fillStyle = gradient;
    ctx.fillRect(x, y, barWidth * healthPercent, barHeight);
  },

  bossShotgunAttack(boss) {
    // 实现散射攻击逻辑
  },

  bossLaserAttack(boss) {
    // 实现激光攻击逻辑
  },

  bossRageAttack(boss) {
    // 实现狂暴攻击逻辑
  },

  createBossDeathEffect(boss) {
    // 实现Boss死亡特效
  },

  createBossDamageEffect(boss) {
    // 实现Boss受伤效果
  },

  drawSeasonEffect(ctx) {
    const season = this.data.season;
    const seasonEffect = this.data.seasonEffect;
    const time = Date.now() / 1000;

    switch (season) {
      case 'spring':
        // 飘落花瓣效果
        for (let i = 0; i < 10; i++) {
          const x = Math.random() * this.canvasWidth;
          const y = Math.random() * this.canvasHeight;
          const size = Math.random() * 5 + 2;
          const speed = Math.random() * 0.5 + 0.5;
          const angle = Math.random() * Math.PI * 2;
          const dx = Math.cos(angle) * speed;
          const dy = Math.sin(angle) * speed;

          ctx.save();
          ctx.translate(x, y);
          ctx.rotate(time * speed);
          ctx.fillStyle = `rgba(255, 255, 255, ${Math.random() * 0.5 + 0.5})`;
          ctx.fillRect(-size/2, -size/2, size, size);
          ctx.restore();
        }
        break;
      case 'summer':
        // 阳光效果
        const gradient = ctx.createRadialGradient(
          this.canvasWidth/2, this.canvasHeight/2, 0,
          this.canvasWidth/2, this.canvasHeight/2, this.canvasWidth
        );
        gradient.addColorStop(0, 'rgba(255, 255, 255, 0)');
        gradient.addColorStop(0.5, 'rgba(255, 255, 255, 0.2)');
        gradient.addColorStop(1, 'rgba(255, 255, 255, 0)');
        ctx.fillStyle = gradient;
        ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);
        break;
      case 'autumn':
        // 飘落枫叶效果
        for (let i = 0; i < 20; i++) {
          const x = Math.random() * this.canvasWidth;
          const y = Math.random() * this.canvasHeight;
          const size = Math.random() * 10 + 5;
          const speed = Math.random() * 0.5 + 0.5;
          const angle = Math.random() * Math.PI * 2;
          const dx = Math.cos(angle) * speed;
          const dy = Math.sin(angle) * speed;

          ctx.save();
          ctx.translate(x, y);
          ctx.rotate(time * speed);
          ctx.fillStyle = `rgba(255, 165, 0, ${Math.random() * 0.5 + 0.5})`;
          ctx.fillRect(-size/2, -size/2, size, size);
          ctx.restore();
        }
        break;
      case 'winter':
        // 飘雪效果
        for (let i = 0; i < 50; i++) {
          const x = Math.random() * this.canvasWidth;
          const y = Math.random() * this.canvasHeight;
          const size = Math.random() * 3 + 1;
          const speed = Math.random() * 0.5 + 0.5;
          const angle = Math.random() * Math.PI * 2;
          const dx = Math.cos(angle) * speed;
          const dy = Math.sin(angle) * speed;

          ctx.save();
          ctx.translate(x, y);
          ctx.rotate(time * speed);
          ctx.fillStyle = 'white';
          ctx.fillRect(-size/2, -size/2, size, size);
          ctx.restore();
        }
        break;
    }
  }
}); 

部分源码如下,请大家关注工具箱之父体验

相关推荐
盛夏绽放5 小时前
微信小程序地图map全方位解析
微信小程序·小程序
初尘屿风7 小时前
基于微信小程序的电影院订票选座系统的设计与实现,SSM+Vue+毕业论文+开题报告+任务书+指导搭建视频
vue.js·微信小程序·小程序
paterWang9 小时前
基于SpringBoot的驾校报名小程序系统设计与实现(源码+文档)
spring boot·后端·小程序
EasyNVR10 小时前
EasyRTC:全平台支持与自研算法驱动的智能音视频通讯解决方案
运维·服务器·小程序·音视频·webrtc·p2p·智能硬件
韩召华15 小时前
微信小程序(uni)+蓝牙连接+Xprint打印机实现打印功能
微信小程序·小程序·notepad++
韩召华15 小时前
微信小程序实现拉卡拉支付
微信小程序·小程序
paterWang18 小时前
基于 Spring Boot + 微信小程序的短文写作竞赛管理系统设计与实现(源码+文档)
spring boot·后端·微信小程序
嘻哈∠※1 天前
基于SpringBoot+vue粮油商城小程序系统
vue.js·spring boot·小程序
luckyext1 天前
HBuilderX中,VUE生成随机数字,vue调用随机数函数
前端·javascript·vue.js·微信小程序·小程序
毕业设计-011 天前
0081.基于springboot+uni-app的垃圾分类小程序+论文
spring boot·小程序·uni-app