cocos2d lua绑定感悟---像cc.Sprite,cc.Director这些是如何识别的

其实自从打开GameScene.lua文件以来,我一直都很想搞清楚的一个问题就是cc.Sprite这些是如何识别的。其实第一反应肯定就是:它肯定是一个全局变量,要不然怎么调用create方法呢。先不考究cocos的C++类方法是如何绑定到lua的,我就是想知道这个全局变量是什么时候注册的?

知道一点lua知识的都知道 lua里面的全局变量会保存到一个全局表_G中去,问题就转换为了 什么时候向_G中注册的?在使用cc.Sprite的create之前,我好像没有没有在lua中定义cc.Sprite这样的变量,所以不可能是lua定义的这个全局变量,而是cocos在初始化lua引擎的时候对它进行注册的。

让我们来看看lua引擎初始化的时候都做了什么操作。果然找到了_G的踪迹。

 luaL_register(_state, "_G", global_functions);

这是在向lua中注册全局函数。(关键是此时的栈顶是 全局表 啊!!!这点很重要)。

让我们继续看下去,我们会看到各种注册:

 register_all_cocos2dx(_state);
    register_all_cocos2dx_extension(_state);
    register_cocos2dx_extension_CCBProxy(_state);
    tolua_opengl_open(_state);
    register_all_cocos2dx_ui(_state);
    register_all_cocos2dx_studio(_state);
    register_all_cocos2dx_manual(_state);
    register_all_cocos2dx_module_manual(_state);
    register_all_cocos2dx_extension_manual(_state);
    register_all_cocos2dx_coco_studio_manual(_state);
    register_all_cocos2dx_ui_manual(_state);
    register_all_cocos2dx_spine(_state);
    register_all_cocos2dx_spine_manual(_state);
    register_glnode_manual(_state);

每一个注册完成后,均会还原现场,即保持栈顶是_G表。让我们选一个来分析吧,就以register_all_cocos2dx 为例吧。

TOLUA_API int register_all_cocos2dx(lua_State* tolua_S)
{
	tolua_open(tolua_S);

	tolua_module(tolua_S,"cc",0);
	tolua_beginmodule(tolua_S,"cc");

	lua_register_cocos2dx_Ref(tolua_S);
	lua_register_cocos2dx_Console(tolua_S);

	...省略很多代码...
}

这里貌似看到一点苗头。cc和我们的cc.Sprite很近了。

基础函数介绍:

tolua_module:尝试注册以name为名的模块,每个模块都是在向父模块注册,但是cc没有父模块,所以它会认为_G是它该去注册的地方。

TOLUA_API void tolua_module (lua_State* L, const char* name, int hasvar)
{
    if (name)
    {
        /* tolua module */
        lua_pushstring(L,name);
        lua_rawget(L,-2);//拿到name在当前模块表中是否进行了注册
        if (!lua_istable(L,-1))  /* check if module already exists */
        {

			//没有注册过,new一个
            lua_pop(L,1);
            lua_newtable(L);
            lua_pushstring(L,name);
            lua_pushvalue(L,-2);

	/*
	下面这段测试表明该模块是加到(全局表)中
		if(lua_istable(L,-4)){
		<span style="white-space:pre">	</span>lua_getfield(L,-4,"print");
		<span style="white-space:pre">	</span>if(lua_isnil(L,-1)){
		<span style="white-space:pre">		</span>char a='a';
		<span style="white-space:pre">	</span>}else{
		<span style="white-space:pre">		</span>char b ='b';  //come here啦啦啦!!!
		<span style="white-space:pre">	</span>}
		<span style="white-space:pre">	</span>lua_pop(L,1);
	<span style="white-space:pre">	</span>}*/

		//注册到当前模块表中去
            lua_rawset(L,-4);       /* assing module into module */
        }
    }
}

从上面的测试代码就可以发现就是向_G表注册。所以我们的猜测是完全正确的。为什么是_G表呢?之前已经提示过了(注册全局函数的时候,会把_G放在栈顶)。

现在全局表中有这样的一个键值对:_GTable["cc"]=cc_table。

接下就看Sprite是如何注册进去的吧。在register_all_cocos2dx那堆注册的函数中,我们发现:

lua_register_cocos2dx_Sprite(tolua_S);
int lua_register_cocos2dx_Sprite(lua_State* tolua_S)
{
    tolua_usertype(tolua_S,"cc.Sprite");
    tolua_cclass(tolua_S,"Sprite","cc.Sprite","cc.Node",nullptr);

    tolua_beginmodule(tolua_S,"Sprite");
    tolua_function(tolua_S,"setSpriteFrame",lua_cocos2dx_Sprite_setSpriteFrame);
	//...此处省略很多代码...
}

基础函数介绍:

tolua_usertype:向注册表中注册该用户类型,创建该类型的表。(table和type在注册表中是双向映射)。

tolua_cclass:设置该类的元表啊,父类,tolua_super表注册,tolua_ubox表注册,。并且以"Sprite"为key加入到当前所在父模板表中。

然后是向表中注册一些函数。

我们知道当前父模板表是cc_table,当前模板表是:sprite_table。cc_table["Sprite"] = sprite_table。sprite_table["setSpriteFrame"] = lua_cocos2dx_Sprite_setSpriteFrame。

现在就可以通过全局表去访问 到Sprite了,并且可以访问到里面的方法。

所以我觉得cc.Sprite.setSpriteFrame(...)的执行流程是:向_G表中拿到cc对应的cc_table,再看在cc_table中是否有Sprite,如果有就在sprite_table中去寻找setSpriteFrame方法。

以上纯属个人看法。本人也是在学习中,欢迎和一起交流。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2025-01-07 21:03:15

cocos2d lua绑定感悟---像cc.Sprite,cc.Director这些是如何识别的的相关文章

cocos lua绑定感悟---tolua_isusertable及lua如何访问cocos静态函数的方法

现在还是个新手,对很多还不是很了解,所以语言估计会有点晦涩,望原谅啊!! <pre name="code" class="html">TOLUA_API int tolua_isusertable (lua_State* L, int lo, const char* type, int def, tolua_Error* err) { if (def && lua_gettop(L)<abs(lo)) return 1; if (l

cocos lua 绑定感悟---各种表

1:tolua_super tolua_super存在于注册表中,其中记录了各种类型的父类,key是类型的table,value是也是个<v_key,v_value>的表,v_key是父类的名字,value是1.在判断类型的时候,这个非常有用. 2:tolua_ubox 在注册表中和每种类型的表中都存在这样一张表,注册表是在 toluafix_open 中初始化的,而每种类型的tolua_ubox表示在该注册该类型的时候初始化的,请参考setbox函数,它要么是父类的tolua_ubox表,要

cocos2d-js Shader系列2:在cc.Sprite上使用Shader(黑白、灰度、造旧效果)

在Sprite中使用Shader做特殊的颜色处理比较简单,只需要把Shader程序绑定到Sprite上即可: sprite.shaderProgram = alphaTestShader; Cocos2d内置了一些Shader,详细可以看代码: 其中,CCShaderCache缓存了一些Shader实例,而GLProgram则对gl的api做了简单的封装让接口更友好. 需要注意的是,使用GLProgram编译shader程序时,cocos2d会自动加入了一些参数. _compileShader:

cc.Sprite

cc.Sprite 1: 游戏中显示一个图片,通常我们把这个叫做"精灵" sprite;2: cocos creator如果需要显示一个图片,那么需要在节点上挂一个精灵组件,为这个组件指定要显示的图片(SpriteFrame); 3: 显示一个图片的步骤: (1) 创建一个节点; (2) 添加一个组件; (3) 要显示的图片(SpriteFrame)拖动到SpriteFrame; (4) 配置图片的SIZE_MODE: a: CUSTOM 大小和CCNode的大小一致; b: RAW

cocos creator基础-(六)cc.Sprite使用

1: 了解cc.Sprite的使用;2: 了解cc.Sprite的大小模式;3: 学会使用九宫格,使用九宫格节省美术资源;4: 学会个性化的时间精度条的使用;5: 代码里面来更换图片; cc.Sprite 1: 游戏中显示一个图片,通常我们把这个叫做”精灵” sprite2: cocos creator如果需要显示一个图片,那么需要在节点上挂一个精灵组件,为这个组件指定要显示的图片(SpriteFrame)3: 显示一个图片的步骤: (1) 创建一个节点; (2) 添加一个组件; (3) 要显示

使用cocos2d脚本生成lua绑定

这几天要老大要求把DragonBones移到cocos2dx 3.0 里边,并且绑定lua使用接口.因为刚学lua,使用的引擎也刚从2.2改为3.0,各种不熟悉,折腾了好几天才弄完,有空了总结一下 这篇先说一下cocos2d生成lua绑定的修改,有空的话再写一篇lua中注册回调到c++中方法 我的目录结构 假设我的目录名称是DragonBones -Cocosdx目录 -DragonBones  -c代码 -c代码头 -tools  db_DragonBones.ini genbindings.

cocos动画没有cc.Sprite.spriteFrame属性

对于新人来说总是有那么多的坑等着你. 新建动画节点的时候千万别[新建空节点]!!! 上面这个就是新建了空的节点,导致没有cc.Sprite.spriteFrame属性. 正确姿势: 粗略试了一下除了空节点,其他的应该都可以.[创建节点]->[创建渲染节点]->[Sprite(精灵)] 总结:经验就是踩坑积累的.很多播客写的教程并不全,所以新手操作起来也会有很多问题,自身多总结多实践就好. 原文地址:https://www.cnblogs.com/codeDevotee/p/11104071.h

Cocos2d-x3.0 lua绑定C++类

这里记录下我实现Lua绑定的全过程. 原文地址:http://blog.csdn.net/qqmcy/article/details/26099859 准备工作: 1.创一个一个Lua的2dx工程.(这个网上已经有好多了) 2.创一个C++类. TestScene.h  这个只是一个简单的场景 // // TestScene.h // uitestLua // // Created by 杜甲 on 14-5-17. // // #ifndef __uitestLua__TestScene__

Cocos2d Lua 入门小例子 一个记忆力游戏

1.游戏说明 一个"记忆"类的比赛游戏.你和电脑对战,轮到谁的回合,谁翻两张牌,如果两张牌一样,就消掉这两张牌,得2分,可以继续翻牌,如果两张牌不一样,就换一个人.直到最后,看谁的得分高. 游戏设计思想可以看这篇文章<Cocos2d 游戏状态机> 2. Lua 简单面向对象 我们知道Lua是脚本语言,不是真正面向对象语言.但是面向对象好像能让代码结构更加合理,Javascript, Lua都可以模拟出面向对象.Lua面向对象还有超多种方式实现,这里当然不一一介绍.简单来看个