Lua元表应用汇总

真的是好久好久没有写过东西了。= 。=

元表是Lua里头一个很强大的特性,有了它,可以自定义扩展出很多本身Lua并不原生支持的东西。所以其实一直都想做一个关于元表应用的汇总,趁着过年这点闲暇,暂且汇总下目前所了解的一些,也权当抛砖引玉吧。

重载算术运算符


这个没什么好说的,也算是元表的最初级运用了,具体应用见Lua手册中的介绍。

Cache表


这个也属于元表的基本运用,没什么好说的,通过弱引用来做一个Cache缓存。

只读表


通过实现__index和__index元方法,来实现对一个表的只读访问(这里的实现只针对一层表结构)

实现面向对象


这个之前有专门写过,参见

一个完整的Lua版OOP示例

简单使用Lua实现类的继承

共享表数据


有时候我们可能需要这样一个表参数传递,表里大部分数据是固定的,但是部分数据是动态创建的,如果每次都全部重新创建一遍就比较浪费,于是可以将固定数据做成一张表,然后每次创建新表使其可以共享这个固定数据表里的数据,新表内部只包含那些动态的数据。


以上的都是比较常见的一些应用,下面的这些也许就比较“冷门”了,至少我第一次接触的时候是觉得很“黑科技”的。

带功能的函数


这个主要运用了__call函数,用一个表来扩展原有函数,从而来实现带记忆(对运行过的输入参数保存结果,下次同样的参数传递进来可直接返回结果,达到优化效率的目的,这里也应用了上述的Cache表)。且此表可直接对原有函数进行替换,并可附加清除记忆功能。

为函数添加标签


这里也是通过__call将函数转换为可执行表,然后在其元表中加入一个标签来为此函数添加标签,同时新生成的函数可以与原函数完美替换。

统计函数运行信息


这个跟上面的类似,还是利用__call将函数转换为可执行表,向其元表中添加统计记录,并在函数运行时统计信息,最后再通过GetStatInfo来查看此函数的运行信息,这样在我们需要对某些函数做性能统计时,就不用修改原函数或者全盘查找替换了。

Lua装饰器


其实上面几个应用在其他语言里(比如Python)都可被称为装饰器(Decorator),并且为其提供了一些语法糖,这里我们也利用Lua的元表为其做了一个类似的语法糖(使用 .. 运算符),并用这个语法糖将以上几个函数修改了下。

先看最终效果:

这里首先我们用统计函数来修饰原函数,用于统计原函数真正的运行次数,然后为这个函数加上记忆函数功能使其相同输入参数时仅须运行1次,最后加上标签foo_final, 为这个最终函数打上标记。

最终运行结果显示,一切符合预期。

最后附上各个装饰器的实现:

以及最后用于生成装饰器的函数实现:

其实有了这个装饰器,就可以使用Lua去做所谓的面向切面的编程(Aspect-Oriented Programming)了,能做的事情就远不止上面提到的那几种,只是上面几个我个人比较常用而已。
最后,元表的世界好奇妙,哈哈。

 

欢迎关注微信公众号:Lua爱好者

使用Lua制作动态数据表格

表格配置中有种很常用的表格就是等级数值表,类似下面这种:

table_1
一般都是数值策划用exce制作出来的,而且很大可能是用公式计算出来的。通常情况下这么做没什么问题,但是有这么一种需求,一个怪物的掉落经验会随着玩家等级变化而变化,那么要配置这样一个掉落表就会是个让人很繁琐的事情了。通常我们会有两种做法:(我之前呆过的项目经验) 继续阅读

简单使用Lua实现表格动态解析

在游戏开发里,游戏配置是必不可少的一项。表格式配置是一种非常常见的格式,简单易用,支持excel等表格工具编辑,深受广大策划同学的喜爱。这里介绍一种简单使用Lua来做表格配置的方式。

首先是表格的格式,为了简单起见没有采用直接解析excel格式的方式来做,而采用了csv格式,个人喜好,采用制表符作为分隔符。生成出来的格式大概如下
(这里推荐使用OpenOffice来进行编辑):

ID\tName\tDescription\n
1\tTom\t他是一个工人\n

继续阅读

将cocos2dx里的lua升级至5.3

由于项(ge)目(ren)需(xing)要(qu),决定将项目的代码升级到最新的5.3.0版,源码点这下载

由于cocos2d-x是个跨平台项目,所以要分别对windows,android,ios三个环境均要做一定修改。而由于cocos2d-x默认是使用luajit的,而最新的luajit并不支持Lua5.3,所以作为代价就是放弃jit带来的效率提升,然而这个对我们的项目其实并没有什么影响(游戏玩法决定不需要太注重效率)
继续阅读

使用cocos2d-x的console实现远程调试

使用Lua开发有一个很爽的地方就是可以从控制台实时输入Lua指令来进行调试,但是之前该方法仅在windows下有效,之前也介绍过,见这里。研究了下发现cocos2d-x是有一个console类来支持远程调试的,哈哈,从此真机调试也可以很方便了。

这里先介绍下console的关键API先:

listenOnTCP(number) 这里参数是监听的端口号
addCommand(tb, funciton) 这里第一个参数是一个表,内容如下:{name = "指令名", help = "指令介绍"},第二个参数就是执行的函数了,传入参数为(句柄,字符串参数)

继续阅读

Cocos2d-x 3.2 Lua 在Android设备闪退问题解决记录

描述:iOS设备运行正常,windows环境下模拟器程序运行正常,但是Android设备大多数都有运行一段时间闪退的问题。

第一次运行android设备上时使用版本3.0,后来升级到3.1.1,再到3.2,Android闪退问题一直存在,尤其是在红米系列设备,几乎必现。
因为对Android开发不是很熟悉,没法直接定位到导致crash的地方,于是请教了同事,后发现是打包的API版本过高,修改后闪退问题有明显好转,但是依然存在,最近项目进度不是那么赶,于是决定要彻底追查这个问题。
继续阅读

一套基于Cocos2d-x的Lua快速开发框架

   最近半年一直都在研究cocos2d-x的开发,由于自身对Lua的喜好,所以基本从一开始都是使用Lua作为主要开发语言,在开发过程中,也对cocos2d-x有了一定了解,但是说实话cocos2d-x对Lua的支持还是不太友好,基本还是停留在“能”使用Lua开发的阶段,只是使用了tolua++将API都导出来了而已,没有对lua开发者做更进一步的帮助,这样其实并没完全体现Lua的优势。

    其实开发初期就听闻有一个“quick cocos2d-x”的项目,也是采用的Lua,顾名思义目的就是为了提高开发者的效率。对这个项目使用了一番,觉得它做的那个模拟器机制是个不错的想法,虽然还有很多bug。对它这个框架的有些核心思想不是太认同,主要是这个框架对cocos2d的源码进行过修改,而不是一个纯粹的lua级框架,这样做势必自己必须要有一个cocos2d-x的分支,这样会带来一个很要命的问题——在cocos2d-x进行功能增加或者bug修复的时候,需要做大量的工作来将他们合并入自己的分支,所以也就没太关心它的架构实现了。(另模拟器提供的重载不是脚本级的,而是重启进程这点也不是很满意)

    所以最后还是选择了自己来写一套基于cocos2d-x的纯粹的Lua级的框架,针对开发过程中开发者一般都会遇到需要解决的问题做了框架级的封装,使我们可以将更多的心思花在项目的逻辑上,而不用关心太多cocos2d的细节。(比如屏幕的拖拽,缩放,UI资源的加载管理这些等等)

    目前这个框架也在公司的项目里开始运用,表现的还不错,而且也在不断的完善中,但是要把它使用起来还是要花上几分钟来配置,所以今天花了点时间写了个python脚本来做配置。另这个项目本身就是寄放在github上的开源项目(https://github.com/yestein/cocos-lua),打算最近花些时间对这个框架写些说明文档将其正式开源出来,也希望它可以接受更多的检验,成长的更好。未来我也会在这里专门开辟一个专栏来对其进行说明。

Lua表的实现

Lua最强大的数据结构就是它的表,那么它是如何实现的呢?

typedef struct Table {
  CommonHeader;
  lu_byte flags;  /* 1<<p means tagmethod(p) is not present */ 
  lu_byte lsizenode;  /* log2 of size of `node' array */
  struct Table *metatable;
  TValue *array;  /* array part */
  Node *node;
  Node *lastfree;  /* any free position is before this position */
  GCObject *gclist;
  int sizearray;  /* size of `array' array */
} Table;

这个是Lua表的定义,其中
lszienode 表示表所分配内存的长度,为2的n次方
array 为表的数组部分,真的是一个数组,长度也为2的n次方
node 为表的哈希表部分,也是一个数组
lastfree 用于指向表中目前为空的部分(实际free为它的地址减一)
gclist 用于Lua的GC
sizearry 数组部分大小
继续阅读