刚开始接触cocos2d-x 下的Lua编程,主要参看了李华明大神的博客中的介绍,http://blog.csdn.net/xiaominghimi/article/category/1155088 大概了解了一下,下面这篇博客主要记录一下如何在Cocos2d-x项目中使用Lua进行开发,还有在Lua中如何使用自定义的精灵类(Lua脚本和自创建类之间的访问)这两个内容;这些内容在李华明大神的博客中都有详细的介绍,个人看我觉得有点乱,所以写下这篇入门博客。

一、如何在Cocos2d-x项目中使用Lua进行开发

首先创建一个带有Lua的Cocos2d-x项目,在资源目录下就会看到两个lua文件,hello.lua和hello2.lua,在hello.lua这个文件中就实现了一个简单的demo,关于这个文件中的内容结构大致如下

其中的xpcall就是程序的入口,官方解释如下:

xpcall(f,err):

This function is similar to pcall, except that you can set a new error handler.

xpcall calls function f in protected mode, using err as the error handler. Any error inside f is not propagated; instead, xpcall catches the error, calls the err function with the original error object, and returns a status code. Its first result is the status code (a boolean), which is true if the call succeeds without errors. In this case, xpcall also returns all results from the call, after this first result. In case of any error, xpcall returns false plus the result from err.

至于hello2.lua这个文件,没有什么内容(只有一个函数),主要是为了体现require的用法。

那么项目中是如何调用lua代码的呢?-----在Classes目录下的AppDelegate.m文件中的 applicationDidFinishLaunching 方法中,就可以看到是如何进行调用的了。

// register lua engine
CCLuaEngine* pEngine = CCLuaEngine::defaultEngine();
CCScriptEngineManager::sharedManager()->setScriptEngine(pEngine); std::string path = CCFileUtils::sharedFileUtils()->fullPathForFilename("hello.lua");
pEngine->executeScriptFile(path.c_str());

下面用以下代码替换hello.lua文件中的所以代码:

--这是一个简单的demo

--这个函数用于创建layer
local function creatLayer() visibleSize = CCDirector:sharedDirector():getWinSize()
origin = CCDirector:sharedDirector():getVisibleOrigin() local layer = CCLayer:create() local myLabel = CCLabelTTF:create("This is a demo!","Arial",35)
myLabel:setPosition(origin.x + visibleSize.width / 2 , origin.y + visibleSize.height / 2)
layer:addChild(myLabel) local sprite = CCSprite:create("Icon.png")
sprite:setPosition(origin.x + visibleSize.width / 2 , origin.y + visibleSize.height / 2+50)
layer:addChild(sprite)
return layer end --创建一个scene并调用上面的函数添加一个layer
local sceneGame = CCScene:create()
sceneGame:addChild(creatLayer()) -- run
CCDirector:sharedDirector():runWithScene(sceneGame)

这段代码很简单吧!运行程序,在界面中显示一个label和一个sprite。

脚本lua等一般都示通过中间层(解析)进行与前端代码(Cocos2dX封装的引擎类库)交互,所以很多方法名称可能发生了改变,假如我们不知道它的构造函数是否有修改,或者说参数忘记都是什么了,那么请打开下图中的 LuaCocos2d.cpp文件,(注意这个文件代码很多,打开较慢)然后你会看到很多方法的定义与实现!

我们搜索 CCLabelTTF的构造方法,那么搜一下如下语句:tolua_beginmodule(tolua_S,"CCLabelTTF");

这样就可以看到大批类似的方法:

tolua_beginmodule(tolua_S,"CCLabelTTF");
tolua_function(tolua_S,"new",tolua_Cocos2d_CCLabelTTF_new00);
tolua_function(tolua_S,"new_local",tolua_Cocos2d_CCLabelTTF_new00_local);
tolua_function(tolua_S,".call",tolua_Cocos2d_CCLabelTTF_new00_local);
tolua_function(tolua_S,"delete",tolua_Cocos2d_CCLabelTTF_delete00);
tolua_function(tolua_S,"init",tolua_Cocos2d_CCLabelTTF_init00);
tolua_function(tolua_S,"setString",tolua_Cocos2d_CCLabelTTF_setString00);
tolua_function(tolua_S,"getString",tolua_Cocos2d_CCLabelTTF_getString00);
tolua_function(tolua_S,"getHorizontalAlignment",tolua_Cocos2d_CCLabelTTF_getHorizontalAlignment00);
tolua_function(tolua_S,"setHorizontalAlignment",tolua_Cocos2d_CCLabelTTF_setHorizontalAlignment00);
tolua_function(tolua_S,"getVerticalAlignment",tolua_Cocos2d_CCLabelTTF_getVerticalAlignment00);
tolua_function(tolua_S,"setVerticalAlignment",tolua_Cocos2d_CCLabelTTF_setVerticalAlignment00);
tolua_function(tolua_S,"getDimensions",tolua_Cocos2d_CCLabelTTF_getDimensions00);
tolua_function(tolua_S,"setDimensions",tolua_Cocos2d_CCLabelTTF_setDimensions00);
tolua_function(tolua_S,"getFontSize",tolua_Cocos2d_CCLabelTTF_getFontSize00);
tolua_function(tolua_S,"setFontSize",tolua_Cocos2d_CCLabelTTF_setFontSize00);
tolua_function(tolua_S,"getFontName",tolua_Cocos2d_CCLabelTTF_getFontName00);
tolua_function(tolua_S,"setFontName",tolua_Cocos2d_CCLabelTTF_setFontName00);
tolua_function(tolua_S,"create",tolua_Cocos2d_CCLabelTTF_create00);
tolua_function(tolua_S,"create",tolua_Cocos2d_CCLabelTTF_create01);
tolua_function(tolua_S,"create",tolua_Cocos2d_CCLabelTTF_create02);
tolua_function(tolua_S,"create",tolua_Cocos2d_CCLabelTTF_create03);
tolua_endmodule(tolua_S);

这里就是此类的所有 lua-cocos2dx之间的转换函数定义,比如常用的CCLabelTTF中的setString这个方法:

   tolua_function(tolua_S,"setString",tolua_Cocos2d_CCLabelTTF_setString00);

此函数第一参数大家不用理会,第二个参数表示我们使用cocos2d-x时调用的函数名称,后面则是lua-cocos2dx之间的转换函数实现代码,大家可以继续搜索第三个参数或者按住command然后点击第三个参数找到其函数实现代码:

/* method: setString of class  CCLabelTTF */
#ifndef TOLUA_DISABLE_tolua_Cocos2d_CCLabelTTF_setString00
static int tolua_Cocos2d_CCLabelTTF_setString00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"CCLabelTTF",0,&tolua_err) ||
!tolua_isstring(tolua_S,2,0,&tolua_err) ||
!tolua_isnoobj(tolua_S,3,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
CCLabelTTF* self = (CCLabelTTF*) tolua_tousertype(tolua_S,1,0);
const char* label = ((const char*) tolua_tostring(tolua_S,2,0));
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'setString'", NULL);
#endif
{
self->setString(label);
}
}
return 0;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'setString'.",&tolua_err);
return 0;
#endif
}

注意到其中的:
self->
setString
(label); 继续按住Command然后点击setString就可以进入cocos2d-x引擎代码 CCLabelTTF.cpp中的此函数实现啦!

从上面的这个过程来看,执行lua程序的过程大致是:解析lua脚本中的一句代码->通过解析层代码->将其转换并转到前端代码进行使用。

二、在Lua中如何使用自定义的精灵类(Lua脚本和自创建类之间的访问)

关于这个问题,在李华明的文章中进行了详细的介绍(个人觉得有点乱)http://blog.csdn.net/xiaominghimi/article/details/7936395  和  http://blog.csdn.net/xiaominghimi/article/details/8770396 ,这里只是个人练习的时候的一些记录。

(1)首先在项目中添加一个自定义的精灵类HSprite(向layer添加这样的一个精灵后,会弹出一个提示框,显示"create HSprite success","Himi_Lua")

#ifndef __luademo__HSprite__
#define __luademo__HSprite__ #include <iostream>
#include "cocos2d.h" using namespace cocos2d; class HSprite : public cocos2d::CCSprite{ public:
static HSprite* createHSprite(const char* _name);
void hspriteInit();
}; #endif /* defined(__luademo__HSprite__) */
#include "HSprite.h"

HSprite* HSprite::createHSprite(const char* _name){
HSprite* sp = new HSprite();
if(sp && sp->initWithFile(_name)){
sp->hspriteInit();
sp->autorelease();
return sp;
}
CC_SAFE_DELETE(sp);
return NULL;
} void HSprite::hspriteInit(){
CCMessageBox("create HSprite success", "Himi_Lua");
}

(2)然后开始向LuaCocos2d.cpp文件添加我们自定义精灵类,让Lua脚本能认识它;

①在LuaCocos2d.cpp类中搜索“tolua_reg_types”这个函数,然后在其中进行注册:

添加这一行代码: tolua_usertype(tolua_S,"HSprite");

如下:

/* function to register type */
static void tolua_reg_types (lua_State* tolua_S)
{
tolua_usertype(tolua_S,"HSprite"); tolua_usertype(tolua_S,"kmMat4");
tolua_usertype(tolua_S,"CCControlSaturationBrightnessPicker");
tolua_usertype(tolua_S,"CCShaky3D");
......

②声明我们所自定义的函数,
搜索“tolua_Cocos2d_open”这个函数,然后在其中添加如下代码:

tolua_cclass(tolua_S, "HSprite", "HSprite", "CCSprite", NULL);
tolua_beginmodule(tolua_S,"HSprite");
tolua_function(tolua_S,"createHSprite",tolua_Himi_HSprite_createHSrpite00);
tolua_endmodule(tolua_S);

如下:

/* Open function */
TOLUA_API int tolua_Cocos2d_open (lua_State* tolua_S)
{
tolua_open(tolua_S);
tolua_reg_types(tolua_S);
tolua_module(tolua_S,NULL,0);
tolua_beginmodule(tolua_S,NULL);
tolua_cclass(tolua_S,"kmMat4","kmMat4","",NULL);
tolua_beginmodule(tolua_S,"kmMat4");
tolua_array(tolua_S,"mat",tolua_get_Cocos2d_kmMat4_mat,tolua_set_Cocos2d_kmMat4_mat);
tolua_endmodule(tolua_S); //添加的内容
tolua_cclass(tolua_S, "HSprite", "HSprite", "CCSprite", NULL);
tolua_beginmodule(tolua_S,"HSprite");
tolua_function(tolua_S,"createHSprite",tolua_Himi_HSprite_createHSrpite00);
tolua_endmodule(tolua_S); ...

注意:这时候程序会报错,因为我们还没有实现
tolua_Himi_HSprite_createHSrpite00这个lua---cocos2dx之间的转换函数,下面实现这个函数。

③实现tolua_Himi_HSprite_createHSrpite00这个lua---cocos2dx之间的转换函数

直接添加如下代码即可。

/* method: create of class  HSprite */
#ifndef TOLUA_DISABLE_tolua_Himi_HSprite_createHSrpite00
static int tolua_Himi_HSprite_createHSrpite00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertable(tolua_S,1,"HSprite",0,&tolua_err) ||
!tolua_isstring(tolua_S,2,0,&tolua_err) ||
!tolua_isnoobj(tolua_S,3,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
const char* pszFileName = ((const char*) tolua_tostring(tolua_S,2,0));
{
HSprite* tolua_ret = (HSprite*) HSprite::createHSprite(pszFileName);
int nID = (tolua_ret) ? tolua_ret->m_uID : -1;
int* pLuaID = (tolua_ret) ? &tolua_ret->m_nLuaID : NULL;
toluafix_pushusertype_ccobject(tolua_S, nID, pLuaID, (void*)tolua_ret,"HSprite");
}
}
return 1;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'create'.",&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE

④下面我们在lua程序中就可以使用我们自定义的HSprite类了。

在hello.lua文件中的代码全部修改为:

local function createLayer()
visibleSize = CCDirector:sharedDirector():getWinSize()
origin = CCDirector:sharedDirector():getVisibleOrigin() local layer = CCLayer:create()
--创建自定义类型精灵 local hsprite = HSprite:createHSprite("Icon.png")
hsprite:setPosition(origin.x + visibleSize.width / 2 , origin.y + visibleSize.height / 2+50)
hsprite:setScale(1.5)
hsprite:setRotation(45)
layer:addChild(hsprite) return layer
end -- run
local sceneGame = CCScene:create()
sceneGame:addChild(createLayer())
CCDirector:sharedDirector():runWithScene(sceneGame)

⑤执行程序即可出现如下:

但是在终端 中会有如下的提示信息:

Cocos2d: [LUA ERROR] ...B74443-4D75-4C9D-83C8-582D665693AC/luademo.app/hello.lua:9: error in function 'setPosition'.
argument #1 is 'HSprite'; 'CCNode' expected.

在李华明的博客中有解决这个问题的方法:
使用tolua++编译pkg,从而创建自定义类让Lua脚本使用  (本人还没试,试过ok了,再进行补充!

Learning Lua Programming (4) Cocos2d-x中Lua编程(一)的更多相关文章

  1. Learning Lua Programming (3) iMac下搭建Lua脚本最好的编码环境(代码补全,编译运行)

    这篇文章参考自http://blog.sina.com.cn/s/blog_991afe570101rdgf.html,十分感谢原作者的伟大创造,本人亲测可行. 这篇文章记录一下如何在MAC系统环境下 ...

  2. Learning Lua Programming (2) Lua编程基础

    开始学习Lua编程,首先从一些简单的语法开始. 一.编辑环境 下面推荐一个Lua编程的IDE,感觉是很强大的.ZeroBrane Studio,windows平台,mac平台都有.点击打开链接  官方 ...

  3. C# 运行中 Lua 语言脚本

    这里就不介绍Lua语言了,使用挺广的一种脚本语言.自行百度. 第一步 使用 Nuget 安装引用 VikingErik.LuaInterface. 第二步 添加 Using using LuaInte ...

  4. 项目中lua(基础)

    关于项目中lua任务(某些没弄懂,但lua上耗费时间有点长了不看了) 这段时间看了lua语法和项目中lua应用 .在lua中注册c库,在lua5.2中好像都是注册c库,相当于在lua中定义一个tabl ...

  5. openresty开发系列24--openresty中lua的引入及使用

    openresty开发系列24--openresty中lua的引入及使用 openresty 引入 lua 一)openresty中nginx引入lua方式 1)xxx_by_lua   ---> ...

  6. 【第二篇】xLua中lua加载方式

     xLua中lua文件加载方式 1. 直接执行字符串方式 LuaEnv luaenv = new LuaEnv(); luaenv.DoString("CS.UnityEngine.Debu ...

  7. xlua中lua对象到c#对象的转型

    lua中的类型 基础类型 #define LUA_TNIL 0 #define LUA_TBOOLEAN 1 #define LUA_TLIGHTUSERDATA 2 #define LUA_TNUM ...

  8. xLua中Lua调用C#

    xLua中Lua调用C# 1.前提 这里使用的是XLua框架,需要提前配置xlua,设置加载器路径: 可以参考之前的Blog:<xlua入门基础>: //调用段,所有的lua代码都写在Lu ...

  9. redis中lua脚本的简单使用

    一.背景 在使用redis的过程中,发现有些时候需要原子性去操作redis命令,而redis的lua脚本正好可以实现这一功能.比如: 扣减库存操作.限流操作等等. redis的pipelining虽然 ...

随机推荐

  1. Win7/8在用账户密码登录时, 设置成保留用户名, 只输入密码

    修改注册表, 0表示保留用户名. 1表示每次都需要输入用户名密码. 位置: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersio ...

  2. Android Bug 记录

    1.Unable to resolve target 'android-5' 无法解析目标 ' 安卓系统-5'      Unable to resolve target 'Google Inc.:G ...

  3. vagrant 使用方法

    0.介绍 Vagrant 是一款用来构建虚拟开发环境的工具,非常适合 php/python/ruby/java 这类语言开发 web 应用,"代码在我机子上运行没有问题"这种说辞将 ...

  4. sql中select语句的逻辑执行顺序

    下面是SELECT语句的逻辑执行顺序: FROMONJOINWHEREGROUP BYWITH CUBE or WITH ROLLUPHAVINGSELECTDISTINCTORDER BYTOP M ...

  5. Code 49 码

    Code 49码是一种多层.连续型.可变长度的条码符号,它可以表示全部的128个ASCII字符.每个Code 49条码符号由2到8层组成,每层有18个条和17个空.层与层之间由一个层分隔条分开.每层包 ...

  6. 如何去掉Protel99se汉化菜单

    说明: 安装Protel99se汉化包后,卸载后重新安装也无法去掉汉化菜单.本文介绍解决办法. 问题: 网上一些Protel99se的安装包内,在介绍Protel安装时,采用3大步的方法.第一步安装P ...

  7. SpringBoot接口服务处理Whitelabel Error Page(转)

    To switch it off you can set server.error.whitelabel.enabled=false http://stackoverflow.com/question ...

  8. mybatis通用DAO

    扫扫关注"茶爸爸"微信公众号 坚持最初的执着,从不曾有半点懈怠,为优秀而努力,为证明自己而活. 回复:茶爸爸了解他这个人!! 花了几天的时间研究了一下mybatis的源代码,觉得这 ...

  9. android 获取本机号码需要root吗?

    首先要明白,有的手机是获取不到自身的手机号的, 查了些资料,有以下两种方式可以获取到:      1. 通过对方给你发短信,打电话获取本机号码:       2. 还有一个就是通过APN来查询,但是这 ...

  10. Java for循环用法

    Java中for循环多了一种写法--foreach写法(一般仅仅用于遍历整个数组,不用操心越界等问题). 1.1)常规写法: package foreach.main.sn; public class ...