刚开始接触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. FreeCodeCamp:Truncate a string

    要求: 用瑞兹来截断对面的退路! 截断一个字符串! 如果字符串的长度比指定的参数num长,则把多余的部分用...来表示. 切记,插入到字符串尾部的三个点号也会计入字符串的长度. 但是,如果指定的参数n ...

  2. JavaSE学习总结第14天_API常用对象4

      14.01 如何校验一个QQ号码案例 import java.util.Scanner; /* * 校验qq号码. * 1:要求必须是5-15位数字 * 2:0不能开头 * * 分析: * A:键 ...

  3. URL参数中有 特殊符号或加密数据 的问题解决

    url出现了有+,空格,/,?,%,#,&,=等特殊符号的时候,可能在服务器端无法获得正确的参数值,如何是好?解决办法将这些字符转化成服务器可以识别的字符,对应关系如下:URL字符转义 用其它 ...

  4. Week15(12月16日):授课综述1

    Part I:提问 =========================== 1.(   )类提供了一个对Entity Framework的抽象,能够进行数据持久化并接受数据. A.Layout    ...

  5. ASP.NET CS文件中输出JavaScript脚本

    ClientScript.RegisterStartupScript:http://msdn.microsoft.com/zh-cn/library/system.web.ui.clientscrip ...

  6. C# 计算器 运算符和数字键的keys对照

    keys. private void Computer_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.NumPad0) ...

  7. bespoke_百度百科

    bespoke_百度百科 bespoke

  8. Codeforces Round #200 (Div. 2) C. Rational Resistance

    C. Rational Resistance time limit per test 1 second memory limit per test 256 megabytes input standa ...

  9. AsyncQueryHandler处理数据

    参考:http://blog.csdn.net/hfreeman2011/article/details/8555474和http://blog.csdn.net/dragondog/article/ ...

  10. BZOJ 1036: [ZJOI2008]树的统计Count( 树链剖分 )

    树链剖分... 不知道为什么跑这么慢 = = 调了一节课啊跪.. ------------------------------------------------------------------- ...