刚开始接触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. iOS离线打包

    预备环境 iOS开发环境,Mac OS.XCode 7.2以上版本: 下载HBuilder离线打包iOS版SDK(5+ SDK下载). SDK目录说明 HBuilder-Hello:离线打包演示应用: ...

  2. Single Number i and ii

    Single Number Given an array of integers, every element appears twice except for one. Find that sing ...

  3. codeforces 463E . Caisa and Tree

    题目链接 给一棵树, 两种操作, 一种是将点u的权值改为y, 另一种是查询根节点到点u的路径上, gcd(v, u)>1的深度最深的点v. 修改操作不超过50次. 这个题, 暴力可以过, 但是在 ...

  4. java-StringTokenizer类

    StringTokenizer类别可以通过某个字符或者多个字符作为分界符,来将字符串划分为多个标记(token). package com.example.helloworld; import jav ...

  5. ie条件注释还能这样写

    通过条件注释给html开始标签定义不同的class, 来区分不同版本的IE,可以在样式表中避免 样式属性hack (如 _margin-top, *float:none ) 注意: IE10+不支持条 ...

  6. repeater一个简单的用法例子

    (前台) <asp:Repeater ID="Repeater1" runat="server"       onitemdatabound=" ...

  7. vc 国际化的资源文件处理

    MS Windows操作系统是一个世界上广泛使用的操作系统,对于不同语种的国家MS Windows有相应语种的版本.在不同语种的Windows平台上应该运行相应语种的应用程序.也就是说程序的用户界面( ...

  8. IT第十八天 - 类的封装、继承、重载、上周总结★★★

    IT第十八天 上午 封装 1.关键字this,是表示该类在实例化时的对象,即this.表示为该对象的属性 2.类的数据保护,set.get方法的写法规则,为了之后的反射机制的读取数据,set方法中对于 ...

  9. 点菜系统 pickview的简单实用

    使用pickview的时候多想想tableview的使用,观察两者的相同之处 pickview的主要用途用于选择地区  生日年月日  和点餐 示例代码 简单的pickview点餐系统//  ViewC ...

  10. linux配置nfs服务

    简单介绍: unix/linux系统一种远程文件文件夹共享的服务,能够把某一个远程的文件文件夹共享到本地,进而像操作本地文件一样,操作这个远程的文件夹. 比如:a主机作为服务端,共享出来test1这个 ...