<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          游戲速率倍速與慢動作

          共 3437字,需瀏覽 7分鐘

           ·

          2020-10-25 12:33


          CocosCreator之控制游戲速率實現(xiàn)倍速與慢動作

          摘要

          在游戲開發(fā)中,游戲速率控制一直是一個需求,官方提供了計時器的控制接口以及動作系統(tǒng)的 cc.speed,但是使用起來不是很方便且無法影響到 update 控制邏輯以及物理系統(tǒng),那么如何實現(xiàn)這一需求呢?

          正文

          使用版本

          CocosCreator 版本 2.3.4

          思維過程

          想問題還是要去根上找,跑到源碼里先看看官方實現(xiàn)的計時器控制邏輯是怎么樣的?在 CCSchedule.js 中可以看到有這樣一個方法:

          setTimeScale:?function?(timeScale)?{
          ????this._timeScale?=?timeScale;
          }

          這個私有屬性是如何控制速率的呢?一番尋找,是在 update 中進行了計算:

          update:?function?(dt)?{
          ????this._updateHashLocked?=?true;
          ????if(this._timeScale?!==?1)
          ????????dt?*=?this._timeScale;

          ????var?i,?list,?len,?entry;
          ????//......
          }

          這樣就明白了,實際上就是把被計時器控制的組件的 dt 時間給改了,那我們想實現(xiàn)全局的控制應(yīng)該再往根源處尋找。

          導(dǎo)演類控制

          正常講游戲循環(huán)是每秒 60 幀,那么每幀的主循環(huán)邏輯應(yīng)該不是在 CCGame.js 就是在 CCDirector.js 中,果然在導(dǎo)演類中看到了 mainLoop 方法,而其中有這么一段代碼(省略了無關(guān)代碼):

          //?calculate?"global"?dt
          this.calculateDeltaTime(now);

          //?Update
          if?(!this._paused)?{
          ????//?before?update
          ????this.emit(cc.Director.EVENT_BEFORE_UPDATE);

          ????//?Call?start?for?new?added?components
          ????this._compScheduler.startPhase();

          ????//?Update?for?components
          ????this._compScheduler.updatePhase(this._deltaTime);

          ????//?Engine?update?with?scheduler
          ????this._scheduler.update(this._deltaTime);

          ????//?Late?update?for?components
          ????this._compScheduler.lateUpdatePhase(this._deltaTime);

          ????//?After?life-cycle?executed
          ????this._compScheduler.clearup();

          ????//?User?can?use?this?event?to?do?things?after?update
          ????this.emit(cc.Director.EVENT_AFTER_UPDATE);
          ????
          ????//?Destroy?entities?that?have?been?removed?recently
          ????Obj._deferredDestroy();
          }

          在沒暫停的情況,計算完 dt 后分發(fā)下去,那我們在 this.calculateDeltaTime(now) 方法里面把 this._deltaTime 給改了不就可以了,比如這樣:

          calculateDeltaTime:?function?(now)?{
          ????if?(!now)?now?=?performance.now();

          ????this._deltaTime?=?now?>?this._lastUpdate???(now?-?this._lastUpdate)?/?1000?:?0;
          ????if?(CC_DEBUG?&&?(this._deltaTime?>?1))
          ????????this._deltaTime?=?1?/?60.0;
          ????this._lastUpdate?=?now;

          ????//?乘以?2?實現(xiàn)倍數(shù)
          ????this._deltaTime?*=?2;
          },

          或者把這個乘以邏輯放在 calculateDeltaTime 調(diào)用的下面也可以:

          //?calculate?"global"?dt
          this.calculateDeltaTime(now);

          //?乘以?2?實現(xiàn)倍數(shù)
          this._deltaTime?*=?2;

          更好的實現(xiàn)

          試了試還真實現(xiàn)了,能夠做到全局控制速率,但是這個方法要魔改下引擎,換項目或者引擎版本無法做到復(fù)用,有沒有更好的辦法呢?當然,是可以不改引擎還能改引擎的(怪怪的,嘿嘿)。其實就是在自己的代碼里去更改引擎代碼,但是又涉及一個順序問題,要確保引擎的更改順序早于你使用的邏輯。

          如果你翻過文檔,你會知道插件腳本就能實現(xiàn)這個需求,在 CocosCreator 中腳本執(zhí)行順序為:Cocos2d 引擎最先執(zhí)行,然后是插件腳本(有多個的話按項目中的路徑字母順序依次加載),最后才是我們寫的普通腳本(打包后只有一個文件,內(nèi)部按 require 的依賴順序依次初始化)。

          那就寫個引擎擴展腳本 k-cocos.js 去擴展引擎就行了,不用魔改引擎,完美!

          cc.kSpeed()誕生

          接下來就是在這個插件腳本中修改一下引擎計算 dt 的方法,為了方便控制,可以引入一個變量,然后在計算后讓時間乘以這個變量,變量默認為 1 代表正常速度,想倍數(shù)我們把變量改為 2 就可以了。導(dǎo)演類作為一個單例對象讓這個實現(xiàn)更加簡單,在 k-cocos.js 中寫入:

          //?游戲速率變量
          cc.director._kSpeed?=?1;

          var?_originCalculateDeltaTime?=?cc.Director.prototype.calculateDeltaTime;
          cc.director.calculateDeltaTime?=?function?(now)?{
          ????_originCalculateDeltaTime.call(this,?now);
          ????this._deltaTime?*=?this._kSpeed;
          }

          //?將方法掛到?cc?對象上
          cc.kSpeed?=?function?(speed)?{
          ????cc.director._kSpeed?=?speed;
          }

          因為是單例對象,直接為其聲明 _kSpeed 這個私有變量,然后重寫 calculateDeltaTime 方法,在調(diào)用保留后的原方法后進行一次乘法即可?。╟all 方法中的 this 換成 cc.director 也是一樣的,如果用箭頭函數(shù)記得改)

          為了不與未來引擎的接口沖突,所有擴展的屬性方法都加個 k 字母,這樣 cc.kSpeed() 就誕生啦!可以在任何地方愉快的進行 cc.kSpeed(0.3) 這種寫法了。

          效果圖:

          干脆開源吧

          實現(xiàn)了想要的效果,到這里文章其實應(yīng)該結(jié)束了,但是誰讓闊闊這么有奉獻精神,獨樂樂不如眾樂樂,論壇那么多人問游戲倍速的問題,干脆開源吧!名稱就叫 KCocos 擴展庫,再給自己設(shè)計一個圖標:

          不僅開源,再寫個文檔,寫就寫的高大上點!

          結(jié)語

          擴展腳本已經(jīng)開源,還實現(xiàn)了全局觸點數(shù)量控制、也擴展了節(jié)點的一些屬性和方法,還有許多想法沒加進去,比如 _hitTest 等!

          歡迎大家提建議、給點個星星 Star,歡迎加入討論 QQ 群:1085201157

          GitHub地址:https://github.com/KuoKuo666/k-cocos

          碼云地址:https://gitee.com/kuokuo666/k-cocos

          對應(yīng)文檔地址:https://kuokuo666.github.io

          2020!我們一起進步!O(∩_∩)O~~

          個人網(wǎng)站

          內(nèi)容也會同步 CSDN 與微信公眾號哦!

          www.kuokuo666.com

          微信公眾號


          瀏覽 74
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产女人看国产在线女人 | 插操视频 | 一级人妻人操 | 五月激情在线 | 无码一区一区 |