微信小游戏 demo 飞机大战 代码分析(二)(databus.js)
微信小游戏 demo 飞机大战 代码分析(一)(main.js)
微信小游戏 demo 飞机大战 代码分析(三)(spirit.js, animation.js)
微信小游戏 demo 飞机大战 代码分析(四)(enemy.js, bullet.js, index.js)
本博客将使用逐行代码分析的方式讲解该demo,本文适用于对其他高级语言熟悉,对js还未深入了解的同学,博主会尽可能将所有遇到的不明白的部分标注清楚,若有不正确或不清楚的地方,欢迎在评论中指正
本文的代码均由微信小游戏自动生成的demo飞机大战中获取
databus.js
代码:
import Pool from './base/pool'
let instance
/**
* 全局状态管理器
*/
export default class DataBus {
constructor() {
if ( instance )
return instance
instance = this
this.pool = new Pool()
this.reset()
}
reset() {
this.frame = 0
this.score = 0
this.bullets = []
this.enemys = []
this.animations = []
this.gameOver = false
}
/**
* 回收敌人,进入对象池
* 此后不进入帧循环
*/
removeEnemey(enemy) {
let temp = this.enemys.shift()
temp.visible = false
this.pool.recover('enemy', enemy)
}
/**
* 回收子弹,进入对象池
* 此后不进入帧循环
*/
removeBullets(bullet) {
let temp = this.bullets.shift()
temp.visible = false
this.pool.recover('bullet', bullet)
}
}
instance
- 该对象用于承载该文件中惟一的databus类,实现单例模式
- 单例模式是一种设计模式,保证全局仅有一个该类的对象,这样能在该demo中保证全局数据的一致性
constructor
构造器
- 如果instance不为空已经存在,那么就返回instance
- 这是实现单例模式,保证不管多少次new都只能产生一个对象
- 如果不为空,将instance设置为自身,并进行下列初始化操作
- 创建一个对象池pool
- 对象池技术是通过将生成的对象暂时保存于池中,需要对象时先在池中查看是否有多余对象,若不足再生成对象,而在销毁对象时不进行真正销毁,而是加入对象池中
- 重置所有内容,设置为空
- 创建一个对象池pool
removeEnemey(enemy)
移除某个敌方对象(敌机)
- 从enemys数组中获取第一个元素
- shift方法是js中移除第一个元素并返回的方法
- 设置其不可见
- 移入名为enemy的池中
removeBullet(bullet)
移除某一个子弹
操作方式同上一个函数相同
pool.js
一个用于实现对象池的函数
代码:
const __ = {
poolDic: Symbol('poolDic')
}
/**
* 简易的对象池实现
* 用于对象的存贮和重复使用
* 可以有效减少对象创建开销和避免频繁的垃圾回收
* 提高游戏性能
*/
export default class Pool {
constructor() {
this[__.poolDic] = {}
}
/**
* 根据对象标识符
* 获取对应的对象池
*/
getPoolBySign(name) {
return this[__.poolDic][name] || ( this[__.poolDic][name] = [] )
}
/**
* 根据传入的对象标识符,查询对象池
* 对象池为空创建新的类,否则从对象池中取
*/
getItemByClass(name, className) {
let pool = this.getPoolBySign(name)
let result = ( pool.length
? pool.shift()
: new className() )
return result
}
/**
* 将对象回收到对象池
* 方便后续继续使用
*/
recover(name, instance) {
this.getPoolBySign(name).push(instance)
}
}
const __
用于防止魔术字符串出现的常量列表
- Symbol
- 在js中反复用于获取某些值或者对象的字符串称为魔术字符串,如果字符串过多,正常使用可以,但是若需要修改,则需要同时修改多个字符串,非常不利于维护
- 为了解决这个问题,ES6引入了一个新的数据类型Symbol,用于存储这些字符串类型,而之后需要用到该字符串仅需要用该常量取得
- symbol类型为类似于字符串的类型,不能使用new命令,也不能添加属性
- 在这里声明了一个对象名称为poolDic,用于保存多个对象池的一个字典
constructor()
- 创建一个空的poolDic
getPoolBySign(name)
- 根据传入的名称获取相应的对象池,若不存在则生成一个新的,以一个数组来作为对象池
getItemByClass(name, className)
获取对象
- 获取相应对象池
- 判断对象池是否为空,若不为空,返回第一个元素,并从对象池中移除
- 若不为空,则用传入的类名生成新的一个对象
recover(name, instance)
回收对象
- 获取对象池并向其中推入元素
- push是js数组中的操作,用于将元素打入数组当中