1. 程式人生 > >遊戲人生(一),我的lua之旅:那些坑爹的CCBReaderLoad

遊戲人生(一),我的lua之旅:那些坑爹的CCBReaderLoad

首先,我們說說這個CCBReaderLoad。這個指令碼是cocos2dx自帶的一個lua+cocosbuilder 的工具,具體功能吶,往下看。

先來看下我遇到的一個問題:

————美工給了我一個.ccbi檔案,讓我放到遊戲裡去。

然後我們說說這個ccbi。ccbi是cocosbuilder繪製介面匯出的檔案,有興趣的同學可以自行去百度。我們來討論下如何用這個ccbi,以及ccbi中的坑。

先來看一段testlua的程式碼

TestMenusLayer = TestMenusLayer or {}
ccb["TestMenusLayer"] = TestMenusLayer

local function onMenuItemAClicked()
    if nil ~= TestMenusLayer["mMenuItemStatusLabelBMFont"] then
        local labelBmFt = tolua.cast(TestMenusLayer["mMenuItemStatusLabelBMFont"],"CCLabelBMFont")
        if nil ~= labelBmFt then
            labelBmFt:setString("Menu Item A clicked.");
        end
    end
end


local function onMenuItemBClicked()
    if nil ~= TestMenusLayer["mMenuItemStatusLabelBMFont"] then
        local labelBmFt = tolua.cast(TestMenusLayer["mMenuItemStatusLabelBMFont"],"CCLabelBMFont")
        if nil ~= labelBmFt then
            labelBmFt:setString("Menu Item B clicked.");
        end
    end
end


local function pressedC( ... )
    if nil ~= TestMenusLayer["mMenuItemStatusLabelBMFont"] then
        local labelBmFt = tolua.cast(TestMenusLayer["mMenuItemStatusLabelBMFont"],"CCLabelBMFont")
        if nil ~= labelBmFt then
            labelBmFt:setString("Menu Item C clicked.");
        end
    end
end
local function onMenuTestClicked()
    cclog("CCBMenuTest");
    local scene = CCScene:create()
    local  proxy = CCBProxy:create()
    local  node  = CCBuilderReaderLoad("cocosbuilderRes/ccb/ccb/TestMenus.ccbi",proxy,HelloCocosBuilderLayer)
    local  layer = tolua.cast(node,"CCLayer")
    if nil ~= HelloCocosBuilderLayer["mTestTitleLabelTTF"] then
        local ccLabelTTF = tolua.cast(HelloCocosBuilderLayer["mTestTitleLabelTTF"],"CCLabelTTF")
        if nil ~= ccLabelTTF then
            ccLabelTTF:setString("ccb/ccb/TestMenus.ccbi")
        end
    end
    if nil ~= scene then
        scene:addChild(layer)
        scene:addChild(CreateBackMenuItem())
        CCDirector:sharedDirector():pushScene(CCTransitionFade:create(0.5, scene, ccc3(0,0,0))); 
    end
end


TestMenusLayer["onMenuItemAClicked"] = onMenuItemAClicked
TestMenusLayer["onMenuItemBClicked"] = onMenuItemBClicked
TestMenusLayer["pressedC:"] = pressedC

看不懂沒關係,我們來解釋下這個段程式碼:

首先解釋

TestMenusLayer = TestMenusLayer or {}
ccb["TestMenusLayer"] = TestMenusLayer

這個是將ccbi元素儲存到TestMenusLayer這個table裡。具體實現我們後面在說。注意的是這個ccb["TestMenusLayer"] 就是ccbi結構中的根節點


然後再看

TestMenusLayer["onMenuItemAClicked"] = onMenuItemAClicked
TestMenusLayer["onMenuItemBClicked"] = onMenuItemBClicked
TestMenusLayer["pressedC:"] = pressedC

onMenuItemAClicked,onMenuItemBClicked,pressedC 這個不用多說是上面的回撥方法。lua中變數可以是方法。

TestMenusLayer["pressedC:"] 


其他兩個同理,這個是回撥需要的selector

需要注意以下幾點:

1、以上程式碼只適用於 doucment root/doc root var。

2、selector在ccbi中的數量要與方法中回撥數量一直,多或者少都會造成異常

3、如果出現介面顯示成功但是回撥失敗的情況,請檢測根節點是否書寫錯誤。

典型問題

Cocos2d: [LUA-print] LUA ERROR: [string "CCBReaderLoad.lua"]:73: attempt to concatenate local 'callbackName' (a userdata value)

Cocos2d: [LUA-print] stack traceback:

...1330379-BE60-47BF-8151-D8068E8D1DEB/Sok.app/src/main.lua:11: in function '__concat'

[string "CCBReaderLoad.lua"]:73: in function 'CCBuilderReaderLoad'

這個問題煩了我好幾天,搞的我頭的大了。 我們分析下這個東西,很明顯CCBReaderLoad.lua 73行,走起
73行,一行print,和日誌報的內容也不一樣,不管他,先註釋掉,然後再print(“123123”);

執行結果發現果然不再報錯了,日誌顯示了我們的123123.顯然這裡出了問題,我們看看什麼情況:67行if 是 function 顯然我們的回撥方法有的不被認為是方法。

根本原因是註冊的selector與回撥方法數量不一致。仔細檢查就會發現了。

最後我們在說說

TestMenusLayer = TestMenusLayer or {}
ccb["TestMenusLayer"] = TestMenusLayer


CCBReaderLoad 第一行,好了什麼都不用說了,相信你能明白這個儲存了。