基于cocos2d-x引擎的游戏框架设计
使用 cocos2d-x 和 Lua 快速开发游戏(1)

下面就分别叙述不同平台下开发环境的搭建步骤。
搭建 Mac 平台的 HOST 运行环境因为 cocos2d-x 对 Lua 的支持在不断改进中,所以最好从 下载最新 master 分支的cocos2d-x 源代码来编译 HOST。
拿到最新源代码后,⼀一定要记得执行 sudo install-templates-xcode.sh -f 重新安装模版。
准备工作做好后,新建⼀一个 LuaHost 项目,使用 cocos2dx_lua 模版,并设置为在模拟器中运行。
由于 iOS 5.x 的模拟器有⼀一个 bug,会在游戏运行时输出大量无关的警告信息,影响我们调试开发,所以还要在 Xcode 中设置运行目标为 iOS 4.3 模拟器。
接下来,修改 AppDelegate.cpp 文件,将 applicationDidFinishLaunching() 函数中载入 Lua 脚本的代码做⼀一些修改。
改动前:string path = CCFileUtils::fullPathFromRelativePath("hello.lua");pEngine->addSearchPath(path.substr(0, path.find_last_of("/")).c_str()); pEngine->executeScriptFile(path.c_str());改动后:string path = CCFileUtils::fullPathFromRelativePath("scripts/");pEngine->addSearchPath(path.c_str());path = CCFileUtils::fullPathFromRelativePath("scripts/main.lua");CCLOG("\nLOAD LUA FILE: %s\n", path.c_str());pEngine->executeScriptFile(path.c_str());代码改动的目的是让我们可以将 Lua 脚本放置在单独的目录中。
Cocos2D-X for XNA游戏开发指南(上)

非常绚丽的应用程序外观。Sl rg t i el h集成了一些 v i 传统 的控 件 , 实现高品质 的文本 、矢量图、媒体 动画效果及数据绑定等功能 。 iel h适用于开 Sl rg t v i 发具有固定页面外观的应用程序, 如新浪微博。 X NA  ̄a wok me r其设计初 衷是为了让游戏开发 变得 更简单 。 使用X A, N 一方面你不必考虑创建
mp n n ,所 u方 正 是在 此背景 下 , c s D— 社 区联 合 国内知 Co o e t 以去掉 了r n 法中实现 的循 Co o 2 x me o o e t 名 的Wid wsP o e 交游戏平 台O e X ie 环 ,因为Ga C mp n n本身就 实现 了游戏的 n o h n社 p n Lv C pi t 的Up ae c o d t重载方法处 移植 了C c 2 X frX 版 本,大大降低 了在 循环 结构 。C Ap l ain o o D— o NA 理T u h o c 事件 , rw重载方法调用C Drco的 Da C i tr e Wid ws h n平 台上开发游戏的难度。 n o oe P
W id ws h n ] J 开 发 n o o e, f P :J  ̄
Coo2 入W id ws h n 平 台 csD进 n o oe P
我们知道 , 在Wid wsP o e n o h n 系统上开发应用程 我们看 到, N 已帮助我们处理了很多事情, X A 大 序有两种选择:S v rg to n o h n  ̄ 大 降低了游戏开发难度 , i el h r d wsP o e l i f Wi 例如不需要管理窗 口、
cocos lua 组件父类方法 -回复

cocos lua 组件父类方法-回复Cocos Lua 组件父类方法详解Cocos2d-x 是一个跨平台、开源的游戏开发框架,它能够支持游戏开发者同时在多个主流平台上开发游戏,包括Windows、Mac、Linux、iOS 和Android 等。
Cocos2d-x 提供了丰富的功能和强大的工具,使得游戏开发更加容易和高效。
在Cocos2d-x 中使用Lua 作为脚本语言来编写游戏逻辑十分常见,Lua 作为一种轻量级的脚本语言,使得游戏逻辑可以在不重新编译游戏引擎的情况下进行调整和修改,从而大大提高了游戏开发的效率。
在Cocos2d-x 中,组件(Component) 是一种常见的编程模式,用于将游戏对象的功能和属性分离开,使得对象可以以更加灵活和可扩展的方式进行设计。
每个组件都是一个Lua 脚本,可以通过继承父类方法来定义自己的行为和功能。
本文将重点介绍Cocos Lua 中组件父类方法的使用,通过一步一步的解释,帮助读者深入了解这一部分的用法和意义。
1. 组件的定义和继承首先,我们需要了解如何定义一个组件并继承父类方法。
在Cocos2d-x的Lua 中,可以通过如下的方式定义一个组件:local MyComponent = class("MyComponent", function() return ponent:create()end)这段代码中,我们定义了一个名为MyComponent 的组件,并通过ponent:create() 创建了一个父类对象。
接下来,我们可以使用MyComponent 来定义我们自己的方法和属性。
2. 组件的生命周期方法组件的生命周期方法是在特定的时间点被调用的,比如当组件被添加到一个游戏对象时、组件更新时或组件被移除时。
这些方法允许我们在特定的时间点做一些额外的操作。
function MyComponent:ctor()组件被创建时调用endfunction MyComponent:onEnter()组件被添加到游戏对象时调用endfunction MyComponent:onExit()组件从游戏对象中移除时调用endfunction MyComponent:update(dt)组件更新时调用end在上述代码中,ctor() 方法会在组件被创建时调用,我们可以在这里进行一些初始化操作。
Cocos2d-x游戏实例-《跑跑跑》制作教程(第七篇)添加能吃的物品以及胜利条件

Cocos2d-x游戏实例-《跑跑跑》制作教程(第七篇)——添加能吃的物品以及胜利条件
我们的游戏已经很像游戏了(像?敢情它真的不是一个游戏?),于是我们给主角加点吃的吧,老是这么跑,没有追求啊喂~
1.画点吃的物体
现在,我们又要打开我们的地图编辑器,把下面的星星作为可以吃的物品画到barrier地图层上:
看看我的画吧,依旧有大师风范~噗
2.添加“另类”障碍物。
其实,吃的物品,也可以当成是障碍物,只不过这个障碍物和主角碰撞之后会消失,仅此而已。
于是,我们和之前描红格子的方式一样,不过,这次我们要描蓝色格子,选择图块上的蓝色格子,噢,抱歉,它是绿色的= =。
右键,属性,我们给绿色格子添加一个属性,叫做“star”,属性值为true。
然后,我们把地图切换到meta层,在上面用绿色格子把我们的所有星星都覆盖~效果如下:
是很好,但是,暂时就这么做吧。
chapter6 游戏界面设计

游戏的可玩性与交互界面
• 游戏可玩性的基础是交互界面的可用性。 • 游戏界面的可操作性,包括手眼协调、条件反射和难度递增 等,是游戏可玩性的一个基本要素。 • 交互界面的沉浸感是大多数游戏可玩性的共性要素之一。 • 交互界面的操作效率也是游戏可玩性的要素之一。
交互界面的设计基础 • 色彩设计:
色彩的运用对交互界面的设计至关重要。优秀的色彩搭
对象结构面板是用来显示画
布中所有控件的一个列表。
列表中不仅列举了所有的控
件,还通过缩进描述了控件之间
的关系,在对控件做管理的时候
将会更加方便。
Cocos Studio用户界面编辑器的介绍 • UI动画面板
UI动画主要是针对界面上的控件做一些复合的属性 变化,通过简单的属性设置就能够实现很多动画效果, 对于程序来说往往这部分占用了大量的时间。
Cocos2d-x中的用户交互
EventListener的继承关系
Cocos2d-x中的用户交互
• 触摸事件 在Cocos2d-x中,可以为任意一个游戏元素添加接收事件, Cocos2d-x中的Layer提供了很好的技术支持。Layer类封装了 触摸输入的接口,用于接收输入事件。Layer类中还可以使用 setTouchEnabled方法来打开或着关闭接收触摸的输入。 •单点触摸事件(EventListenerTouchOneByOne) •多点触摸事件(EventListenerTouchAllAtOnce)
1.创建项目 打开CocosStudio,选择UI Editor,在界面中选择文件->新建即可创 建一个新项目,在界面的左上角显示的是画布大小,可以调整,这里我们 设置为960x640。创建好后出现如下界面。
Cocos Studio用户界面编辑器的使用
x-studio365游戏开发工具集软件用户文档

x-studio365游戏开发工具集软件用户文档Rev.1.01x-studio365游戏开发工具集软件(以下简称x-studio365软件)简介: x-studio365软件是一款基于cocos2d-x游戏引擎开发的工具;为更加方便游戏开发者而生,具有完整粒子编辑功能,场景(UI)编辑功能,屏幕适配预览功能(让手动适配问题彻底解放),可实时预览游戏界面在任意尺寸移动终端的显示效果。
本软件主要特色:(1)直接使用cocos2d-x引擎渲染主编辑界面,效果实时可靠(2)支持多达20种布局对齐方式, 免去游戏UI界面设计时用肉眼对齐控件的困扰(3)节点多选,整体移动,改变大小(4)画布缩放,浮动(5)支持粒子编辑功能(6)屏幕适配预览功能,可预览任意设备尺寸效果(6)支持导入csb(将csb文件拖入编辑器场景即可)和发布到csb给ccoos2d-x引擎直接使用(7)灵活的UI节点父子关系,不论是精灵,按钮,层还是粒子节点均可作为父节点承载其他节点(8)具有AES批量数据加密工具, 具有AES CBC模式批量数据加密解密,MD5校验,特定格式文件提取,差异文件提取等功能.(9)spine骨骼动画预览用法:将spine导出的.atlas文件拖入场景即可.(10)粒子编辑器,支持动态范围滑块调参(11)支持导入CocosStudio .ccs工程以及CocosStudio发布的.json 格式 UI工程x-studio365软件各界面说明(1)主菜单栏(2)工具栏,包含设计尺寸选择,横竖屏选择,设备预览尺寸选择,保存,高级UI布局对齐等功能(3)场景视图: 显示工程所有场景列表,通过双击场景名可切换场景(4)场景对象探查器: 当前场景中UI节点树形结构,可快速锁定和隐藏场景上的对象,通过在节点树种拖动节点可改变场景对象的渲染层级和父子节点关系(5)可视化编辑和预览界面, 此界面由cocos2d-x游戏引擎渲染, 为软件的核心界面(6)属性编辑界面,用于显示和实时修改场景对象的属性(7)工具箱界面,包含所有软件支持的UI控件和粒子系统对象(8)输出界面,软件运行过程中日志输出x-studio365软件使用说明(1)新建工程: 通过软件主菜单【文件】【新建工程】在弹出的对话框中输入工程名和选择工程目录后点击确认按钮即可, 新建工程后,会自动添加一个默认场景scene1, 如图所示(2)新建场景: 通过软件主菜单【文件】【新建场景】在弹出的对话框中输入场景名称,然后点击确认即可,注意场景名称不能和工程已有场景重复。
游戏开发引擎—Cocos2d-x 3.2开发《大富翁》退出对话框

游戏开发引擎—Cocos2d-x 3.2开发《大富翁》04_ 退出对话框本文检索关键词:游戏引擎,游戏开发引擎,cocos引擎html5游戏开发上一节中介绍了如何制作菜单场景,本节主要讲如何制作游戏中的退出对话框。
效果图:首先看看在MenuScene.cpp如是如何调用对话框的:1 2 3 4 5 6 7 8 9 void MenuScene::popupLayer(){// 定义一个弹出层,传入一张背景图PopupLayer* popDialog = PopupLayer::create(DIALOG_BG);// ContentSize 是可选的设置,可以不设置,如果设置把它当作 9 图缩放popDialog->setContentSize(CCSizeMake(Quit_Dialog_Size_Width, Quit_Dialog_Size_Height)); popDialog->setTitle(DIALOG_TITLE);popDialog->setContentText(DIALOG_CONTENT, 20, 60, 250);// 设置回调函数,回调传回一个 CCNode 以获取 tag 判断点击的按钮popDialog->setCallbackFunc(this, callfuncN_selector(MenuScene::quitButtonCallback));10 11 12 13 14 // 添加按钮,设置图片,文字,tag 信息popDialog->addButton(BUTTON_BG1, BUTTON_BG3, OK, Btn_Quit_OK_TAG);popDialog->addButton(BUTTON_BG2, BUTTON_BG3, CANCEL, Btn_Quit_Cancel_TAG); this->addChild(popDialog);// 添加到当前层}PopupLayer.h 和 PopupLayer.cpp 是弹出对话框的代码:首先看PopupLayer.h1 2 3 4 5 6 7 8 9 10 11 12 const int Pop_FontSize = 20;//定义字体大小class PopupLayer :public Layer{static PopupLayer * create(const char* backgroundImage);//根据背景图创建对象void setTitle(const char* title ,int fontsize=Pop_FontSize);//设置对话框标题void setContentText(const char* text ,int fontsize=Pop_FontSize ,int padding=50 ,int paddintTop=100);//设置对话框文本内容void setCallbackFunc(Object* target, SEL_CallFuncN callfun);//设置按键回调方法bool addButton(const char* normalImage, const char* selectedImage, const char* title, int tag=0);//添加对话框按键,如确认取消virtual void onEnter();//当进入时调用virtual void onExit();//13 14 15 16 17 18 19 20 void buttonCallback(CCObject* pSender);int m_contentPadding;// 文字内容两边的空白区距离int m_contentPaddingTop; //文字上边空白区距离CCObject* m_callbackListener;SEL_CallFuncN m_callback;//定义具有retain 属性的变量CC_SYNTHESIZE_RETAIN(Menu*, m__pMenu, MenuButton);CC_SYNTHESIZE_RETAIN(Sprite*, m__sfBackGround, SpriteBackGround);…………………….};PopupLayer.cpp 部分代码如下:1 2 3 4 5 6 7 8 PopupLayer::PopupLayer():m__pMenu(NULL), m_contentPadding(0), m_contentPaddingTop(0), m_c allbackListener(NULL), m_callback(NULL), m__sfBackGround(NULL), m__s9BackGround(NULL), m__ltContentText(NULL), m__ltTitle(NULL){}//释放变量PopupLayer::~PopupLayer()9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2{CC_SAFE_RELEASE(m__pMenu);CC_SAFE_RELEASE(m__sfBackGround);CC_SAFE_RELEASE(m__ltContentText);CC_SAFE_RELEASE(m__ltTitle);CC_SAFE_RELEASE(m__s9BackGround);}void PopupLayer::setCallbackFunc(cocos2d::Object *target, SEL_CallFuncN callfun) {//menuItem根据调传入的对象,会进行方法的回调m_callbackListener = target;m_callback = callfun;}bool PopupLayer::init(){// 初始化需要的 Menu,随后跟进参数向menu中添加Item选项Menu* menu = Menu::create();menu->setPosition(CCPointZero);setMenuButton(menu);setTouchMode(Touch::DispatchMode::ONE_BY_ONE);auto listener = EventListenerTouchOneByOne::create();listener->setSwallowTouches(true);0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 listener->onTouchBegan = [](Touch *t,Event *e){CCLog("PopupLayer touch");return true;};_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);//屏蔽下层事件响应 return true;}132333435根据参数、标题、tag、图片效果,添加MenuItem选项:1 2 3 4 5 6 7 8 9 1 0 bool PopupLayer::addButton(const char *normalImage, const char *selectedImage, const char *title, in t tag){Size winSize = CCDirector::getInstance()->getWinSize();Point pCenter = ccp(winSize.width / 2, winSize.height / 2);// 创建MenuItem按钮,并设置回调方法MenuItemImage* menuImage = MenuItemImage::create(normalImage, selectedImage, this, menu_ selector(PopupLayer::buttonCallback));menuImage->setTag(tag);menuImage->setPosition(pCenter);// 给MenuItem添加文字说明并设置在MenuItem中位置11 12 13 141516Size imenu = menuImage->getContentSize();LabelTTF* ttf = LabelTTF::create(title, "", 20);ttf->setColor(ccc3(0, 0, 0));ttf->setPosition(ccp(imenu.width / 2, imenu.height / 2));menuImage->addChild(ttf);getMenuButton()->addChild(menuImage);return true;现在来看MenuItem 的回调方法buttonCallback1 2 3 4 5 6 7 void PopupLayer::buttonCallback(cocos2d::CCObject *pSender){Node* node = dynamic_cast<Node*>(pSender);CCLog("touch tag: %d", node->getTag());if (m_callback && m_callbackListener){(m_callbackListener->*m_callback)(node);//这会调用setCallbackFunc ()方法传入的MenuScene 对象的quitButtonCallback ()方法9 this->removeFromParent();//把对话框从父节点移除}对话框弹出前调用onEnter方法进行界面初始化工作1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1void PopupLayer::onEnter(){…………………..Size contentSize;// 设置对话框背景,代码省略// 添加按钮,并设置其位置this->addChild(getMenuButton());float btnWidth = contentSize.width / (getMenuButton()->getChildrenCount() + 1);Vector<Node*> vecArray = getMenuButton()->getChildren();int j=0;for(auto it=vecArray.begin();it!=vecArray.end();it++){Node* node = dynamic_cast<Node*>(*it);node->setPosition(Point(winSize.width/2 - contentSize.width/2+btnWidth*(j+1),winSize.height/2-c ontentSize.height/3));j++;14 15 16 17 18 19 2 0 2 1 2 2 2 3 2 // 显示对话框标题内容省略// 添加对话框弹出效果Action* popupLayer = Sequence::create(ScaleTo::create(0.0, 0.0), ScaleTo::create(0.15, 1.05),ScaleTo::create(0.08, 0.95),ScaleTo::create(0.08, 1.0),NULL);this->runAction(popupLayer);}425代码写的稍微多了些,为便于测试,我把代码上传一下,下载:cocos2d-x-3.2_richer(第四部分).rar。
cocos creator调用java方法

cocos creator调用java方法(最新版3篇)目录(篇1)1.引言2.cocos creator 简介3.java 方法在 cocos creator 中的调用方法4.实际应用示例5.结语正文(篇1)1.引言在游戏开发中,Cocos Creator 是一款功能强大的游戏开发引擎,它支持多种编程语言,如 JavaScript、TypeScript 和 Java。
Java 是一种广泛使用的编程语言,具有丰富的类库和开发者社区。
因此,在 Cocos Creator 中调用 Java 方法可以极大地提高开发效率。
本文将介绍如何在Cocos Creator 中调用 Java 方法。
2.Cocos Creator 简介Cocos Creator 是基于 Cocos2d-x 引擎的一款游戏开发工具。
Cocos2d-x 是一款开源的跨平台游戏开发框架,支持多种操作系统和平台。
Cocos Creator 提供了可视化的编辑器,方便开发者设计和开发游戏。
同时,Cocos Creator 支持多种编程语言,使得开发者可以根据项目需求选择合适的编程语言进行开发。
3.Java 方法在 Cocos Creator 中的调用方法要在 Cocos Creator 中调用 Java 方法,需要遵循以下步骤:(1) 创建 Java 类并实现相应的方法。
(2) 在 Cocos Creator 中,将 Java 类添加到项目中。
(3) 在 Cocos Creator 中的 JavaScript 或 TypeScript 文件中,通过 Type 类引用 Java 类,并调用相应的方法。
以下是一个简单的示例:Java 类:```javapublic class JavaExample {public void exampleMethod() {System.out.println("This is a Java method.");}}```在 Cocos Creator 中,将 Java 类添加到项目中。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
基于cocos2d-x引擎的游戏框架设计移动互联网浪潮正在彻底改变人们日常的生活习惯和生活方式。
相应的,基于移动终端和感应交互的游戏,也为人们带来了全新的游戏体验。
本文,我们将结合目前流行的cocos2d-x 引擎,使用C++语言,基于iOS平台,和大家分享iPhone、iPad上游戏客户端的构架与实现。
游戏架构与实现目前,很多基于cocos2d-x的代码基本上仅是对引擎功能的使用,完全不能按照游戏项目的标准来参考。
作为游戏项目代码,不仅需要实现游戏的诸多功能,还需要从架构层面,从模块设计的角度来思考和设计,使代码具有更好的复用性和拓展性。
对于游戏客户端,按照功能模块的区别可分为:引擎封装层模块、游戏数据管理模块、应用程序配置模块、日志记录模块、网络管理模块、消息事件机制模块、输入输出控制模块、音效管理模块、UI系统模块、逻辑系统处理模块、调试器控制模块等。
针对不同类型的游戏,通常只需要单独实现最上层的游戏逻辑系统,而剩余的模块完全可以复用。
下面将详细讲解各个模块的职能与实现(暂不包含游戏逻辑系统)。
引擎封装模块(EngineSystem)为了减少客户端代码对cocos2d-x引擎的依赖程度和降低耦合度,我们建立了引擎封装层模块,将引擎必要的初始化、逻辑更新、渲染和资源管理等操作全部交给引擎封装层处理,使客户端的其他模块不需要过于依赖引擎层。
同时,为了避免客户端代码中频繁、直接地调用平台相关的诸多功能,我们还将一些平台相关的功能全部封装在引擎封装层模块内。
cocos2d-x功能很多很强大,但在开发时,需要根据项目需要有条件选择引擎功能(当然,cocos2d-x本身设计实现的很好)。
例如,在引擎封装层内部,我们仅使用了一个CCScene 对象,在设计之初就刻意避免处理多个CCScene之间的初始化、跳转、销毁、更新等操作,极大地简化了逻辑层代码,降低了复杂度,且到目前为止,在表现效果上没有什么影响。
数据管理模块(DBSystem)在开发过程中经常会存储和读取大量的静/动态数据,对比我们针对这部分设计了DBSystem 模块,专门进行游戏数据层的管理。
每种类型的游戏数据都会派生出一个具体的类,如音效数据管理器、图片数据管理器等。
这些数据管理器都在DBSystem内部统一进行初始化、更新和销毁,并各自使用单例模式。
外层使用时,直接通过其类进行数据读取即可,无须关心其初始化、逻辑更新、销毁等操作。
同时,为了时刻对游戏的静态数据进行监控,所有的数据模块都暴露了获取其所包含数据的接口,这样我们就可以在游戏中随时获取数据层的信息,方便进行统计和监控。
应用配置系统(VariableSystem)开发者一般需要对应用属性进行可配置化处理:一方面可以方便开发者快速开启/屏蔽某些功能;另一方面能更人性化地支持用户偏好设置。
目前,我们根据类型的不同,建立了账号、网络、日志三种配置文件,分别对游戏账号、游戏功能信息、游戏网络配置信息、游戏日志配置信息进行动态设置,全部使用XML进行数据存储和读取。
在开发中通常需要保存大量临时数据,这些数据往往被放在各个模块内部,如果其他模块需要使用,就造成两个模块间强行依赖,增加了耦合度。
所以,我们将所有临时需要的数据统一定位为内存配置数据,放在我们的应用配置系统中,其和账号、网络、日志配置文件的区别在于:基于文件配置的属性数据都需要在程序退出时强行写回文件,而基于内存配置的属性数据无须保存。
音效控制模块(SoundSystem)iOS平台并没有十分完善的音效引擎,而一般自行实现的音效库都难以进行拓展和支持跨平台,所以我们直接选取流行的FmodEx引擎,进行游戏音效的播放和管理。
同时,结合FmodEx提供的强大接口,可以很方便地实现声音大小设置、暂停、循环、3D音效等操作,完全满足一般游戏的需求。
在游戏中,一般都需要频繁的播放多个音效,为了提高效率并节省内存,我们在逻辑层对每一个音效文件都使用了引用计数技术,对同一种音效文件仅需通过计数的方式维持一份实例即可,同时播放的多个相同音效,实际上都是使用同样的一份实例而已,无须单独创建音效实例;另外,通过引用计数,很好地解决了音效资源回收的问题,当音效资源计数为零时,即表示其可以被回收,对应的资源,占用的内存也将被释放。
日志系统模块(LoggerSystem)为了方便在开发、运营期对出现的问题及时进行定位和排查,对游戏中关键的处理流程都需要进行日志记录。
在客户端,我们仿照Log4J的方式,实现了分级(Trace级、Info级、Error 级等)、分文件、分输出方式的强大日志管理。
游戏的日志模块,结合了应用配置系统,完全实现了动态化配置,通过对日志配置文件进行设置修改,开发者可以很方便地设置日志的开启等级、输出方式、大小拆分、输出名称等。
另外,对于客户端日志模块,无须过多考虑其性能问题,所以我们的日志模块,完全是简单地在主线程里进行文件写入,没有多开线程进行文件操作。
消息事件系统模块(EventSystem)考虑到客户端框架总体的拓展性,我们完全使用事件驱动模型(Event-driven)来设计和开发,将客户端中事件的触发时机和具体处理逻辑彻底分隔开。
游戏的各个模块,仅需要注册、监听和实现其关心的消息事件,而无须关心事件何时被触发,降低了总体耦合度。
目前游戏中所有UI面板的隐藏/显示、事件响应、音效的播放/停止、游戏流程的切换、游戏角色状态迁移等,完全通过事件驱动方式开发;同时这种基于事件的处理方式,为项目使用动态脚本拓展提供了支持:脚本层省去对逻辑代码的大量直接调用,通过消息事件完成脚本层和逻辑层的交互调度,大大简化了开发的复杂度。
UI系统(GUISystem)cocos2d、cocos2d-x这两种引擎本身并没有提供太多UI控件,仅提供了按钮、进度条等基础控件,如果想使用更多的UI控件,需要开发者借鉴或使用其他成熟的GUI引擎,如CEGUI 等。
在我们的UI系统中,充分借鉴了CEGUI的设计思想。
整体上,将游戏中有关联的UI控件集中到一个个单独的CCLayer上,组成多个独立的Layout,也就是我们在代码中定义的IWindow 类。
每一个IWindow类,都包含其自身的根面板(CCLayer)和众多依附在其上的子UI控件。
通过IWindow,我们实现了对所有UI布局Layout进行统一的接口调用和处理,如初始化加载、消息注册与响应、隐藏/显示、销毁等。
虽然我们在之前的多个项目开发中提倡将窗口的逻辑实现全部交给动态语言(Python&Lua)来实现,但对于某一些UI功能,并不适合使用脚本来进行逻辑拓展。
对于这类难度比较大、复杂度特别高的UI处理,使用原生的C++开发可能更为合适,所以,在UI系统中,针对这两种不同的需求,我们对IWindow进行了拓展:对需要使用脚本来拓展逻辑的Layout,派生出UIWindowByScript类,其内部主要通过消息事件机制将对应窗口的初始化、加载、逻辑更新、事件处理、销毁等操作传递给对应的脚本逻辑处理;对于需要使用C++来进行处理的Layout,直接根据功能需要,从IWindow上派生出各个具体的实现类。
目前的UI布局还未完全通过外部配置文件动态实现,我们将借鉴CEGUI的处理方式,将所有UI的布局信息、控件属性与事件响应处理等全部使用外层配置文件实现,从而将这些静态信息和程序分隔开,达到动态配置的目的。
网络管理模块(NetSystem)考虑到传统类型游戏和即时竞技类游戏的差异性,在设计网络模块之初,我们就同时支持了UDP和TCP两种通信方式。
为了支持UDP通信方式,我们使用监听器模型,在客户端中设计了UDPAcceptor管理器,专门进行UDP通信方式的初始化、操作和销毁。
同时,考虑到UDP通信方式的特殊性,在UDPAcceptor内部,我们对收到的数据进行了杂乱包的过滤,并且使用序列号技术(Sequence Number),实现了UDP数据包先后顺序的管理和纠正,确保最终交给逻辑层处理的数据包,都是完整可靠有序的。
对于TCP通信方式,我们使用连接器模型,在客户端中封装了TCPConnector管理器。
为了解决粘包、拼接、临时数据拷贝等问题,我们在内部设计了特殊的MemNode存储结构,将读取的数据全部存储到MemNode里,其内部根据当前数据的读、写指针位置来进行有效数据定位,确保最终交给上层逻辑使用的数据包,都是完整独立的数据。
网络模块面临着频繁的数据接受和发送,如果不进行控制,频繁的new/delete对性能会有一定影响。
因此,我们在网络系统内部使用链表式内存池技术,对接收和发送的数据包都通过该内存池进行统一分配、回收和管理,从根本上解决了频繁的new/delete。
另外,在NetSystem内部,使用网络编程中传统的Selector模式进行网络连接的监听、轮询、读取和发送。
目前市面上很多游戏对网络模块都是单开线程进行处理,而在我们考虑到多线程同步、数据串行化等问题,所以尽量避免了多线程的方式,使用非阻塞式I/O,全部在逻辑主线程里面进行网络控制管理。
输入控制系统(InputSystem)因为cocos2d-x本身提供的UI控件都有其自身的输入响应机制,所以我们很难直接修改游戏的输入控制系统。
此处我们讨论的输入控制系统,主要就是针对CCLayer进行的Touch 和Accelerate事件控制与管理。
在游戏中,为了对Touch和Accelerate事件进行统一的管理和处理,在整个客户端的窗口上,我们特意设计了一个最底层的UILayer(也就是所有UI布局Layout的根窗口)。
整个游戏中,仅这个根窗口的CCLayer监听了Touch和Accelerate事件,其内部对两种事件进行捕获和处理,然后将对应的事件,存储在内部的输入消息队列中,通过消息事件,通知当前各个游戏管理器调度和处理。
调试器系统(DebugerSystem)在游戏过程中,需要时刻对游戏内的各项性能指标进行监控,判断各个模块、各个环节是否存在着重大的性能问题。
因此,我们在客户端中,彻底将调试、监控作为一个核心模块来设计开发,目前主要分为网络模块调试器(NetDebuger)、渲染模块调试器(RenderDebuger)、逻辑模块调试器(LogicDebuger)三大模块(可根据需要动态增加)。
对于NetDebuger,主要监控当前网络上下行数据量、接受和发送的数据包个数、网络接受和发送的耗时信息等,并通过曲线图展示;对于RenderDebuger,主要用于监控当前客户端渲染的具体信息,例如DIP数量、像素填充率、渲染顶点数量等,开发者可以通过这些渲染引擎判断当前渲染是否存在性能问题;对于LogicDebuger ,管理和统计所有逻辑对象个数、大小、逻辑处理耗时等。