Initial commit
This commit is contained in:
48
js/player/bullet.js
Normal file
48
js/player/bullet.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import Sprite from '../base/sprite';
|
||||
|
||||
const BULLET_IMG_SRC = 'images/bullet.png';
|
||||
const BULLET_WIDTH = 16;
|
||||
const BULLET_HEIGHT = 30;
|
||||
|
||||
export default class Bullet extends Sprite {
|
||||
constructor() {
|
||||
super(BULLET_IMG_SRC, BULLET_WIDTH, BULLET_HEIGHT);
|
||||
}
|
||||
|
||||
init(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.isActive = true;
|
||||
this.visible = true;
|
||||
}
|
||||
|
||||
setPos(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
// 每一帧更新子弹位置
|
||||
update() {
|
||||
if (GameGlobal.databus.isGameOver) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 子弹位置由外部控制(Player控制)
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.isActive = false;
|
||||
// 子弹没有销毁动画,直接移除
|
||||
this.remove();
|
||||
}
|
||||
|
||||
remove() {
|
||||
this.isActive = false;
|
||||
this.visible = false;
|
||||
// 回收子弹对象
|
||||
GameGlobal.databus.removeBullets(this);
|
||||
// 注意:DataBus.removeBullets 内部调用 pool.recover('bullet', bullet)
|
||||
// 我们需要修改 DataBus 或者在这里手动回收
|
||||
// 由于 DataBus 是通用的,我们最好修改 DataBus 或者在 DataBus 中传入 key
|
||||
}
|
||||
}
|
||||
161
js/player/index.js
Normal file
161
js/player/index.js
Normal file
@@ -0,0 +1,161 @@
|
||||
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'
|
||||
}); // 震动
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user