微信小遊戲 demo 飛機大戰 代碼分析 (二)(databus.js)

微信小遊戲 demo 飛機大戰 代碼分析(二)(databus.js)

微信小遊戲 demo 飛機大戰 代碼分析(一)(main.js)html

微信小遊戲 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

構造器this

  • 若是instance不爲空已經存在,那麼就返回instance
    • 這是實現單例模式,保證無論多少次new都只能產生一個對象
  • 若是不爲空,將instance設置爲自身,並進行下列初始化操做
    • 建立一個對象池pool
      • 對象池技術是經過將生成的對象暫時保存於池中,須要對象時先在池中查看是否有多餘對象,若不足再生成對象,而在銷燬對象時不進行真正銷燬,而是加入對象池中
    • 重置全部內容,設置爲空

removeEnemey(enemy)

移除某個敵方對象(敵機)設計

  • 從enemys數組中獲取第一個元素
    • shift方法是js中移除第一個元素並返回的方法
  • 設置其不可見
  • 移入名爲enemy的池中

removeBullet(bullet)

移除某一個子彈code

操做方式同上一個函數相同htm

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數組中的操做,用於將元素打入數組當中
相關文章
相關標籤/搜索