转让lua性能executeGlobalFunction
没有其他的,搞搞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的更多相关文章
- 怎么调试lua性能
怎么调试lua性能 我们的游戏使用的是Cocos2dx-lua 3.9的项目,最近发现我们的游戏.运行比较缓慢.想做一次性能优化了.其实主要分为GPU.CPU的分别优化.GPU部分的优化.网上有很多优 ...
- Lua性能优化
原文:Lua Performance Tips 偶然找到<Lua Performance Tips>这篇关于Lua的优化文章,个人认为相较于多数泛泛而谈要好不少.尽管Lua已经到5.2版本 ...
- Lua 性能相关笔记
1.创建一个闭合函数要比创建一个table更廉价,访问非局部的变量也比table字段更快. 2.访问局部变量要比全局变量更快,尽可能的使用局部变量,可以避免无用的名称引入全局环境. 3.do-end语 ...
- C++转让Lua
转载请注明出处:http://blog.csdn.net/zhy_cheng/article/details/39756423 我使用的cocos2d-x版本号是2.3.3.先在一个C++projec ...
- [Lua性能] 小试验一例
local s1 = os.clock() local list1 = {} , do list1[#list1 + ] = end local e1 = os.clock() print(" ...
- lua的性能优化
Roberto Ierusalimschy写过经典的Lua 性能提示的文章,链接地址>> 我通过实际的代码来验证,发现一个问题.当我使用 LuaStudio 运行时,发现结果反而与提示相反 ...
- 使用Lua 局部变量来优化性能,同一时候比較局部变量和全局变量
在竞争激烈的游戏行业中,尤其页游,面对策划复杂和频繁的需求,使用脚本能够减少难度和成本.在使用Lua的过程中,会常常訪问全局变量来作为配置文件. 在訪问全局变量时,能够通过局部变量引用全局变量来优化. ...
- Lua 架构 The Lua Architecture
转载自:http://magicpanda.net/2010/10/lua%E6%9E%B6%E6%9E%84%E6%96%87%E6%A1%A3/ Lua架构文档(翻译) 十 102010 前段时间 ...
- 深入浅出Lua虚拟机
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 作者:郑小辉 | 腾讯 游戏客户端开发高级工程师 写在前面:本文所有的文字都是我手工一个一个敲的,以及本文后面分享的Demo代码都是我一行一 ...
随机推荐
- Dubbo-Admin管理平台和Zookeeper注册中心的搭建(转)
林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubb ...
- Codeforces Round #258 (Div. 2) B. Sort the Array
题目链接:http://codeforces.com/contest/451/problem/B 思路:首先找下降段的个数,假设下降段是大于等于2的,那么就直接输出no,假设下降段的个数为1,那么就把 ...
- uva 1331 - Minimax Triangulation(dp)
option=com_onlinejudge&Itemid=8&page=show_problem&category=514&problem=4077&mosm ...
- 白板编程浅谈——Why, What, How(转)
原文链接:http://lucida.me/blog/whiteboard-coding-demystified/ 这篇文章节选自我正在撰写的一本关于应届生面试求职的书籍,欢迎在评论或微博(@peng ...
- CentOS配置smaba与Windows共享文件
操作环境:CentOS 6.5 64bit Linux与Linux间通过什么共享文件呢--NFS,Windows与Windows之间呢--共享文件功能就OK了,那Windows与Linux之间呢? 这 ...
- uva 1401 dp+Trie
http://uva.onlinejudge.org/index.php? option=com_onlinejudge&Itemid=8&page=show_problem& ...
- 对ESB概念的理解(转)
http://www.ibm.com/developerworks/cn/webservices/0811_magy_esb/ 什么是 ESB?ESB 严格来说不是某一个产品,而是一种框架,设计模式. ...
- 赵雅智_BroadcastReceiver短信监听
AndroidManifest.xml 注冊广播接收者 加入权限 <?xml version="1.0" encoding="utf-8"?> &l ...
- Android - 分享内容 - 接收其他APP的内容
就象程序可以发送数据给其他程序,所以也可以接收其他程序的数据.想一下用户如何和程序交互,以及想从其他程序接收什么样类型的数据.例如,一个社交程序可能对接收其他程序的文字(比如有趣的网址)感兴趣.Goo ...
- CF 444B(DZY Loves FFT-时间复杂度)
B. DZY Loves FFT time limit per test 1 second memory limit per test 256 megabytes input standard inp ...