【Cocos2dX(2.x)_Lua开发之三】★重要必看篇★在Lua中使用自定义精灵(Lua脚本与自创建类之间的访问)及Lua基础讲解

最后更新于:2022-04-01 10:15:58

本站文章均为[ 李华明Himi ](http://www.himigame.com/about-himi)原创,转载务必在明显处注明: 转载自[【黑米GameDev街区】](http://www.himigame.com/) 原文链接: [http://www.himigame.com/lua-2/985.html](http://www.himigame.com/lua-2/985.html "【Cocos2dX(2.x)_Lua开发之一】★重要必看篇★在Lua中使用自定义精灵(Lua脚本与自创建类之间的访问)及Lua基础讲解") [☞ 点击订阅 ☜](http://list.qq.com/cgi-bin/qf_invite?id=acfc24e272cc4a26debf3b3866edb626a9ea3fc80fd8893c) 本博客最新动态!及时将最新博文通知您! 本篇做起来比较累,大家请参考最新篇[【COCOS2DX-LUA 脚本开发之四】使用tolua++编译pkg,从而创建自定义类让Lua脚本使用](http://www.himigame.com/lua1/1259.html) 此篇可能会在最新的cocos2dx版本中出现如下问题: ~~~ LUA ERROR: ...24F82-1230-41FE-8A04-C445FB7D1BAB/mtet.app/hello.lua:35: error in function 'addChild'. argument #2 is 'MySprite'; 'CCNode' expected. ~~~ 最近Himi都没有更新博文了,其实也是犹豫写本cocos2d(x)引擎书籍在做准备,目录的草稿都写好了,目录中包含的大家最感兴趣的cocos2d/x动作编辑器的详细制作流程与源码! 但是遗憾的是Himi还是腾不出时间去写; 放弃去写的另外一个原因就是因为支持我的童鞋门,在7月份就说过要为大家奉上关于cocos2dx-lua的系列教程,但是一直由于时间等问题一再拖到现在,如果Himi真要准备写书估计半年内都基本很难有时间更新博客的,当然也考虑到公司项目,最终放弃;(暂时放弃,以后有可能的话还是会写的 )![](image/56fcaa6a58e7f.gif) 顺便说一句,关于Himi9个技术群,不论是cocos2d-iphone、cocos2dx、android还是以后陆续公布的Unity3D群,周期性的Himi和管理员们会定期清理(一切都是为了更多想学习的新童鞋考虑),希望大家进群冒泡,积极讨论。好了,废话就不多说了,从今天开始Himi为童鞋们出cocos2dx-lua的系列开发教程,希望大家还一如既往得支持;3Q  Himi 当前开发工具等版本如下: mac: 10.8      xcode:4.4.1       cocos2dx :cocos2d-2.0-rc2-x-2.0.1 本篇介绍两个知识点:  1\. Lua基础 2.在lua脚本中使用我们自定义的精灵类 ### 一:lua基础 关于Lua的其实很早前Himi写过一篇关于cocos2dx-Lua 的基础博文了,但是是cocos2dx 1.x版本的,对于不是很熟悉的童鞋,Himi还是建议去看一看,连接:[【iOS-cocos2d-X 游戏开发之八】在Cocos2dX游戏中使用Lua脚本进行游戏开发(基础篇)并介绍脚本在游戏中详细用途!](http://www.himigame.com/iphone-cocos2dx/681.html) Himi以后更新的Lua系列都是基于Cocos2dx 2.x版本的了。 ###二:在lua脚本中使用我们自定义的精灵类 首先创建cocos2dx-lua项目,然后在项目中添加我们的自定义精灵类:这里Himi类名为:HSprite HSprite.h: ~~~ // // HSprite.h // cocos2dx_lua_tests_by_Himi // // Created by Himi on 12-8-30. // // #ifndef cocos2dx_lua_tests_by_Himi_HSprite_h #define cocos2dx_lua_tests_by_Himi_HSprite_h #include "cocos2d.h" using namespace cocos2d; class HSprite : public cocos2d::CCSprite{ public: static HSprite* createHSprite(const char* _name); void hspriteInit(); }; #endif ~~~ HSprite.cpp: ~~~ // // HSprite.cpp // cocos2dx_lua_tests_by_Himi // // Created by Himi on 12-8-30. // // #import "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"); } ~~~ 以上代码不做解释了,很简单,继承CCSprite,添加一个自动释放的创建函数(createHSprite)以及一个自定义初始化函数(hspriteInit) 下面我们打开LuaCocos2d.cpp 类,这个类在项目的 libs/lua/cocos2dx_support目录下,如下图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-31_56fcd0275416b.png) 然后开始添加我们自定义精灵类,让Lua脚本能认识它; 步骤分为3步: 1\. 注册我们的自定义类: 在LuaCocos2d.cpp类中搜索“tolua_reg_types”这个函数,然后在其中进行注册: ~~~ tolua_usertype(tolua_S,"HSprite"); ~~~ 如下图所示: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-31_56fcd0276f911.png) 第二步:声明我们自定义类的函数: 搜索“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); ~~~ 如下图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-31_56fcd0279f71b.png) 这里开始解释: 首先定义能让脚本认识的类函数,遵循如下: a)  tolua_cclass(tolua_S, “HSprite”, “HSprite”, “CCSprite”, NULL); tolua_cclass声明哪个类函数,第一个状态值默认:tolua_S 后两个参数:是自定义类类名 再往后是继承的父类类名 b)添加参数开始声明: tolua_beginmodule(tolua_S,”HSprite”); c)  添加自定类函数: tolua_function(tolua_S,”createHSprite”,tolua_Himi_HSprite_createHSrpite00); 第一个参数默认,第二个参数自定义类名,第三个:实现脚本与自定义类之间的转换实现函数 注意,这里有多个函数,可以继续写; d) 结束自定义函数: tolua_endmodule(tolua_S); 第三步:实现我们的脚本之间转换函数  tolua_Himi_HSprite_createHSrpite00 实现如下: ~~~ /* 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; tolua_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 ~~~ 如下图所示: [![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-31_56fcd027c5e60.jpg)](http://www.himigame.com/wp-content/uploads/2012/08/32.jpg) 这里Himi解释下: 童鞋们可以从第 384行的 #endif 把这个实现函数分为两部分来看, 首先是375~384之间的代码: ~~~ #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 ~~~ 这里是对参数类型的判断: tolua_isusertable  是否为”第三个参数”自定义类型 tolua_isstring  是否为字符串类型 tolua_isnoobj  结束(没有参数的判断) 然后是386~392之间的代码段: ~~~ 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; tolua_pushusertype_ccobject(tolua_S, nID, pLuaID, (void*)tolua_ret,"HSprite"); } ~~~ 这里是对脚本代码的解析从而调用的自定义创建的函数 最后我们修改  hello2.lua  脚本中的代码:(创建cocos2dx-lua项目默认Resources下自带的文件) 在脚本最后”– run”下代码修改如下: ~~~ -- run local sceneGame = CCScene:create() -- sceneGame:addChild(createLayerFram()) -- sceneGame:addChild(createLayerMenu()) sceneGame:addChild(createHimiLayer()) CCDirector:sharedDirector():runWithScene(sceneGame) ~~~ 这里Himi注视了另个layer的添加,添加了自己的Layer ~~~ sceneGame:addChild(createHimiLayer()) ~~~ 然后将Himi自定义方法添加在脚本中,代码如下: ~~~ local function createHimiLayer() local layerH = CCLayer:create() local _font = CCLabelTTF:create("Himi_(cocos2dx-Lua)教程","Arial",33) _font:setPosition(230,280) layerH:addChild(_font) --创建自定义类型精灵 local hsprite = HSprite:createHSprite("himi.png") hsprite:setPosition(100,100) hsprite:setScale(1.5) hsprite:setRotation(45) layerH:addChild(hsprite) return layerH end ~~~ 创建自己定义的精灵,然后进行调用缩放,旋转,设置坐标函数。 ok,运行后的接图如下: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-31_56fcd027ec0e1.png) 好了,本篇就到这里,童鞋们感觉本站好的文章记得分享,转播散播哦
';