cocos-lua 架构简介及使用

Github:https://github.com/yestein/cocos-lua

基础接口:

Class:New(base_class, class_name) :用于实现面对对象的类,base_class 若为nil则为完全定义一个新类。

一切的基础--LogicNode

cocos-lua里头所有对象的基础类,也就是所有cocos-lua里的对象都具有它的功能,它包括以下功能:

  • 拥有child和parent
  • 监听事件
  • 查询调用指定名称的函数,用以实现COM
  • 可以接受消息执行,并将消息继续向child传递
  • 打印日志

接口如下:

  • GetParent() --获取父节点
  • AddChild(child_name, child_node, order) --添加子节点
  • RemoveChild(child_name) --删除子节点
  • GetChild(child_name) --获取指定的子节点
  • ForEachChild(callback, …) --迭代遍历每一个子节点
  • DeclareListenEvent(event_type, func_name) --注册事件监听
  • QueryFunction(func_name) --查询指定名称的函数
  • QueryFunctionWithChild(func_name) --查询指定名称的函数(包括所有的子节点)
  • TryCall(func_name, …) --尝试调用指定名称的函数(包括子节点种,若全部没有,则返回nil)
  • ReceiveMessage(msg, …) --对node及其所有子节点都试图调用名为msg的函数
  • Print(log_level, fmt, …) --打印日志
  • AddComponent(child_name, component_name, …) --添加指定名称的组件

事件(event)和消息(message)的区别

event是一个全局的类似信号弹的角色,主要用于不同模块之间的通信。如逻辑模块抛出一个角色伤害事件,表现模块受到事件后对相应的角色做出受伤的表现,如受伤动作,飘出红色伤害值等。event的使用在于抛出event的模块并不知道哪个模块会去处理它,并通过这个来降低模块间的藕合度。

message更类似于一个定向的指示弹,主要用于模块内部的操作。模块收到一个message,首先模块本身对这个message要做出回应,是否要处理,然后继续将这个message传递给它的子模块。如表现模块给角色表现模块发送一个角色受伤的message,角色表现模块受到message之后做出对角色播放受伤动作,然后这个message继续传递给它的子模块如文字飘血模块,文字飘血模块播放一个跳动的数字。message的使用在于模块收到message的时候并不知道自己能不能处理这个message,而需要将message一层层逐级询问子模块,目的在于降低模块内部子模块之间的耦合,方便模块进行组装。
PS:cocos-lua里为了处理message方便,将message的名称定义为处理函数的名称,类似于obj-c。

综上所述,event和message的目的都是为了降低整体代码的藕合度,他们的区别如下:

  • 是否定向。event的发送者不关心谁会接收这个event,而message要求发送者必须知道对谁发送。
  • 是否有序。event的接收者处理顺序是无法预测的,message的可以按指定顺序发送给相应的接收者。

对象池(ObjPool):

Id对象池模版,可以方便的创建一个对象池,提供Add,Remove,Get操作,并返回自增长的对象Id,并会抛出对象诞生和消亡的事件。

PS:在初始化的时候需要指定Obj的Name,因为在有obj被添加和删除的时候会分别抛出“ObjName“Add和”ObjName“Remove的事件。

模块(Module):

Module继承自LogicNode,通过ModuleMgr这个对象池进行管理,若模块需要每帧进行的循环操作可通过自身的函数RegisterActive(module_name, fun_name) 来向游戏世界注册。

场景管理概述:

SceneMgr:
管理场景的对象池,并提供简便的加载和卸载场景接口。

SceneBase:
继承自LogicNode的每个场景模版的基类,内置一些常用操作,如场景的拖动及限制范围,缩放是否加载物理世界等等。

Layer:
每个cocos2d的scene下会有多个Layer,这里对cocos2d的Layer进行了一个管理,可通过指定的name取到指定的layer。
提供接口:AddLayer(创建好一个layer后按指定name往里加入),CreateLayer(直接创建一个指定name的layer),GetLayer
PS:每个场景建立后都会有一个默认的名为“main”的layer。

场景UI

提供2种方法,基于Cocos2d和基于CocoStudio的方法。

CocoSudio:

根据Scene的cocos_ui列表来加载对应UI的JSON文件,格式如下:

Scene.cocos_ui = {
    [JSON文件地址] = {
        name = UI名称(不可重复),
        hide = 0, --加载完成后是否隐藏
        button = {逻辑变量名 = 控件名, ...},
        label = {逻辑变量名 = 控件名, ...},
        labelbmfont = {逻辑变量名 = 控件名, ...},
        ...
    }
}

对于按钮类控件,Scene类会有一个OnCocosButtonEvent处理函数,在有按钮被按下等操作时少辉触发,函数内容自己实现,格式如下:

function Scene:OnCocosButtonEvent(ui_name, button_name, event)
    --body
end

其中ui_name就是刚才填入的UI名称,button_name是刚才填入的逻辑变量名,event有4个,定义在Ui.lua中,分别是

Ui.TOUCH_EVENT_BEGAN    = 0
Ui.TOUCH_EVENT_MOVED    = 1
Ui.TOUCH_EVENT_ENDED    = 2
Ui.TOUCH_EVENT_CANCELED = 3

如何创建一个新的场景模版

这里推荐首先为这个场景单独建立一个lua文件,便于以后管理。然后写入以下代码:

local Scene = SceneMgr:GetClass("场景名", 1)
Scene.property = {} --场景属性,如是否可接受触摸事件,是否可拖动,是否可缩放等

function Scene:_Uninit( ... )
 -- body
end

function Scene:_Init( ... )
 -- body
end

function Scene:OnCocosButtonEvent(ui_name, button_name, event)
    --body
end

这样一个基本的场景模版就创建好了,在需要加载的时候只需要调用 SceneMgr:LoadScene(scene_name) 这个接口即可加载这个场景,如果是游戏世界第一次加载场景则需要调用 SceneMgr:FirstLoadScene(scene_name)

小谈通货膨胀--纸币,银行与中央银行

金属货币的时代过去,接下来纸币出现了。
首先我有一个很大的疑问,既然货币是以铸造成本决定价值,为什么在造纸术普及之后纸币还会具有价值呢?
这里就要说纸币是如何出现的了。金属货币最大的不便就是每次出行都要带大量的货币,很重很不方便。所以出现了早期的钱庄帮你保管它们,同时给你开他们的仓单(也就是电视里经常提到的银票),只要提供仓单就可以去他们管辖区域的网点取出对应的货币,钱庄通过在提取真实货币的时候收取一定服务费存活(其实就可以理解为一个区域联网的货币仓库)。钱庄的出现,于是人们发现交易的时候不用交易金银,交易仓单就好了,其实这就是早期的纸币,如我国宋朝时期的“交子”。

继续阅读

小谈通货膨胀--早期的金属货币

前几日去西电玩的时候,在图书馆借了本书,讲通货膨胀的,看完有种茅塞顿开的感脚,趁着还记得把一些所思所想写下来。说来惭愧,虽然是财经学校毕业的,但是在校期间一点经济相关的知识都没学,这篇文章要是写的有啥不对,还望各位同学给予指正。

什么是通货膨胀?
流通的货币代表的价值量超过了市场上商品的价值总量,从而造成货币贬值。

那货币是怎么诞生的呢?
最早的交换媒介是金属,但是这个交易起来有个很麻烦的问题,那就是每次都要称量,于是出现了铸币。铸币就是按照制定规格去铸造钱币,每个都代表指定的重量。但是这样有个问题,铸币是会磨损的,磨损后就没有以前的重量了怎么办?于是就得有个组织出来打包票说,你放心的用我铸的币,就算磨损了在我这也是按足值算,而一般扮演这样角色的是国家。比如中国最早的统一货币秦朝,就用的半两钱,代表这枚钱币重半两,包括后来的汉朝的五铢钱也是。

继续阅读