遊戲人生(一),我的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 第一行,好了什麼都不用說了,相信你能明白這個儲存了。