微信小游戲 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數組中的操作,用於將元素打入數組當中


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM