cocos2dx中lua实现调用ccbi和动画等c++工具类

现在新版cocos2dx已经官方支持lua调用ccbi文件, 具体官方有例子

下面的文章已经用处不大




目前cocos2dx 暂时不支持lua调用高级的extensions类, 但是界面部分大量使用cocosbuilder,所以增加了lua支持ccbi和superanimation。

一。cocos2dx中C调lua函数:
CCLuaEngine* pEngine = CCLuaEngine::defaultEngine();
       pEngine->executeGlobalFunction(iter->second.c_str());    //必须是全局的,参数为函数的名字
/***********************************************************
二。lua调用c的函数:
用tolua++,编写pkg文件,生成cpp文件,
可以用一个pkg,include其他的pkg文件
例如
$#include "zsw_extension.h"
$pfile "CCBIFactory.pkg"
$pfile "SuperAnimNodeV2.pkg"
这样生成一个zsw_extension.cpp文件,
这里要注意一下:在使用回调lua函数的时候(registerScriptTapHandler)需要手动修改一个地方
 !tolua_isusertype(tolua_S,1,"SuperAnimNode",0,&tolua_err) ||
 (tolua_isvaluenil(tolua_S,2,&tolua_err) || !toluafix_isfunction(tolua_S,2,"LUA_FUNCTION",0,&tolua_err)) ||
 !tolua_isnoobj(tolua_S,3,&tolua_err)  (修改error的判断)
下面修改返回的是function
SuperAnimNode* self = (SuperAnimNode*)  tolua_tousertype(tolua_S,1,0);
 //int nHandler = ((int)  tolua_tonumber(tolua_S,2,0));
  LUA_FUNCTION funcID = (  toluafix_ref_function(tolua_S,2,0));
。。。
  self->registerScriptTapHandler(funcID);
让回调返回lua的函数
然后可以手动copy一个zsw_extension.h文件

#ifndef __LUAzsw_H_
#define __LUAzsw_H_

extern "C" {
#include "tolua++.h"
#include "tolua_fix.h"
}

#include <map>
#include < string>
#include "tolua_fix.h"
#include "cocos2d.h"
#include "CCLuaEngine.h"
#include "SimpleAudioEngine.h"
#include "../zgame/Animation.h"




using namespace cocos2d;
using namespace CocosDenshion;

TOLUA_API int tolua_ZgameLua_open(lua_State* tolua_S);

#endif // __LUAzsw_H_



再打开cocos2dx_support目录下面的CCLuaEngine.cpp
(copy这个文件到本地目录,然后在工程中加入该文件)
1.  添加
#include "zsw_extension.h"
2. 在init中加入我们生成的
bool CCLuaEngine::init(void)
{
   m_state = lua_open();
   luaL_openlibs(m_state);
   tolua_Cocos2d_open(m_state);
tolua_zsw_open(m_state);                                 //   (这里就是加入的函数)
之后lua就可以调用pkg编写的函数了
/****************************************************************************
三。ccb事件和回调处理方法


void GameUILayer::onNodeLoaded(cocos2d::CCNode * pNode,    cocos2d::extension::CCNodeLoader * pNodeLoader) {
}


SEL_MenuHandler GameUILayer::onResolveCCBCCMenuItemSelector(CCObject * pTarget, CCString * pSelectorName) {
       return NULL;
}

SEL_CCControlHandler GameUILayer::onResolveCCBCCControlSelector(CCObject * pTarget, CCString * pSelectorName) {

string name = pSelectorName->getCString();
       CCB_SELECTORRESOLVER_CCCONTROL_GLUE(this, name.c_str(), GameUILayer::onClicked);

       return NULL;
}

bool GameUILayer::onAssignCCBMemberVariable(CCObject * pTarget, CCString * pMemberVariableName, CCNode * pNode) {

       CCNode *button = NULL;
string name = pMemberVariableName->getCString();
       XIAOLEI_CCB_MEMBERVARIABLEASSIGNER_GLUE(this, name.c_str(), CCNode *, button);

       int index = name.find_first_of( '-', 0);
if (index != string::npos)
       {
               char* funcName = (char*) (( "set_" + name.substr(0,index)).c_str());
               char* typeName = (char*) name.substr(index+1).c_str();
            // CCLuaEngine* pEngine = CCLuaEngine::defaultEngine();
               registerCCBIMember(funcName, button, typeName);
       }

       objectNameMapping.insert(map<int, string>::value_type(button->m_uID, name));

       return false;
}

void GameUILayer::onClicked(CCObject * pSender, cocos2d::extension::CCControlEvent pCCControlEvent) {

       map<int, string>::iterator iter = objectNameMapping.find(pSender->m_uID);

if(iter != objectNameMapping. end())
       {
               CCLuaEngine* pEngine = (CCLuaEngine*)CCScriptEngineManager::sharedManager()->getScriptEngine();
//                pEngine->executeGlobalFunctionByShaoLei(iter->second.c_str(), pSender, (char*)iter->second.c_str(), pCCControlEvent);
               pEngine->executeGlobalFunction((iter->second+ "_onClicked").c_str());
       }
}

void GameUILayer::registerCCBIMember( const char* functionName, CCObject *obj, char* typeName)
{
   CCLuaEngine*    m_engine = (CCLuaEngine*)CCScriptEngineManager::sharedManager()->getScriptEngine();

   lua_State* m_state_ = m_engine->getLuaState();

 lua_getglobal(m_state_, functionName);                         /* query function by name, stack: function */
if (!lua_isfunction(m_state_, -1))
 {
   CCLOG( "[LUA ERROR] name '%s' does not represent a Lua function", functionName);
   lua_pop(m_state_, 1);
   return;
 }

 m_engine->pushCCObject(obj, typeName);

 int error = lua_pcall(m_state_, 1, 0, 0);                                                 /* call function, stack: ret */
if ( error)
 {
   CCLOG( "[LUA ERROR] %s", lua_tostring(m_state_, - 1));
   lua_pop(m_state_, 1); // clean error message
   return;
 }

}



四,lua部分代码

function second_change_onClicked()
       node:removeFromParentAndCleanup(true)

       local loader = CCBIFactory:create()
       node = loader:loadCCBI(sceneGame, "first.ccbi", "GameUILoader")
       sceneGame:addChild(node)

       return 0
end

function second_text_onClicked()
       second_text:setString("test")
       return 0
end


function set_second_text(obj)
       second_text = obj
end


五。ccb编辑注意名字:
1. 名字不能重复,因为lua都是全局的
2. button部分, CCBIfilename_keypress
button的seletor全部为固定的onClicked
调用lua函数对应为CCBIfilename_keypress_onClicked
3. 成员变量名字也不能重复,都是全局的
CCBIfilename_text-CCLabelTTF(后面跟-类型)
lua对应的函数set_CCBIfilename_text(obj)
以后就可以直接用obj里面赋值的对象来操作

by 孙少磊

你可能感兴趣的:(C++,cocos2d,lua,调用,cocos2d-x,tolua,lua_support)