import Animation from '../base/animation'; import { SCREEN_WIDTH, SCREEN_HEIGHT } from '../render'; const ENEMY_IMG_SRC = 'images/enemy.png'; const ENEMY_WIDTH = 60; const ENEMY_HEIGHT = 60; const EXPLO_IMG_PREFIX = 'images/explosion'; export default class Enemy extends Animation { speed = Math.random() * 2 + 1; // 飞行速度 constructor() { super(ENEMY_IMG_SRC, ENEMY_WIDTH, ENEMY_HEIGHT); } init(speed) { this.x = 0; this.y = 0; // 随机选择一个边生成 (0:上, 1:右, 2:下, 3:左) const side = Math.floor(Math.random() * 4); switch (side) { case 0: // Top this.x = Math.random() * (SCREEN_WIDTH - this.width); this.y = -this.height; break; case 1: // Right this.x = SCREEN_WIDTH; this.y = Math.random() * (SCREEN_HEIGHT - this.height); break; case 2: // Bottom this.x = Math.random() * (SCREEN_WIDTH - this.width); this.y = SCREEN_HEIGHT; break; case 3: // Left this.x = -this.width; this.y = Math.random() * (SCREEN_HEIGHT - this.height); break; } // 计算朝向中心的速度向量 const targetX = SCREEN_WIDTH / 2 - this.width / 2; const targetY = SCREEN_HEIGHT / 2 - this.height / 2; const dx = targetX - this.x; const dy = targetY - this.y; const distance = Math.sqrt(dx * dx + dy * dy); this.speed = speed || (Math.random() * 2 + 2); // 默认速度 this.vx = (dx / distance) * this.speed; this.vy = (dy / distance) * this.speed; this.isActive = true; this.visible = true; // 设置爆炸动画 this.initExplosionAnimation(); } // 预定义爆炸的帧动画 initExplosionAnimation() { const EXPLO_FRAME_COUNT = 19; const frames = Array.from( { length: EXPLO_FRAME_COUNT }, (_, i) => `${EXPLO_IMG_PREFIX}${i + 1}.png` ); this.initFrames(frames); } // 每一帧更新敌人位置 update() { if (GameGlobal.databus.isGameOver) { return; } this.x += this.vx; this.y += this.vy; // 如果到达中心(或者非常接近),可以视为撞击玩家(碰撞检测会处理) // 这里不需要额外的边界回收逻辑,因为它们最终会撞上玩家或被消灭 } destroy() { this.isActive = false; // 播放销毁动画后移除 this.playAnimation(); GameGlobal.musicManager.playExplosion(); // 播放爆炸音效 wx.vibrateShort({ type: 'light' }); // 轻微震动 this.on('stopAnimation', () => this.remove.bind(this)); } remove() { this.isActive = false; this.visible = false; GameGlobal.databus.removeEnemy(this); } }