轉讓lua效能executeGlobalFunction

來源:互聯網
上載者:User

標籤:

沒有其他的,搞搞cocos2dx的lua文字,話lua這件事情在幾年前學過一段時間。還曾對自己c++介面,我已經做了一些小東西。只是時間的流逝,模糊記憶。

拿起點功夫和成本。下面是我的一些經驗。


cocos2dx運用tolua++來製作的lua介面,tolua++文檔不多,網上的一些文章也是答非所問,所以自己看代碼是最佳學習途徑。




cocos2dx操作lua的類是CCLuaEngine,當中實現了載入與實行lua指令碼。以及操作lua stack。




LuaCocos2d.cpp非常主要,檔案的開頭凝視也說明其是由tolua++自己主動產生的,我們想在lua中操作自訂的類就是通過改動此檔案實現的,兩個重要函數是void tolua_reg_types (lua_State* tolua_S)與int tolua_Cocos2d_open (lua_State* tolua_S),前者是注冊自訂類型,後者是定義其介面,調用關係是tolua_Cocos2d_open調用tolua_reg_types,而tolua_Cocos2d_open是在CCLuaEngine的init中調用的。




如果我要向lua注冊新類。那麼首先我要在tolua_reg_types中加入一行注冊代碼,然後在tolua_Cocos2d_open加入其介面說明。我將這兩個步驟定義成兩個函數,單獨在一個檔案裡實現。檔案名稱為cwLuaReg.cpp,內容為:
#include "cwLuaReg.h"


#include "cwGameObject.h"
#include "cwCollisionObject.h"
#include "cwGravityObject.h"


#ifdef __cplusplus


static int tolua_collect_cwGameObject(lua_State* tolua_S)
{
    cwGameObject* self = (cwGameObject*) tolua_tousertype(tolua_S,1,0);
    delete self;
    return 0;
}


static int tolua_collect_cwGravityObject(lua_State* tolua_S)
{
    cwGravityObject* self = (cwGravityObject*) tolua_tousertype(tolua_S,1,0);
    delete self;
    return 0;
}


#ifndef TOLUA_DISABLE_tolua_cw_GameObject_create00
static int tolua_cw_GameObject_create00(lua_State* tolua_S)
{
    tolua_Error tolua_err;
    if(!tolua_isusertable(tolua_S,1,"cwGameObject",0,&tolua_err) ||
        !tolua_isnoobj(tolua_S,2,&tolua_err))
        goto tolua_lerror;
    else
    {
        {
            cwGameObject* tolua_ret = (cwGameObject*)  cwGameObject::create();
            int nID = (tolua_ret) ? (int)tolua_ret->m_uID : -1;
            int* pLuaID = (tolua_ret) ?

&tolua_ret->m_nLuaID : NULL;
            toluafix_pushusertype_ccobject(tolua_S, nID, pLuaID, (void*)tolua_ret,"cwGameObject");
        }
    }
    return 1;
tolua_lerror:
    return 0;
}
#endif //#ifndef TOLUA_DISABLE


#ifndef TOLUA_DISABLE_tolua_cw_GameObject_getSpeed00
static int tolua_cw_GameObject_getSpeed00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
    tolua_Error tolua_err;
    if (!tolua_isusertype(tolua_S,1,"cwGameObject",0,&tolua_err) ||
        !tolua_isnoobj(tolua_S,2,&tolua_err))
        goto tolua_lerror;
    else
#endif
    {
        cwGameObject* self = (cwGameObject*)  tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
        if (!self) tolua_error(tolua_S,"invalid ‘self‘ in function ‘speed‘", NULL);
#endif
        {
            float tolua_ret = (float)  self->speed();
            tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
        }
    }
    return 1;
#ifndef TOLUA_RELEASE
    tolua_lerror:
    tolua_error(tolua_S,"#ferror in function ‘speed‘.",&tolua_err);
    return 0;
#endif
}
#endif


#ifndef TOLUA_DISABLE_tolua_cw_GameObject_setSpeed00
static int tolua_cw_GameObject_setSpeed00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
    tolua_Error tolua_err;
    if (!tolua_isusertype(tolua_S,1,"cwGameObject",0,&tolua_err) ||
        !tolua_isnumber(tolua_S,2,0,&tolua_err) ||
        !tolua_isnoobj(tolua_S,3,&tolua_err))
        goto tolua_lerror;
    else
#endif
    {
        cwGameObject* self = (cwGameObject*)  tolua_tousertype(tolua_S,1,0);
        float speed = ((float)  tolua_tonumber(tolua_S,2,0));
#ifndef TOLUA_RELEASE
        if (!self) tolua_error(tolua_S,"invalid ‘self‘ in function ‘setSpeed‘", NULL);
#endif
        {
            self->setSpeed(speed);
        }
    }
    return 0;
#ifndef TOLUA_RELEASE
    tolua_lerror:
    tolua_error(tolua_S,"#ferror in function ‘setSpeed‘.",&tolua_err);
    return 0;
#endif
}
#endif


#ifndef TOLUA_DISABLE_tolua_cw_GameObject_getMoveDir00
static int tolua_cw_GameObject_getMoveDir00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
    tolua_Error tolua_err;
    if (!tolua_isusertype(tolua_S,1,"cwGameObject",0,&tolua_err) ||
        !tolua_isnoobj(tolua_S,2,&tolua_err))
        goto tolua_lerror;
    else
#endif
    {
        cwGameObject* self = (cwGameObject*)  tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
        if (!self) tolua_error(tolua_S,"invalid ‘self‘ in function ‘getMoveDir‘", NULL);
#endif
        cwVector2D& dir = self->moveDir();
        tolua_pushnumber(tolua_S,(lua_Number)dir.x);
        tolua_pushnumber(tolua_S,(lua_Number)dir.y);
    }
    return 2;
#ifndef TOLUA_RELEASE
    tolua_lerror:
    tolua_error(tolua_S,"#ferror in function ‘getMoveDir‘.",&tolua_err);
    return 0;
#endif
}
#endif


#ifndef TOLUA_DISABLE_tolua_cw_GameObject_setMoveDir00
static int tolua_cw_GameObject_setMoveDir00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
    tolua_Error tolua_err;
    if (!tolua_isusertype(tolua_S,1,"cwGameObject",0,&tolua_err) ||
        !tolua_isnumber(tolua_S,2,0,&tolua_err) ||
        !tolua_isnumber(tolua_S,3,0,&tolua_err) ||
        !tolua_isnoobj(tolua_S,4,&tolua_err))
        goto tolua_lerror;
    else
#endif
    {
        cwGameObject* self = (cwGameObject*)  tolua_tousertype(tolua_S,1,0);
        float dirX = ((float)  tolua_tonumber(tolua_S,2,0));
        float dirY = ((float)  tolua_tonumber(tolua_S,3,0));
#ifndef TOLUA_RELEASE
        if (!self) tolua_error(tolua_S,"invalid ‘self‘ in function ‘setMoveDir‘", NULL);
#endif
        self->setMoveDir(dirX, dirY);
    }
    return 0;
#ifndef TOLUA_RELEASE
    tolua_lerror:
    tolua_error(tolua_S,"#ferror in function ‘getMoveDir‘.",&tolua_err);
    return 0;
#endif
}
#endif


#endif


TOLUA_API int tolua_cwLua_reg_types(lua_State* tolua_S)
{
    //add by sunny
    tolua_usertype(tolua_S,"cwGameObject");
    tolua_usertype(tolua_S,"cwGravityObject");
    //end sunny


    return 1;
}


TOLUA_API int tolua_cwLua_reg(lua_State* tolua_S)
{
#ifdef __cplusplus
    tolua_cclass(tolua_S,"cwGameObject","cwGameObject","CCSprite",tolua_collect_cwGameObject);
#else
    tolua_cclass(tolua_S,"cwGameObject","cwGameObject","CCSprite",NULL);
#endif


    tolua_beginmodule(tolua_S,"cwGameObject");
    tolua_function(tolua_S,"create",tolua_cw_GameObject_create00);
    tolua_function(tolua_S,"speed",tolua_cw_GameObject_getSpeed00);
    tolua_function(tolua_S,"setSpeed",tolua_cw_GameObject_setSpeed00);
    tolua_function(tolua_S,"moveDir",tolua_cw_GameObject_getMoveDir00);
    tolua_function(tolua_S,"setMoveDir",tolua_cw_GameObject_setMoveDir00);
    tolua_endmodule(tolua_S);


#ifdef __cplusplus
    tolua_cclass(tolua_S,"cwGravityObject","cwGravityObject","cwGameObject",tolua_collect_cwGravityObject);
#else
    tolua_cclass(tolua_S,"cwGravityObject","cwGravityObject","cwGameObject",NULL);
#endif


    tolua_beginmodule(tolua_S,"cwGravityObject");
    tolua_endmodule(tolua_S);


    return 1;
}


將tolua_cwLua_reg_types和tolua_cwLua_reg分別加到LuaCocos2d.cpp相應函數末尾。這樣兩個類cwGameObject與cwGravityObject就能夠在lua中使用了。




做到這還不能達到我的期望,原因是cocos2d的luaproject裡。在AppDelegate::applicationDidFinishLaunching函數中僅僅是載入並運行了hello.lua指令檔。然後一切就都交給lua了,而我僅僅是想使用lua實現一些AI方面的功能,即cwGameObject在須要運行AI時。調用lua中的一個函數。所以我須要的是一個能夠調用lua函數的功能,查看了一下CCLuaEngine類。貌似沒有我想要的。僅僅能自己添了個函數:
virtual int executeGlobalFunction(const char* functionName, float dt, CCObject* pObject, const char* typeName);
functionName:被調lua函數名;dt:幀時間間隔。pObject:調用lua的對象;typeName:pObject物件類型
實現例如以下:
int CCLuaEngine::executeGlobalFunction(const char* functionName, float dt, CCObject* pObject, const char* typeName)
{
    lua_getglobal(m_state, functionName);      


    if (!lua_isfunction(m_state, -1))
    {
        CCLOG("[LUA ERROR] name ‘%s‘ does not represent a Lua function", functionName);
        lua_pop(m_state, 1);
        return 0;
    }


    pushFloat(dt);
    pushCCObject(pObject, typeName);


    int error = lua_pcall(m_state, 2, 1, 0);            


    if (error)
    {
        CCLOG("[LUA ERROR] %s", lua_tostring(m_state, - 1));
        lua_pop(m_state, 1); // clean error message
        return 0;
    }


    // get return value
    if (!lua_isnumber(m_state, -1))
    {
        lua_pop(m_state, 1);
        return 0;
    }


    int ret = lua_tointeger(m_state, -1);
    lua_pop(m_state, 1);                                               
    return ret;
}
基本上是照著其它函數扒下來的,不同之處就是加了兩個push。
函數寫的比較死。能夠寫一個接受可變參數的函數,做的通用些。


如果我要在cwGameObject的upadte函數中調用“do_obj_update”lua函數,寫法例如以下:
void cwGameObject::update(float dt)
{
    CCLuaEngine::defaultEngine()->executeGlobalFunction("do_obj_update", dt, this,"cwGameObject");
}
這樣在建立cwGameObject時scheduleUpdate一下就能夠了。


lua指令碼:
-- for CCLuaEngine traceback
function __G__TRACKBACK__(msg)
    print("----------------------------------------")
    print("LUA ERROR: " .. tostring(msg) .. "\n")
    print(debug.traceback())
    print("----------------------------------------")
end


winSize = CCDirector:sharedDirector():getWinSize()


-- avoid memory leak
collectgarbage("setpause", 100)
collectgarbage("setstepmul", 5000)


function do_obj_update(dt, obj)
    local x, y = obj:getPosition()
    local vx, vy = obj:moveDir()


    x = x + vx*dt*obj:speed()
    y = y + vy*dt*obj:speed()


    if x < 0 then
        x = 0
        obj:setMoveDir(-vx, vy)
    end


    if x > winSize.width then
        x = winSize.width
        obj:setMoveDir(-vx, vy)
    end
   
    if y < 0 then
        y = 0
        obj:setMoveDir(vx, -vy)
    end


    if y > winSize.height then
        y = winSize.height
        obj:setMoveDir(vx, -vy)
    end


    obj:setPosition(x, y)
end


print("test.lua loaded.")


指令碼非常easy,do_obj_update函數僅僅是做了一些邊框推斷。
別忘了改動AppDelegate::applicationDidFinishLaunching載入指令檔名~~


cocos2dx版本號碼:cocos2d-2.0-x-2.0.3


http://blog.csdn.net/honghaier/article/details/8700574

轉讓lua效能executeGlobalFunction

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.