Initial commit
This commit is contained in:
100
js/npc/enemy.js
Normal file
100
js/npc/enemy.js
Normal file
@@ -0,0 +1,100 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user