cocos2d-x 血淚史(-1) CCNotificationCenter 與LUA


lua 是個很吊的語言,為什么這么說呢,因為大家都這么說... 而且貌似是為游戲而生,在官網(http://www.lua.org/)上還有各種各樣的lua 庫和工具可供使用,在cocos2d-x 的scripting 目錄下就可以找到cocos2d-x 提供的庫文件還有一個神奇的工具tolua (使用方法見:http://blog.csdn.net/musicvs/article/details/8166572

 

等等,好像標題有點奇怪,-1 是幾個意思。。 恩。。其實最近發現騰訊出了款打飛機的游戲整合了天天酷跑里面那些道具坐騎(寵物)角色各式各樣的關卡和敵人當然還少不了好友攀比系統,我只能說。。太tm吊了!!!所以我的打飛機的游戲感覺沒多大意思了,不過我還是會做下去的。-1 呢就是遇到的些個問題分條就在這說了,因為沒那么多時間去寫系列,等系列的進度碰到這些個問題的時候再引用過來好了。。。^_^

 

我的本意是游戲的主框架用cpp 寫然后技能,關卡什么的用lua 寫,為什么呢,我說我為了學lua 你信么。。

那么技能什么的怎么用lua 寫呢,構想如下:

當釋放技能(觸摸到技能圖標)時,主框架會使用CCNotificationCenter 的

void CCNotificationCenter::postNotification(const char *name, CCObject *object)

方法來做個廣播,然后lua 里接收這個msg 做出響應,這個CCObject* 的參數可以傳進去一個CCDictionary* 包含技能釋放者實例,消耗的怒氣值等等數據。順便提一下在cocos2d-x 3.0 里這里參數名是CCObject* sender,大概是想說明只傳入個sender 就行了或者還有其他設計方面的考慮?不明求各位看官解釋。。。

然后就想寫個小demo 驗證下這個想法是否可行。。好吧開始行動

首先要讓當前項目支持lua,去到下載的cocos2d-x 目錄下把scripting 這個文件夾拷到項目里與cocos2dx,CocosDenshion 什么的同目錄,然后把scripting\lua\proj.win32 里的proj 添加到solution。像這樣:

當然這是不夠的,右鍵你的項目->屬性,C/C++ ->Additional Include Directories 里面加上那坨目錄:

當然Linker->Input->Additional Dependencies 這里也要加上一坨東西:

注意websockets.lib 在external\libwebsockets\win32 這里由於沒有見到源文件(*.cpp),所以要么把這里lib 目錄加到項目的lib 目錄,要么直接把external\libwebsockets\win32\lib 里的東西全拷到項目輸出目錄Debug.win32 下面也行。

然后build 這個liblua~ok 沒問題。

接下來在項目的AppDelegate 里加上一方法:

 void AppDelegate::InitLuaEngine()
 2 {
 3     // register lua engine
 4     CCLuaEngine* pEngine = CCLuaEngine::defaultEngine();
 5     CCScriptEngineManager::sharedManager()->setScriptEngine(pEngine);
 6 
 7     CCLuaStack *pStack = pEngine->getLuaStack();
 8     lua_State *tolua_s = pStack->getLuaState();
 9     tolua_extensions_ccb_open(tolua_s);
10 #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)    
11     pStack = pEngine->getLuaStack();
12     tolua_s = pStack->getLuaState();
13     tolua_web_socket_open(tolua_s);
14 #endif
15         
16     std::vector<std::string> searchPaths = CCFileUtils::sharedFileUtils()->getSearchPaths();
17     searchPaths.push_back("script");
18     CCFileUtils::sharedFileUtils()->setSearchPaths(searchPaths);
19     CCLog("Lua Engine Initialized.");
20 }

當然頭文件里要加上這么一段:

1 // AppDelegate.h
2 #include "CCLuaEngine.h"
3 #include "Lua_extensions_CCB.h"
4 #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
5 #include "Lua_web_socket.h"
6 #endif

接下來因為我們往searchPaths 里面塞了一個"script",所以在資源目錄下新建個"script" 的文件夾再在里面建個lua 文件就叫"registerNotification.lua" 好了...

然后模仿hellolua (cocos2d-x 自帶的template)往里面塞上這樣一些奇怪的東西:

cclog = function(...)
    print(string.format(...))
end

local LUA_TEST_MSG = "LUA TEST MSG"
local kCCNodeOnEnter = "enter"
local kCCNodeOnExit = "exit"

function __G__TRACKBACK__(msg)
    cclog("----------------------------------------")
    cclog("LUA ERROR: " .. tostring(msg) .. "\n")
    cclog(debug.traceback())
    cclog("----------------------------------------")
end

local function regNotification()
    local ccLayer = CCLayer:create();
    
    local function testNotificationHandler(obj)
        cclog("GOT MSG"  .. 1)
    end
    local function testNotificationHandler2(obj)
        cclog("GOT MSG"  .. 2)
    end
    
    local function onEnter()
        cclog("ON ENTER")
        CCNotificationCenter:sharedNotificationCenter():registerScriptObserver(ccLayer, testNotificationHandler, LUA_TEST_MSG)
        CCNotificationCenter:sharedNotificationCenter():registerScriptObserver(ccLayer, testNotificationHandler2, LUA_TEST_MSG)
    end
    
    local function onExit()
        cclog("ON EXIT")
        CCNotificationCenter:sharedNotificationCenter():unregisterScriptObserver(ccLayer, LUA_TEST_MSG)
    end
    
    local function eventHandler(eventType)
        cclog("ON EVENT: " .. eventType)
        if eventType == kCCNodeOnEnter then
            onEnter()
        elseif eventType == kCCNodeOnExit then
            onExit()
        end
    end
    
    ccLayer:registerScriptHandler(eventHandler)
    return ccLayer
end
local function regNotification2()
    local ccLayer = CCLayer:create();
    
    local function testNotificationHandler(obj)
        cclog("GOT MSG" .. 3)
    end
    local function testNotificationHandler2(obj)
        cclog("GOT MSG" .. 4)
    end
    
    local function onEnter()
        cclog("ON ENTER")
        CCNotificationCenter:sharedNotificationCenter():registerScriptObserver(ccLayer, testNotificationHandler, LUA_TEST_MSG)
        CCNotificationCenter:sharedNotificationCenter():registerScriptObserver(ccLayer, testNotificationHandler2, LUA_TEST_MSG)
    end
    
    local function onExit()
        cclog("ON EXIT")
        CCNotificationCenter:sharedNotificationCenter():unregisterScriptObserver(ccLayer, LUA_TEST_MSG)
    end
    
    local function eventHandler(eventType)
        cclog("ON EVENT: " .. eventType)
        if eventType == kCCNodeOnEnter then
            onEnter()
        elseif eventType == kCCNodeOnExit then
            onExit()
        end
    end
    
    ccLayer:registerScriptHandler(eventHandler)
    return ccLayer
end

local function main()
    cclog("LUA Main running with version: " .. _VERSION)
    local layer = regNotification()
    local layer2 = regNotification2()
    local currentScene = CCDirector:sharedDirector():getRunningScene();
    currentScene:addChild(layer)
    currentScene:addChild(layer2)
    cclog("layer added.")
end

xpcall(main, __G__TRACKBACK__)


就是往當前scene 里加上兩個layer,這兩個layer 都注冊了兩次同一個msg,然后在主程序里隨便哪里放一個按鈕或是menuItem,叫做button1吧,按鈕回調里寫上

        CCScriptEngineManager::sharedManager()->getScriptEngine()->executeScriptFile("registerNotification.lua");

另外旁邊再放一個menuItem叫做button2,回調里寫上

        CCNotificationCenter::sharedNotificationCenter()->postNotification("LUA TEST MSG", CCLayer::create());


啊哈,看起來不錯,運行下看看吧。

先點下button2

[LUA-print] LUA Main running with version: Lua 5.1
[LUA-print] ON EVENT: enter
[LUA-print] ON ENTER
[LUA-print] ON EVENT: enterTransitionFinish
[LUA-print] ON EVENT: enter
[LUA-print] ON ENTER
[LUA-print] ON EVENT: enterTransitionFinish
[LUA-print] layer added.

然后是button1

[LUA-print] GOT MSG1
[LUA-print] GOT MSG1

MSG3 哪里去了?! 問題來了~ 對於同一個target,一個msg 只能被注冊一次,對於不同的target,注冊多次也只會回調第一次注冊的那個方法,so~
於是我把問題拋到了cocos2d-x 的官方論壇並且附上了自己的解決方法:http://www.cocos2d-x.org/forums/11/topics/44010?r=44973#message-44973

然后laurentzubiaur 這位大神給出了不用修改cocos2d 源代碼的解決方法,在lua 里把CCNotificationCenter 包上一層,喲西,太吊了!!!然后就沒有然后了...


免責聲明!

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



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