gratitude.durian.xpcool.com/js/player/index.js
2026-08-14 18:01:45 +08:00

151 lines
3.5 KiB
JavaScript

import Animation from '../base/animation';
import { SCREEN_WIDTH, SCREEN_HEIGHT } from '../render';
import Bullet from './bullet';
// 玩家相关常量设置
const PLAYER_IMG_SRC = 'images/hero.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 - this.height - 30;
// 用于在手指移动的时候标识手指是否已经在飞机上了
this.touched = false;
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);
}
/**
* 判断手指是否在飞机上
* @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;
});
}
/**
* 玩家射击操作
* 射击时机由外部决定
*/
shoot() {
const bullet = GameGlobal.databus.pool.getItemByClass('bullet', Bullet);
bullet.init(this.x + this.width / 2 - bullet.width / 2, this.y - 10, 10);
GameGlobal.databus.bullets.push(bullet);
GameGlobal.musicManager.playShoot(); // 播放射击音效
}
update() {
if (GameGlobal.databus.isGameOver) {
return;
}
// 每20帧让玩家射击一次
if (GameGlobal.databus.frame % PLAYER_SHOOT_INTERVAL === 0) {
this.shoot(); // 玩家射击
}
}
destroy() {
this.isActive = false;
this.playAnimation();
GameGlobal.musicManager.playExplosion(); // 播放爆炸音效
wx.vibrateShort({
type: 'medium'
}); // 震动
}
}