Learning Lua Programming (4) Cocos2d-x中Lua编程(一)
刚开始接触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编程(一)的更多相关文章
- Learning Lua Programming (3) iMac下搭建Lua脚本最好的编码环境(代码补全,编译运行)
这篇文章参考自http://blog.sina.com.cn/s/blog_991afe570101rdgf.html,十分感谢原作者的伟大创造,本人亲测可行. 这篇文章记录一下如何在MAC系统环境下 ...
- Learning Lua Programming (2) Lua编程基础
开始学习Lua编程,首先从一些简单的语法开始. 一.编辑环境 下面推荐一个Lua编程的IDE,感觉是很强大的.ZeroBrane Studio,windows平台,mac平台都有.点击打开链接 官方 ...
- C# 运行中 Lua 语言脚本
这里就不介绍Lua语言了,使用挺广的一种脚本语言.自行百度. 第一步 使用 Nuget 安装引用 VikingErik.LuaInterface. 第二步 添加 Using using LuaInte ...
- 项目中lua(基础)
关于项目中lua任务(某些没弄懂,但lua上耗费时间有点长了不看了) 这段时间看了lua语法和项目中lua应用 .在lua中注册c库,在lua5.2中好像都是注册c库,相当于在lua中定义一个tabl ...
- openresty开发系列24--openresty中lua的引入及使用
openresty开发系列24--openresty中lua的引入及使用 openresty 引入 lua 一)openresty中nginx引入lua方式 1)xxx_by_lua ---> ...
- 【第二篇】xLua中lua加载方式
xLua中lua文件加载方式 1. 直接执行字符串方式 LuaEnv luaenv = new LuaEnv(); luaenv.DoString("CS.UnityEngine.Debu ...
- xlua中lua对象到c#对象的转型
lua中的类型 基础类型 #define LUA_TNIL 0 #define LUA_TBOOLEAN 1 #define LUA_TLIGHTUSERDATA 2 #define LUA_TNUM ...
- xLua中Lua调用C#
xLua中Lua调用C# 1.前提 这里使用的是XLua框架,需要提前配置xlua,设置加载器路径: 可以参考之前的Blog:<xlua入门基础>: //调用段,所有的lua代码都写在Lu ...
- redis中lua脚本的简单使用
一.背景 在使用redis的过程中,发现有些时候需要原子性去操作redis命令,而redis的lua脚本正好可以实现这一功能.比如: 扣减库存操作.限流操作等等. redis的pipelining虽然 ...
随机推荐
- JavaSE学习总结第18天_集合框架4
18.01 Map集合概述和特点 Map接口概述:将键映射到值的对象,一个映射不能包含重复的键,每个键最多只能映射到一个值 Map接口和Collection接口的不同 1.Map是双列的,Coll ...
- Hadoop运行中遇到的错误调试
在运行Hadoop的过程中遇到的最多的问题就是DataNode不能正常的启动,各种问题都有可能,说一下我遇到的两种情况: (1)第一种情况是Master的防火墙没有关闭.这样在启动Hadoop的时候, ...
- Spring AOP报错
八月 01, 2016 10:08:48 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRe ...
- SDWebImage 常用方法
SDWebImage是iOS中一款处理图片的框架, 使用它提供的方法, 一句话就能让UIImageView自动去加载并显示网络图片.特别是在UITableViewCell中有UIImageView需要 ...
- PHP 判断数据类型
isset()://变量是否已经声明 empty()://变量是否为空 defined()://常量是否已经定义 define() array_key_exists(mixed key, array ...
- [移动网关]2G环境下资源下载有一定概率失败,客户端日志显示收到403错误
2G环境下资源下载有一定概率失败,客户端日志显示收到403错误 问题现象: 测试同学在使用联通号码在移动网络环境下,访问连接得到的response_code出现是403,导致资源读取失败表情显示异常. ...
- IT第十九天 - 继承、接口、多态、面向对象的编程思想
IT第十九天 上午 继承 1.一般情况下,子类在继承父类时,会调用父类中的无参构造方法,即默认的构造方法:如果在父类中只写了有参的构造方法,这时如果在子类中继承时,就会出现报错,原因是子类继承父类时无 ...
- STL set的用法
要使用set需要事先引入一个头文件 #include<set> set是一个不允许重复的集合,如果要重复可以使用multiset. 1.set的插入[set.insert();],会返回P ...
- PDO--PHP Data Objects
PDO的环境配置:开启支持PDO 在php.ini配置文件里开启: extension=php_pdo.dll extension=php_pdo_mysql.dll 在PDO操作中涉及到类:PDO. ...
- 深入浅出 JSTL
JSLT标签库,是日常开发经常使用的,也是众多标签中性能最好的.这个算是一个java程序员的一个基本功吧. JSP Standard Tag Library (JSTL) 的规范完成于2002年7月, ...