Initial commit
This commit is contained in:
89
js/base/animation.js
Normal file
89
js/base/animation.js
Normal file
@@ -0,0 +1,89 @@
|
||||
import Sprite from './sprite';
|
||||
|
||||
const __ = {
|
||||
timer: Symbol('timer'),
|
||||
};
|
||||
|
||||
/**
|
||||
* 简易的帧动画类实现
|
||||
*/
|
||||
export default class Animation extends Sprite {
|
||||
constructor(imgSrc, width, height) {
|
||||
super(imgSrc, width, height);
|
||||
|
||||
this.isPlaying = false; // 当前动画是否播放中
|
||||
this.loop = false; // 动画是否需要循环播放
|
||||
this.interval = 1000 / 60; // 每一帧的时间间隔
|
||||
this[__.timer] = null; // 帧定时器
|
||||
this.index = -1; // 当前播放的帧
|
||||
this.count = 0; // 总帧数
|
||||
this.imgList = []; // 帧图片集合
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化帧动画的所有帧
|
||||
* @param {Array} imgList - 帧图片的路径数组
|
||||
*/
|
||||
initFrames(imgList) {
|
||||
this.imgList = imgList.map((src) => {
|
||||
const img = wx.createImage();
|
||||
img.src = src;
|
||||
return img;
|
||||
});
|
||||
|
||||
this.count = imgList.length;
|
||||
|
||||
// 推入到全局动画池,便于全局绘图的时候遍历和绘制当前动画帧
|
||||
GameGlobal.databus.animations.push(this);
|
||||
}
|
||||
|
||||
// 将播放中的帧绘制到canvas上
|
||||
aniRender(ctx) {
|
||||
if (this.index >= 0 && this.index < this.count) {
|
||||
ctx.drawImage(
|
||||
this.imgList[this.index],
|
||||
this.x,
|
||||
this.y,
|
||||
this.width * 1.2,
|
||||
this.height * 1.2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 播放预定的帧动画
|
||||
playAnimation(index = 0, loop = false) {
|
||||
this.visible = false; // 动画播放时隐藏精灵图
|
||||
this.isPlaying = true;
|
||||
this.loop = loop;
|
||||
this.index = index;
|
||||
|
||||
if (this.interval > 0 && this.count) {
|
||||
this[__.timer] = setInterval(this.frameLoop.bind(this), this.interval);
|
||||
}
|
||||
}
|
||||
|
||||
// 停止帧动画播放
|
||||
stopAnimation() {
|
||||
this.isPlaying = false;
|
||||
this.index = -1;
|
||||
if (this[__.timer]) {
|
||||
clearInterval(this[__.timer]);
|
||||
this[__.timer] = null; // 清空定时器引用
|
||||
this.emit('stopAnimation');
|
||||
}
|
||||
}
|
||||
|
||||
// 帧遍历
|
||||
frameLoop() {
|
||||
this.index++;
|
||||
|
||||
if (this.index >= this.count) {
|
||||
if (this.loop) {
|
||||
this.index = 0; // 循环播放
|
||||
} else {
|
||||
this.index = this.count - 1; // 保持在最后一帧
|
||||
this.stopAnimation(); // 停止播放
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
43
js/base/pool.js
Normal file
43
js/base/pool.js
Normal file
@@ -0,0 +1,43 @@
|
||||
const __ = {
|
||||
poolDic: Symbol('poolDic'),
|
||||
};
|
||||
|
||||
/**
|
||||
* 简易的对象池实现
|
||||
* 用于对象的存贮和重复使用
|
||||
* 可以有效减少对象创建开销和避免频繁的垃圾回收
|
||||
* 提高游戏性能
|
||||
*/
|
||||
export default class Pool {
|
||||
constructor() {
|
||||
this[__.poolDic] = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据对象标识符
|
||||
* 获取对应的对象池
|
||||
*/
|
||||
getPoolBySign(name) {
|
||||
return this[__.poolDic][name] || (this[__.poolDic][name] = []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据传入的对象标识符,查询对象池
|
||||
* 对象池为空创建新的类,否则从对象池中取
|
||||
*/
|
||||
getItemByClass(name, className) {
|
||||
const pool = this.getPoolBySign(name);
|
||||
|
||||
const result = pool.length ? pool.shift() : new className();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将对象回收到对象池
|
||||
* 方便后续继续使用
|
||||
*/
|
||||
recover(name, instance) {
|
||||
this.getPoolBySign(name).push(instance);
|
||||
}
|
||||
}
|
||||
55
js/base/sprite.js
Normal file
55
js/base/sprite.js
Normal file
@@ -0,0 +1,55 @@
|
||||
import Emitter from '../libs/tinyemitter';
|
||||
|
||||
/**
|
||||
* 游戏基础的精灵类
|
||||
*/
|
||||
export default class Sprite extends Emitter {
|
||||
visible = true; // 是否可见
|
||||
isActive = true; // 是否可碰撞
|
||||
|
||||
constructor(imgSrc = '', width = 0, height = 0, x = 0, y = 0) {
|
||||
super();
|
||||
|
||||
this.img = wx.createImage();
|
||||
this.img.src = imgSrc;
|
||||
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
||||
this.visible = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将精灵图绘制在canvas上
|
||||
*/
|
||||
render(ctx) {
|
||||
if (!this.visible) return;
|
||||
|
||||
ctx.drawImage(this.img, this.x, this.y, this.width, this.height);
|
||||
}
|
||||
|
||||
/**
|
||||
* 简单的碰撞检测定义:
|
||||
* 另一个精灵的中心点处于本精灵所在的矩形内即可
|
||||
* @param{Sprite} sp: Sptite的实例
|
||||
*/
|
||||
isCollideWith(sp) {
|
||||
const spX = sp.x + sp.width / 2;
|
||||
const spY = sp.y + sp.height / 2;
|
||||
|
||||
// 不可见则不检测
|
||||
if (!this.visible || !sp.visible) return false;
|
||||
// 不可碰撞则不检测
|
||||
if (!this.isActive || !sp.isActive) return false;
|
||||
|
||||
return !!(
|
||||
spX >= this.x &&
|
||||
spX <= this.x + this.width &&
|
||||
spY >= this.y &&
|
||||
spY <= this.y + this.height
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user