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)

cocos-lua 架构简介及使用》上有6条评论

  1. 很好,看描述感觉就是我想要的。源码里只有framework目录,能否**一个简单的demo?体现一下事件消息、逻辑模块与表现模块分离等核心内容

  2. 写的很清晰,我看了还有继续看的欲望。加油继续写!!! json是用了第三方插件么?还是怎么搞的?

    • 哈,谢谢鼓励,有些结构已经有些小的调整,因为整个框架只是思想敲定,细节基本还是会慢慢调整。
      json是cocostudio导出的资源文件

发表评论

电子邮件地址不会被公开。