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

继续阅读

Shader修改颜色出现不透明框

原本想做个shader,用来完成对图片色相,饱和度,亮度的调整,结果根据转换算法描述写完之后发现一个很严重的问题,就是原本图片是透明的地方在调整了亮度之后出现了不透明的色块(仅增大会出现)。后来将shader简化,仅将图片做红偏色。原图如下:
无标题2

结果做完shader变成下面这样:

gl_FragColor = vec4(r + 0.3, g, b, a);

无标题

经过一番尝试,后来发现改成这样均正常

gl_FragColor = vec4(r * 1.3, g, b, a);
gl_FragColor = vec4(r  + r * 0.3, g, b, a);

无标题1

总结,大抵是shader里面不能直接用加减单位来修改RGB值,只能用乘除法来做,大概猜测是因为色彩的单位并不是我们以为的[0, 1]吧,具体原因以后再具体分析吧。

一个关于luasocket使用的很蠢的问题

今天遇到了一个问题,服务端给客户端发包,偶尔会出现客户端无法解析的情况。我们服务端采用的skynet,客户端使用的是luasocket,协议采用的sproto。

照例首先不怀疑库的问题,肯定是自己的原因,而且应该是比较蠢的问题。首先问题出现在某一个协议上,这个协议每次发出去,客户端都无法解析,然而从proto文件里无法看出任何差别,也尝试修改了其他几个协议来尝试,并没有发现使其必现的规律,折腾了半天。最后只好动用VS,单步调试,内存跟踪,最终发现一个问题,服务端发出的包内容和客户端收到后拿给sproto解析的包内容不一致!
继续阅读

细数cocos2d踩过的那些坑

cocos2d-x版本:3.2
cocostudio版本:1.6.0
开发语言:Lua,使用cocos本身导出的Lua的API

cocostudio相关:

1. 骨骼设置隐藏时,若该骨骼动作的第一帧是没有渲染贴图的,则设置会失效,查看源码如下:

void DisplayManager::setVisible(bool visible)
{    
	if(!_displayRenderNode)
		return;
	_visible = visible;
    _displayRenderNode->setVisible(visible);
}

_visible = visible;

提到第一句即可。

2. 子骨骼在动作里没有父骨骼的情况下会全部乱掉,并没有通过源码发现。

3. 换贴图的情况下,如果编辑器动作是通过不渲染贴图的方式来做,那么实际播放中如果有换装则会导致隐藏失效,并没有通过源码发现。

将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的锚点与坐标

最近被cocos2d-x的坐标问题绕晕了头,这里整理下。

position: 每个node都有一个position,这个position是相对于它的父节点的坐标,所谓的世界坐标可以认为就是直接挂载在scene下的node的坐标。
AnchorPoint:每个node都会有自己的AnchorPoint,它的作用仅在于在设置position时,是将图片中的哪个点设置到那个位置。

需要注意的是
1 position是逻辑位置,而不是实际像素
2 这个坐标系与windows的坐标系的y轴是反的,cocos2d里(0,0)是在左下角,而不是左上角。
3 每个node的position都是相对父节点的(0,0)的位置,与父节点的锚点无关!我就是因为这个问题没搞清楚在这里绕晕了……

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

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

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

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

继续阅读