162 lines
3.9 KiB
JavaScript
162 lines
3.9 KiB
JavaScript
import Animation from '../base/animation';
|
|
import { SCREEN_WIDTH, SCREEN_HEIGHT } from '../render';
|
|
import Bullet from './bullet';
|
|
|
|
// 玩家相关常量设置
|
|
const PLAYER_IMG_SRC = 'images/turtle5.png';
|
|
const PLAYER_WIDTH = 80;
|
|
const PLAYER_HEIGHT = 80;
|
|
const EXPLO_IMG_PREFIX = 'images/explosion';
|
|
const PLAYER_SHOOT_INTERVAL = 20;
|
|
|
|
export default class Player extends Animation {
|
|
constructor() {
|
|
super(PLAYER_IMG_SRC, PLAYER_WIDTH, PLAYER_HEIGHT);
|
|
|
|
// 初始化坐标
|
|
this.init();
|
|
|
|
// 初始化事件监听
|
|
this.initEvent();
|
|
}
|
|
|
|
init() {
|
|
// 玩家固定在屏幕中心
|
|
this.x = SCREEN_WIDTH / 2 - this.width / 2;
|
|
this.y = SCREEN_HEIGHT / 2 - this.height / 2;
|
|
|
|
// 用于在手指移动的时候标识手指是否已经在飞机上了
|
|
this.touched = false;
|
|
|
|
this.isActive = true;
|
|
this.visible = true;
|
|
|
|
// 设置爆炸动画
|
|
this.initExplosionAnimation();
|
|
|
|
// 初始化子弹(鞭子)
|
|
this.angle = 0;
|
|
this.radius = PLAYER_WIDTH * 1.5; // 旋转半径
|
|
this.bullets = [];
|
|
|
|
// 创建两个子弹
|
|
for (let i = 0; i < 2; i++) {
|
|
const bullet = GameGlobal.databus.pool.getItemByClass('whip_bullet', Bullet);
|
|
bullet.init(this.x, this.y);
|
|
this.bullets.push(bullet);
|
|
GameGlobal.databus.bullets.push(bullet);
|
|
}
|
|
}
|
|
|
|
// 预定义爆炸的帧动画
|
|
initExplosionAnimation() {
|
|
const EXPLO_FRAME_COUNT = 19;
|
|
const frames = Array.from(
|
|
{ length: EXPLO_FRAME_COUNT },
|
|
(_, i) => `${EXPLO_IMG_PREFIX}${i + 1}.png`
|
|
);
|
|
this.initFrames(frames);
|
|
}
|
|
|
|
/**
|
|
* 判断手指是否在飞机上
|
|
* @param {Number} x: 手指的X轴坐标
|
|
* @param {Number} y: 手指的Y轴坐标
|
|
* @return {Boolean}: 用于标识手指是否在飞机上的布尔值
|
|
*/
|
|
checkIsFingerOnAir(x, y) {
|
|
const deviation = 30;
|
|
return (
|
|
x >= this.x - deviation &&
|
|
y >= this.y - deviation &&
|
|
x <= this.x + this.width + deviation &&
|
|
y <= this.y + this.height + deviation
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 根据手指的位置设置飞机的位置
|
|
* 保证手指处于飞机中间
|
|
* 同时限定飞机的活动范围限制在屏幕中
|
|
*/
|
|
setAirPosAcrossFingerPosZ(x, y) {
|
|
const disX = Math.max(
|
|
0,
|
|
Math.min(x - this.width / 2, SCREEN_WIDTH - this.width)
|
|
);
|
|
const disY = Math.max(
|
|
0,
|
|
Math.min(y - this.height / 2, SCREEN_HEIGHT - this.height)
|
|
);
|
|
|
|
this.x = disX;
|
|
this.y = disY;
|
|
}
|
|
|
|
/**
|
|
* 玩家响应手指的触摸事件
|
|
* 改变战机的位置
|
|
*/
|
|
initEvent() {
|
|
wx.onTouchStart((e) => {
|
|
const { clientX: x, clientY: y } = e.touches[0];
|
|
|
|
if (GameGlobal.databus.isGameOver) {
|
|
return;
|
|
}
|
|
if (this.checkIsFingerOnAir(x, y)) {
|
|
this.touched = true;
|
|
this.setAirPosAcrossFingerPosZ(x, y);
|
|
}
|
|
});
|
|
|
|
wx.onTouchMove((e) => {
|
|
const { clientX: x, clientY: y } = e.touches[0];
|
|
|
|
if (GameGlobal.databus.isGameOver) {
|
|
return;
|
|
}
|
|
if (this.touched) {
|
|
this.setAirPosAcrossFingerPosZ(x, y);
|
|
}
|
|
});
|
|
|
|
wx.onTouchEnd((e) => {
|
|
this.touched = false;
|
|
});
|
|
|
|
wx.onTouchCancel((e) => {
|
|
this.touched = false;
|
|
});
|
|
}
|
|
|
|
update() {
|
|
if (GameGlobal.databus.isGameOver) {
|
|
return;
|
|
}
|
|
|
|
// 更新旋转角度
|
|
this.angle += 0.1; // 旋转速度
|
|
|
|
// 更新子弹位置
|
|
this.bullets.forEach((bullet, index) => {
|
|
// 两个子弹相差 180 度 (PI)
|
|
const currentAngle = this.angle + index * Math.PI;
|
|
|
|
const bulletX = this.x + this.width / 2 + Math.cos(currentAngle) * this.radius - bullet.width / 2;
|
|
const bulletY = this.y + this.height / 2 + Math.sin(currentAngle) * this.radius - bullet.height / 2;
|
|
|
|
bullet.setPos(bulletX, bulletY);
|
|
});
|
|
}
|
|
|
|
destroy() {
|
|
this.isActive = false;
|
|
this.playAnimation();
|
|
GameGlobal.musicManager.playExplosion(); // 播放爆炸音效
|
|
wx.vibrateShort({
|
|
type: 'medium'
|
|
}); // 震动
|
|
}
|
|
}
|