zoukankan      html  css  js  c++  java
  • 微信小游戏 demo 飞机大战 代码分析 (二)(databus.js)

    微信小游戏 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
        • 对象池技术是通过将生成的对象暂时保存于池中,需要对象时先在池中查看是否有多余对象,若不足再生成对象,而在销毁对象时不进行真正销毁,而是加入对象池中
      • 重置所有内容,设置为空

    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数组中的操作,用于将元素打入数组当中
  • 相关阅读:
    无符号数和有符号数之间赋值和大小比较
    (转)关于Linux核心转储文件 core dump
    mysql忘记root密码解决办法
    CentOS7安装iptables防火墙
    CENTOS7下安装REDIS
    iptables命令(备忘)
    ps 命令详解
    virtualenv
    How to Baskup and Restore a MySQL database
    linux 用户/用户组添加修改删除(ubuntu/centos)
  • 原文地址:https://www.cnblogs.com/Phoenix-blog/p/10951278.html
Copyright © 2011-2022 走看看