刚开始接触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. 新建linux组、用户命令

    之前在安装oracle的时候,出现了一个问题:安装Oracle,新建组.用户的时候的一个错误.看这篇博客前,先看这个链接,学习要从解决出现的问题出手. 建立用户组和用户 下面总结一下Linux建立组和 ...

  2. Oracle数据库的启动和关闭实例

    在开始了解oracle数据库的命令之前,先来看一个东西:SQL*PLUS(sqlplus) Oracle的sql*plus是与oracle进行交互的客户端工具.在sql*plus中,可以运行sql*p ...

  3. js求指定时间的周一和周日

    /*计算指定时间的的周一和周日 return=>{mondy:Date,sundy:Date} parms:{ date:指定时间,如果不指定则取当前时间 } */ function getWe ...

  4. Android 一个改进的okHttp封装库

    一.概述 之前写了篇Android OkHttp完全解析 是时候来了解OkHttp了,其实主要是作为okhttp的普及文章,当然里面也简单封装了工具类,没想到关注和使用的人还挺多的,由于这股热情,该工 ...

  5. 大数据计算:如何仅用1.5KB内存为十亿对象计数

    大数据计算:如何仅用1.5KB内存为十亿对象计数  Big Data Counting: How To Count A Billion Distinct Objects Using Only 1.5K ...

  6. 在非MFC程序中使用调试宏 ASSERT(),VERIFY()和 TRACE()

    游戏制作已经开始采用C++了,却鲜有人选择使用MFC.但笔者觉得的 ASSERT(),VERIFY()和 TRACE()这几个宏很好用.所以就想自己写一个版本来适应Windows平台下不同的工程类型. ...

  7. [Swust OJ 552]--拼音教学(找规律)

    题目链接:http://acm.swust.edu.cn/problem/0552/ Time limit(ms): 1000 Memory limit(kb): 65535   Descriptio ...

  8. BestCoder Round #57 (div.2)

    第一场BC...感觉还是多参加点比赛吧... 第一题水题各种乱搞就可以过 第二题依旧水题..记个前缀和就行了.. 虽说是2道水题..然而我T1提交时就过了20min, T2还RE了一发..第二次提交就 ...

  9. oracle语句块调用

    如果要写一个临时的语句块调用某个过程,可以参照以下方式: declare cursor v_is is select distinct aac001 from sic84 where aab001=5 ...

  10. js默认行为(也称默认事件)

    对应于智能社21课, 在浏览器的空白页面右击时会出现一个提示框,实际上这是用的document.oncontextmenu属性,如果用下面的代码就能够阻止这样的默认行为: <!DOCTYPE h ...