Cocos Creator 實現大廳+子游戲模式


  大廳+子游戲的模式,在棋牌類型、教育類型游戲中比較常見,通常是安裝包里面只有大廳的資源和代碼,然后子游戲根據需求以熱更新的方式下載來提供給玩家。

  之前一直負責的是cocos2dx-lua的開發,lua作為腳本語言,非常適合做熱更新及大廳+子游戲模式的開發。而cocos creator使用的是js或者ts,作為腳本語言也是很方便做熱更新的,但是js編譯是把所有的腳本編譯成一個單獨的js文件,如果不做調整,會導致所有的大廳+游戲代碼編譯成一個單獨的js文件,是不太方便做成大廳+子游戲的模式的,這里要討論的就是如何調整,以做成大廳+子游戲的模式。

  首先就是要將大廳、子游戲分開來構建了,要不就是創建單獨的大廳+子游戲工程,要不就是將大廳或者子游戲的代碼、資源拷貝到一個構建工程,然后用命令行工具或者直接使用GUI工具構建。我這邊沒有單獨分開創建工程,選擇的是在構建的時候通過腳本拷貝相關的資源,然后單獨構建。

  分開構建/編譯好了資源之后,就是在app中怎么使用了。在lua版本中,引擎的資源加載方式是直接讀取指定目錄的腳本/資源,所以我們只要先將子游戲的腳本/資源下載好,再引入指定目錄的腳本就可以了。js作為腳本資源,思路上我們也是讀取對應目錄的腳本,但是在creator版本中,引擎封裝了一套資源加載工具,每個資源對應一個uuid,訪問資源的時候是使用uuid去尋找資源(我們使用cc.loader.loadRes傳入的是帶資源目錄的url,內部會根據這個url找到uuid再來加載資源),構建/編譯項目的時候,會生成一個setting.js/jsc的文件,這個文件就是uuid和實際資源路徑的對應表。所以我們需要做的就是如何引入子游戲生成的這個setting文件。參考論壇網友的思路,就是引入另外一個js腳本,在該腳本中再去讀取對應子游戲的setting文件,合並到大廳的setting配置中,然后再跳轉到對應的游戲場景,上代碼:

    // 首先還是要設置好搜索路徑
    var searchPaths = jsb.fileUtils.getSearchPaths();
    searchPaths.unshift(cc.JS_DIR);
    jsb.fileUtils.setSearchPaths(searchPaths); 
    
    // 判斷是否已經加載過子游戲的setting
    if (!cc.gameSetting){
        window.require(js_path + 'src/settings.js');
        settings = window._CCSettings;
        window._CCSettings = undefined;

        // 防止重復加載腳本
        if (!cc.jsList[js_path]){
            require(js_path + 'src/' + (settings.debug ? 'project.dev.js' : 'project.js'));
            cc.jsList[js_path] = true
        }
    }
    else{
        settings = cc.gameSetting
    }
            
    // 合並assetTypes
    var gameAssetTypes = settings.assetTypes;
    settings.assetTypes = baseSetting.assetTypes;
    if (gameAssetTypes && settings.assetTypes){
        for (var typeIndex in gameAssetTypes) {
            var type = gameAssetTypes[typeIndex];
            //不包含就塞到settings里面去
            if (settings.assetTypes.indexOf(type) == -1) {
                settings.assetTypes.push(type);
            }
        }
        for (var uuidKey in settings.rawAssets.assets) {
            var index = settings.rawAssets.assets[uuidKey][1];
            var type1 = gameAssetTypes[index];

            for (var typeIndex in settings.assetTypes) {
                var type2 = settings.assetTypes[typeIndex];
                if (type1 == type2) {
                    settings.rawAssets.assets[uuidKey][1] = parseInt(typeIndex);
                }
            }
        }
    }    
    // 調整資源配置
    for (var assetkey in baseSetting.packedAssets) {
        settings.packedAssets[assetkey] = baseSetting.packedAssets[assetkey];
    }
    //動態資源合並
    for (var uuidKey in baseSetting.rawAssets.assets) {        
        settings.rawAssets.assets[uuidKey] = baseSetting.rawAssets.assets[uuidKey];
    }
    //場景合並
    for (var sceneKey in baseSetting.scenes) {
        if (settings.scenes.indexOf(baseSetting.scenes[sceneKey]) == -1){
            settings.scenes.push(baseSetting.scenes[sceneKey]);
        }        
    }
    // uuid合並
    for (var uuidKey in baseSetting.uuids) {
        if (settings.uuids.indexOf(baseSetting.uuids[uuidKey]) == -1) {
            settings.uuids.push(baseSetting.uuids[uuidKey])
        }
    }

  上述代碼是在論壇網友提供的demo基礎上進行了部分調整,核心的邏輯還是一致的:主要就是讀取對應子游戲的setting文件,然后合並到大廳的setting中,建立好子游戲資源的uuid對應關系,主要就能在游戲中引入對應的游戲資源。

  論壇網友提供的demo中,從子游戲回到大廳,需要再引入一份獨立的js文件。但是我的理解是,在啟動大廳的時候已經將大廳的setting加入到內存中了,資源和uuid的對應關系已經建立,這個時候其實已經沒有必要再重復引入一次大廳的setting配置,再來合並。實際項目上,我也是按照我的理解,沒有再單獨的引入js文件實現從子游戲回到大廳,目前也暫時沒有碰到問題。

  另外,因為思路上是大廳和子游戲要分開打包,在開發的過程中我們是可以大廳+子游戲一起開發。但是要注意的是,子游戲不能直接在編輯器中引用大廳的資源,比如子游戲的某個腳本是繼承自大廳的,,如:

cc.Class({
    extends:  bg.GameModel,
    ...
})

  GamModel是大廳工程的代碼,在開發的過程中,因為子游戲和大廳在一個工程,這樣直接使用是沒有問題的。如果將子游戲單獨打包,在構建的過程中會報錯,不過還是能構建成功,但是在運行的時候這個腳本組件就不會綁定到對應的節點上去,所以應該調整一下:

cc.Class({
    extends: window.bg == undefined ? cc.Component : bg.GameModel,
    ...
)}

  這樣構建的過程中不會報錯,腳本組件能正常的綁定到對應的節點上去。運行過程中因為已經加載了大廳的代碼,所以這個三目運算的結果是取后面的bg.GameModel。

  

  實現環境:Cocos Creator 2.0.9 版本。之前使用2.10版本,同樣的代碼構建的工程,在win32模擬器上就會一直報錯,自帶模擬器對應的src目錄下的modular.js會出現錯誤,后來換成2.0.9版本,自編譯win32工程,再用模擬器運行就沒有問題了。在安卓和ios上到是都正常的。


免責聲明!

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



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