ByteEdu.Com教育平台–遊戲前端架構分析

框架引擎:cocos creator

程式語言:JavaScript

架構目錄結構:

下面我們以UIManager為例子,整體程式碼如下:

let Effects = {      "NoEffect": { show: (layer) => { }, hide: (layer, finish) => { finish() }, },  }    cc.Class({      extends: cc.Component,        properties: {          uiParent: cc.Node,          mask: cc.Node, // 半透明屏蔽層          tipTempNode: cc.Node,            model: { // for MVC              visible: false,              get: function () {                  return this._model              }          }      },        onLoad: function () {          window.UIMgr = this          this._model = {              prefabs: {},              cache: {}, // layers cache              stack: [], // layers stack              urls: [],          }            this.mask.parent = this.uiParent          this.mask.active = false      },        checkIsLoaded: function (key) {          return !!this.model.prefabs[key]      },        syncLoad: function (key, cb) {          cb = cb || function () { }            let subs = key.split(':')          let url = (subs.length == 2) ? `SubModules/${subs[0]}/prefabs/ui/${subs[1]}` : `Master/prefabs/ui/${key}`          if (this.model.prefabs[key]) {              cb()          } else {              cc.loader.loadRes(url, (err, prefab) => {                  if (err) {                      return cc.log(err)                  }                  this.model.prefabs[key] = prefab                  this.model.urls.push(url)                  collectMgr.register(url)                  cb()              })          }      },        // usage: UIMgr.show({multi:true, effect:'MoveFromLeft', name:"MessageBox"}, ...)      // usage: UIMgr.show("MessageBox", ...)      show: function (name) { // params: multi, effect          if (!name) return;            let args = Array.prototype.slice.call(arguments)          let params = {}          args.splice(0, 1)            if (typeof (name) != 'string') {              params = name || {}              name = params.name              if (!name) return;          }            let setupLayer = (layer) => {              let count = this.model.stack.push(layer)              layer.node.zIndex = count * 2 + 2              layer.node.parent = this.uiParent              layer.effect = params['effect'] ? Effects[params['effect']] : Effects['NoEffect']              layer.effect.show(layer)              if (layer.node.onenter) {                  layer.node.onenter.apply(null, args)              }          }            this.syncLoad(name, (url) => {              cc.log('show ', name)                if (params.multi || this.model.cache[name] == null) {                  let layer = {                      name: name,                      node: cc.instantiate(this.model.prefabs[name]),                      pfbURL: url,                  }                    this.model.cache[name] = layer                  setupLayer(layer)              } else {                  let layer = this.bringToTop(name)                  if (layer) { // 單個實例且此實例已經在顯示中                      if (layer.node.onenter) {                          layer.node.onenter.apply(null, args)                      }                  } else {                      layer = this.model.cache[name]                      setupLayer(layer)                  }              }                this.resetMask()          })      },        bringToTop: function (name) {          for (let i = 0; i < this.model.stack.length; i++) {              let layer = this.model.stack[i]              if (layer.name == name) {                  this.model.stack.splice(i, 1)                  this.model.stack.push(layer)                  return layer              }          }          return null      },        topName: function () {          return this.model.stack.length == 0 ? "" : this.model.stack[this.model.stack.length - 1].name      },        topNode: function () {          return this.model.stack.length == 0 ? "" : this.model.stack[this.model.stack.length - 1].node      },        pop: function () {          if (this.model.stack.length > 0) {              this.close(this.model.stack[this.model.stack.length - 1].node)          }      },        close: function (node) {          if (node instanceof cc.Component) {              node = node.node          } else if (typeof (node) == 'string') {              if (this.model.cache[node]) {                  node = this.model.cache[node].node              } else {                  return              }          }            let found = null          for (let i = 0; i < this.model.stack.length; i++) {              let layer = this.model.stack[i]              if (layer.node == node) {                  this.model.stack.splice(i, 1)[0]                  found = layer                  break              }          }            if (!found) {              return          }            found.effect.hide(found, () => {              found.node.parent = null              this.resetMask()          })      },        clear: function () {          this.model.stack.forEach((layer) => {              layer.node.parent = null          })            if (globalCfg.memoryCollectImmediate) {              this.model.urls.forEach((url) => {                  collectMgr.release(url)              })          }            this.model.stack.length = 0          this.model.urls.length = 0          this.model.cache = {}            this.resetMask()      },        resetMask: function () {          let count = this.model.stack.length          this.mask.active = (count != 0)          this.mask.zIndex = count * 2 + 1      },        showTip: function (text) {          let node = cc.instantiate(this.tipTempNode)          node.active = true;          node.parent = this.tipTempNode.parent          node.getChildByName('value').getComponent(cc.Label).string = text            node.Run(              cc.delayTime(2),              cc.fadeOut(0.5),              cc.callFunc(() => {                  node.parent = null              })          )      },  });  

遊戲中的調用:

    UIMgr.show('MessageBox', '確定解散嗎? 10S後自動取消', 'ok|cancel', (op) => {              let agreeBool = false              if (op == 'ok') {                  agreeBool = true                  let C2GS_OutProto = {                      Protocol: 2,                      Protocol2: 53,                      OpenID: me.OpenID,                      RoomID: mj._model.roomid,                      SeatID: '' + mj.myPositionIndex,                      IsAgree: agreeBool                  }                  client.send(C2GS_OutProto)              }          })  

手機上的效果:

在我們的框架中調用還是比較簡單的,我們的近期的【血戰到底的課程】就是使用的本套框架,歡迎大家諮詢報名。