小程序工具箱之父已更新
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;
}
}
});
部分源码如下,请大家关注工具箱之父体验