[cocos2dx]基于Cocos2d-x引擎的游戏框架设计

游戏架构与实现

目前,很多基于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

cocos2dcocos2d-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

考虑到传统类型游戏和即时竞技类游戏的差异性,在设计网络模块之初,我们就同时支持了UDPTCP两种通信方式。

为了支持UDP通信方式,我们使用监听器模型,在客户端中设计了UDPAcceptor管理器,专门进行UDP通信方式的初始化、操作和销毁。同时,考虑到UDP通信方式的特殊性,在UDPAcceptor内部,我们对收到的数据进行了杂乱包的过滤,并且使用序列号技术(SequenceNumber),实现了UDP数据包先后顺序的管理和纠正,确保最终交给逻辑层处理的数据包,都是完整可靠有序的。

对于TCP通信方式,我们使用连接器模型,在客户端中封装了TCPConnector管理器。为了解决粘包、拼接、临时数据拷贝等问题,我们在内部设计了特殊的MemNode存储结构,将读取的数据全部存储到MemNode里,其内部根据当前数据的读、写指针位置来进行有效数据定位,确保最终交给上层逻辑使用的数据包,都是完整独立的数据。

网络模块面临着频繁的数据接受和发送,如果不进行控制,频繁的new/delete对性能会有一定影响。因此,我们在网络系统内部使用链表式内存池技术,对接收和发送的数据包都通过该内存池进行统一分配、回收和管理,从根本上解决了频繁的new/delete。另外,在NetSystem内部,使用网络编程中传统的Selector模式进行网络连接的监听、轮询、读取和发送。目前市面上很多游戏对网络模块都是单开线程进行处理,而在我们考虑到多线程同步、数据串行化等问题,所以尽量避免了多线程的方式,使用非阻塞式I/O,全部在逻辑主线程里面进行网络控制管理。

输入控制系统(InputSystem

因为cocos2d-x本身提供的UI控件都有其自身的输入响应机制,所以我们很难直接修改游戏的输入控制系统。此处我们讨论的输入控制系统,主要就是针对CCLayer进行的TouchAccelerate事件控制与管理。

在游戏中,为了对TouchAccelerate事件进行统一的管理和处理,在整个客户端的窗口上,我们特意设计了一个最底层的UILayer(也就是所有UI布局Layout的根窗口)。整个游戏中,仅这个根窗口的CCLayer监听了TouchAccelerate事件,其内部对两种事件进行捕获和处理,然后将对应的事件,存储在内部的输入消息队列中,通过消息事件,通知当前各个游戏管理器调度和处理。

调试器系统(DebugerSystem


在游戏过程中,需要时刻对游戏内的各项性能指标进行监控,判断各个模块、各个环节是否存在着重大的性能问题。因此,我们在客户端中,彻底将调试、监控作为一个核心模块来设计开发,目前主要分为网络模块调试器(NetDebuger)、渲染模块调试器(RenderDebuger)、逻辑模块调试器(LogicDebuger)三大模块(可根据需要动态增加)。对于NetDebuger,主要监控当前网络上下行数据量、接受和发送的数据包个数、网络接受和发送的耗时信息等,并通过曲线图展示;对于RenderDebuger,主要用于监控当前客户端渲染的具体信息,例如DIP数量、像素填充率、渲染顶点数量等,开发者可以通过这些渲染引擎判断当前渲染是否存在性能问题;对于LogicDebuger,管理和统计所有逻辑对象个数、大小、逻辑处理耗时等。我们在实际开发中,通过自行开发的游戏逻辑层调试器系统,结合XCODE本身提供的强大监控工具,可以非常完善仔细地监控各个模块的详细数据、内存、处理耗时等信息,完全满足一般的开发监控需求。

引擎改进与公共代码库游戏中的UI面板,难免会使用到模态窗口,但cocos2d-x引擎并没有提供类似的功能,为了避免在逻辑层编写大量冗余代码来实现该功能,我们需要对cocos2d-x引擎进行必要的修改:在cocos2d-x消息事件处理(CCTouchDispatcher)内部,存在一个事件响应队列,对于所有关心Touch事件的对象,按照优先级从小到大排序,优先级越小,则越优先调度。所以,如果我们需要实现模态窗口的功能,需要自己管理所有UI控件的消息响应级别,并且按照控件之间的父子依赖关系,实现一个类似树的优先级结构,每次需要实现模态窗口时,只要确保其对应的事件优先级在最顶层,并且在处理完消息之后,屏蔽掉该消息,避免继续传递到下面的窗口。

考虑到不同开发者对操作系统、底层接口等熟悉程度不同,为了降低开发成本,我们开发了一套基于iOS平台的基础代码库cobra_ios,其内部封装了开发中常用的各种接口:整套完善的线程安全容器,如数组、单链表、双向循环列表、队列、二叉树等;各种线程控制模型和串行化接口、各种内存管理技术、数据解包器DPacket和数据组包器EPacket。在开发中,所有开发者都统一使用该基础库,使用相同的接口处理,方便开发且提升效率。

cocos2d-xVS.Cocoa

前文提到,cocos2d-x引擎本身没有提供太多UI控件,除开发者自行实现外,我们还可以使用iOS标准的UI控件。熟悉Win32MFC的朋友都知道,Win32标准控件很难与DirectX结合,因为两者是完全相同的渲染机制,但在iOS平台,cocos2d-xCocoa自带的UI控件完全兼容,并可以相互调用,例如在游戏登录界面,我们就可以使用Cocoa自带的NSTextField控件来实现账号和密码输入框。因此,对于游戏开发者来说,学好Cocoa很有必要。

其他

由于iOS平台不支持以动态链接库的方式使用第三方库,所以我们不可能选择Boost+Python的方式进行脚本拓展,不过我们还可以选择Lua等其他可行性比较高的动态语言。工欲善其事,必先利其器,对于中大型项目,除开发客户端外,一般还需要单独开发编辑器进行关卡、场景等编辑处理。对于编辑器的开发,由于引擎cocos2d-x本身完全跨平台,所以我们完全可以使用自己熟悉的语言和平台来开发,选择使用CocoaMFCC#等熟悉的语言,只要确保所有最终的关卡场景数据可被跨平台读取即可。

总结

移动时代,游戏的操作方式,已不仅仅限于传统的鼠标键盘模式,随着触摸、摄像、语音、重力感应等更多操作形式的普及,也为游戏带来了前所未有的机遇和挑战。

当我们阅读此文时,我们学习一个游戏引擎时,要注意的哪些,是否可以把这些归一下类。还有,当我们要构建一个引擎或者是一个自己使用的类库集时,要有哪些来组成。想想,我们平时学习的技术都有哪几类?我们的大部分工作就是封装重构调用库函数。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


    本文实践自 RayWenderlich、Ali Hafizji 的文章《How To Create Dynamic Textures with CCRenderTexture in Cocos2D 2.X》,文中使用Cocos2D,我在这里使用Cocos2D-x 2.1.4进行学习和移植。在这篇文章,将会学习到如何创建实时纹理、如何用Gimp创建无缝拼接纹
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@163.com微信公众号:HopToad 欢迎转载,转载标注出处:http://blog.csdn.netotbaron/article/details/424343991.  软件准备 下载地址:http://cn.cocos2d-x.org/download 2.  简介2.1         引用C
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从Cocos2D-x官网上下载,进入网页http://www.cocos2d-x.org/download,点击Cocos2d-x以下的Download  v3.0,保存到自定义的文件夹2:从python官网上下载。进入网页https://www.python.org/downloads/,我当前下载的是3.4.0(当前最新
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发引擎,易学易用,支持多种智能移动平台。官网地址:http://cocos2d-x.org/当前版本:2.0    有很多的学习资料,在这里我只做为自己的笔记记录下来,错误之处还请指出。在VisualStudio2008平台的编译:1.下载当前稳
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《最强大脑》娱乐节目。将2048改造成一款挑战玩家对数字记忆的小游戏。邮箱:appdevzw@163.com微信公众号:HopToadAPK下载地址:http://download.csdn.net/detailotbaron/8446223源码下载地址:http://download.csdn.net/
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试以QtCreatorIDE来进行CMake构建。Cocos2d-x3.X地址:https://github.com/cocos2d/cocos2d-x1.打开QtCreator,菜单栏→"打开文件或项目...",打开cocos2d-x目录下的CMakeLists.txt文件;2.弹出CMake向导,如下图所示:设置
 下载地址:链接:https://pan.baidu.com/s/1IkQsMU6NoERAAQLcCUMcXQ提取码:p1pb下载完成后,解压进入build目录使用vs2013打开工程设置平台工具集,打开设置界面设置: 点击开始编译等待编译结束编译成功在build文件下会出现一个新文件夹Debug.win32,里面就是编译
分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net前言上次用象棋演示了cocos2dx的基本用法,但是对cocos2dx并没有作深入的讨论,这次以超级马里奥的源代码为线索,我们一起来学习超级马里奥的实
1. 圆形音量button事实上作者的本意应该是叫做“电位计button”。可是我觉得它和我们的圆形音量button非常像,所以就这么叫它吧~先看效果:好了,不多解释,本篇到此为止。(旁白: 噗。就这样结束了?)啊才怪~我们来看看代码:[cpp] viewplaincopyprint?CCContro
原文链接:http://www.cnblogs.com/physwf/archive/2013/04/26/3043912.html为了进一步深入学习贯彻Cocos2d,我们将自己写一个场景类,但我们不会走的太远,凡是都要循序渐进,哪怕只前进一点点,那也至少是前进了,总比贪多嚼不烂一头雾水的好。在上一节中我们建
2019独角兽企业重金招聘Python工程师标准>>>cocos2d2.0之后加入了一种九宫格的实现,主要作用是用来拉伸图片,这样的好处在于保留图片四个角不变形的同时,对图片中间部分进行拉伸,来满足一些控件的自适应(PS: 比如包括按钮,对话框,最直观的形象就是ios里的短信气泡了),这就要求图
原文链接:http://www.cnblogs.com/linji/p/3599478.html1.环境和工具准备Win7VS2010/2012,至于2008v2版本之后似乎就不支持了。 2.安装pythonv.2.0版本之前是用vs模板创建工程的,到vs2.2之后就改用python创建了。到python官网下载版本2.7.5的,然后
环境:ubuntu14.04adt-bundle-linux-x86_64android-ndk-r9d-linux-x86_64cocos2d-x-3.0正式版apache-ant1.9.3python2.7(ubuntu自带)加入环境变量exportANDROID_SDK_ROOT=/home/yangming/adt-bundle-linux/sdkexportPATH=${PATH}:/$ANDROID_SDK_ROOTools/export
1开发背景游戏程序设计涉及了学科中的各个方面,鉴于目的在于学习与进步,本游戏《FlappyBird》采用了两个不同的开发方式来开发本款游戏,一类直接采用win32底层API来实现,另一类采用当前火热的cocos2d-x游戏引擎来开发本游戏。2需求分析2.1数据分析本项目要开发的是一款游
原文链接:http://www.cnblogs.com/linji/p/3599912.html//纯色色块控件(锚点默认左下角)CCLayerColor*ccc=CCLayerColor::create(ccc4(255,0,0,128),200,100);//渐变色块控件CCLayerGradient*ccc=CCLayerGradient::create(ccc4(255,0,0,
原文链接:http://www.cnblogs.com/linji/p/3599488.html//载入一张图片CCSprite*leftDoor=CCSprite::create("loading/door.png");leftDoor->setAnchorPoint(ccp(1,0.5));//设置锚点为右边中心点leftDoor->setPosition(ccp(240,160));/
为了答谢广大学员对智捷课堂以及关老师的支持,现购买51CTO学院关老师的Cocos2d-x课程之一可以送智捷课堂编写图书一本(专题可以送3本)。一、Cocos2d-x课程列表:1、Cocos2d-x入门与提高视频教程__Part22、Cocos2d-x数据持久化与网络通信__Part33、Cocos2d-x架构设计与性能优化内存优
Spawn让多个action同时执行。Spawn有多种不同的create方法,最终都调用了createWithTwoActions(FiniteTimeAction*action1,FiniteTimeAction*action2)方法。createWithTwoActions调用initWithTwoActions方法:对两个action变量初始化:_one=action1;_two=action2;如果两个a
需要环境:php,luajit.昨天在cygwin上安装php和luajit环境,这真特么是一个坑。建议不要用虚拟环境安装打包环境,否则可能会出现各种莫名问题。折腾了一下午,最终将环境转向linux。其中,luajit的安装脚本已经在quick-cocos2d-x-develop/bin/中,直接luajit_install.sh即可。我的lin
v3.0相对v2.2来说,最引人注意的。应该是对触摸层级的优化。和lambda回调函数的引入(嗯嗯,不枉我改了那么多类名。话说,每次cocos2dx大更新。总要改掉一堆类名函数名)。这些特性应该有不少人研究了,所以今天说点跟图片有关的东西。v3.0在载入图片方面也有了非常大改变,仅仅只是