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文件,格式如下: [cpp] Scene.cocos_ui = { [JSON文件地址] = { name = UI名称(不可重复), hide = 0, –加载完成后是否隐藏 button = {逻辑变量名 = 控件名, …}, label = {逻辑变量名 = 控件名, …}, labelbmfont = {逻辑变量名 = 控件名, …}, … } } [/cpp] 对于按钮类控件,Scene类会有一个OnCocosButtonEvent处理函数,在有按钮被按下等操作时少辉触发,函数内容自己实现,格式如下: [cpp] function Scene:OnCocosButtonEvent(ui_name, button_name, event) –body end [/cpp] 其中ui_name就是刚才填入的UI名称,button_name是刚才填入的逻辑变量名,event有4个,定义在Ui.lua中,分别是 [cpp] Ui.TOUCH_EVENT_BEGAN = 0 Ui.TOUCH_EVENT_MOVED = 1 Ui.TOUCH_EVENT_ENDED = 2 Ui.TOUCH_EVENT_CANCELED = 3 [/cpp]

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

这里推荐首先为这个场景单独建立一个lua文件,便于以后管理。然后写入以下代码: [cpp] 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 [/cpp] 这样一个基本的场景模版就创建好了,在需要加载的时候只需要调用 SceneMgr:LoadScene(scene_name) 这个接口即可加载这个场景,如果是游戏世界第一次加载场景则需要调用 SceneMgr:FirstLoadScene(scene_name)