毕业论文基于cocos2dx游戏引擎的小鸡对抗游戏开发_第1页
毕业论文基于cocos2dx游戏引擎的小鸡对抗游戏开发_第2页
毕业论文基于cocos2dx游戏引擎的小鸡对抗游戏开发_第3页
毕业论文基于cocos2dx游戏引擎的小鸡对抗游戏开发_第4页
毕业论文基于cocos2dx游戏引擎的小鸡对抗游戏开发_第5页
已阅读5页,还剩39页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

基于Cocos2d-x的小鸡对抗游戏开发PAGE44目录摘要 IIAbstract III1 前言 42 相关技术支持 5 Cocos2d-x框架层 5 渲染 5 动画 5 事件分发 5 网络 5 UI 5 Cocos2d-x设计模式[13] 5 单例模式 5 二段构建模式 6 管理者模式 6 外观模式[16] 6 防御式编程模式 7 观察者模式 7 组合模式 7 中介者模式 73 游戏总体分析与设计 8 游戏规则 8 玩法介绍 8 鸡类介绍 8 捕捉成功率 8 道具介绍 8 游戏关卡 8 关卡场景 8 关卡限定 8 关卡数组 8 游戏总体设计 8 游戏设计流程 9 游戏逻辑流程 94 游戏详细设计和实现 13 菜单场景的实现 13 初始化的界面 14 按钮回调 15 关卡选择场景的实现 18 游戏场景的实现 22 World(地图) 23 Number(生命值) 24 ChickenManager(小鸡管理器) 24 Number(道具管理器) 30 场景的具体实现 315 总结 38致谢 39参考文献 40基于Cocos2d-x游戏引擎的小鸡对抗游戏开发摘要本文基于cocos2d_x游戏引擎,结合当前生活中所遇到的H7N9而自制的一款休闲类游戏“小鸡对抗”,该游戏实现了玩家与感染有病毒的小鸡做斗争的过程,玩家需要通过一系列的道具去消灭患有H7N9的小鸡,从而获得胜利,该游戏提高了玩家对H7N9的重视,具有时代感,且具有一定的娱乐性和社会实用性。关键词:游戏开发;cocos2d_x引擎;cocos2d_x游戏开发;小鸡对抗游戏TheChickenConfrontationgamedevelopmentThatbasedOnthegameengineofCocos2d-xAbstractThethesisisbasedonthegameengineofCocos2d-x.CombinedwiththetroubleofH7N9,Imadetheleisuregame”TheChickenConfrontationgame”,Thegamerealizetheprocessthatplayersfightagainstthechickenwithvirus,IFplayerwantstowinheneeduseaseriesofpropstodestroythechickenwithH7N9,thegamehasthetimefeelingandhasEntertainmentandSocialutilitytoacertainextent.Keywords:mobilegamesdevelop;thegameengineofCocos2d-x;Cocos2d-xgamedevelop;TheChickenConfrontationGamePAGE湖北科技学院本科毕业设计(论文):基于Cocos2d-x的小鸡对抗游戏开发PAGE湖北科技学院本科毕业论文:用winsock实现FTP客户端PAGE0前言随着科技的发展,成了人们生活中的必需品,每时每刻都可以看到的存在,除了日常的接打,发信息,娱乐也成了不可或缺的功能,相应的,游戏具有开发团队小,开发周期短,成本预算小以及低风险高回报等优点,于是游戏开发[1]近来也越来越火爆,吸引人们从事这一方面的开发。Cocos2d-x[2]是一个开源的、跨平台的、轻量级的2d游戏引擎,它发展的重点是围绕cocos2d跨平台,即其实现一次编码,再各平台分别编译后即可运行,不许为跨平台修改大量代码,不需要在一直方面花费很多时间和人力,目前cocos2d-x引擎已经可以跨以下平台:IOS[3]、Android[4]、Window、Linux[5]、BlackBerry、WindowPhone等平台。其除跨平台外,相对其它的移动游戏引擎还有以下特点:易用性,易于学习掌握的API,大量示例代码和文档;高效性,使用OpenGLES[6];灵活性,易于扩展,易于与其他开源库集成使用;成功商用,根据开源社区的保守统计,基于Cocos2d-x开发的游戏全球范围内已经突破一亿安装量等。因此开发游戏,cocos2d-x是一个很好的选择。近期,由于H7N9[7]的盛行,引发了我想制作出与此有关的游戏,这样不仅可以提高人们的警觉性与关注性,避免病菌肆意的传播,还具有一定的娱乐性,使玩家在娱乐的过程中对H7N9的关注。在利用cocos2d-x引擎制作这款游戏的过程中,主要是进行游戏场景中的制作,导演去控制整个游戏的运作,管理着游戏内的场景,布景,和人物角色有序的运行,在此游戏中的场景有三个,分别为菜单场景、关卡场景和游戏场景,布景测相当于每个场景下的背景,人物角色也就是这个游戏中的小鸡。相关技术支持Cocos2d-x框架层整体来说,cocos2dX提供的一个简便的框架,包含了渲染[8],动画[9],事件分发[10],网络[11]还有UI,物理引擎[12]等几大模块渲染Cocos2d-x的渲染数据跟精灵进行了绑定,然后对于openGl也是直接进行了调用,而不是采用策略或者插件进行调用。对于后期如果采用DX的话,这块比较冗余些。但是这些并不会影响游戏的渲染速度。它提供了batch来进行批次渲染。所以在游戏里,我们对资源进行了分组,然后分别用textPacker拼成一张图片,然后统一采用批次渲染。游戏的速度会提升很多。

对于游戏数据的管理,cocos2d-x采用CCTextureCache这个单例类进行管理。释放可以采用全部释放,还有释放没有用过的。并且也提供了异步加载动画资源的方法,所以对于渲染这块,我们尽量用批次,但是我们要记得释放内存。动画Cocos2d-x提供了一套action机制。整体来说,是spriterunaction。然后驱动action里面的动画数据,进行播放动画。所有的动画都可以走action接口。对于使用者来说,也不用去关心其他东西,只需要初始化好你想要的动作,把动作数据塞给action。让spriterun就可以了。事件分发Cocos2d-x对于事件分发这块就比较弱。他的事件管理是通过存储每一个object以及他接收事件的优先级。然后进行分发。但是他并没有对场景进行树的管理。所以我们就是建立起场景树,然后事件分发先从场景顶端往下分发。期间每个节点可以设置是否响应以及是否继续往下传递的属性,完全丢弃了cocos的那一套事件分发机制。对于场景树的维护,只需要每次step的时候更新下。网络Cocos2d-x提供了对curl的封装。提供了的一些简单比如get,post的封装。但对于断点续传等并没有封装UICocos2d-x提供了几种简单的控件,比如说是CCMenu,CCLabelTTF,CCTableView,CCScrollView,CCImage还有textInput。Cocos2d-x设计模式[13]单例模式Cocos2D-x中的单例如下:CCDirector,CCTextureCache,CCSpriteFrameCache,CCAnimationCache,CUserDefault,CCNotificationCenter,CCShaderCache,CCScriptEngineManager,CCPoolManager,CCFileUtils,CCProfiler,SimleAudioEngie,CCConfiguration,CCApplication,CCDirectorCaller(ios平台),CCEGLView。这里只介绍CCDirector与CCTextureCache单例。首先是CCDirector单例,它负责管理初始化OpenGL渲染窗口以及游戏场景的流程控制,它是cocos2dx游戏开发中必不可少的类之一。为什么要把此类设计成单例对象呢?因为,一个游戏只需要有一个游戏窗口就够了,所以,只需要初始化一次OpenGL渲染窗口。而且场景的流程控制功能,也只需要存在一个这样的场景控制对象即可。为了保证CCDirector类只存在一个实例对象,就必须使用单例模式。接下来是CCTextureCache单例。此类主要负责加载游戏当中所需要的纹理图片资源,这些资源加载好以后,就可以一直保留在内存里面,当下次再需要使用此纹理的时候,直接返回相应的纹理对象引用就可以了,无需再重复加载。当然,这样做可能会很浪费内存,所以cocos2dx采用了一种引用计数的方式来管理对象内存,当纹理刚被加载进来的时候,引用计数为1。如果使用此纹理对象创建一个精灵,那么此纹理对象引用会加1.如果精灵被释放,则相应的引用计数减1.当纹理的引用计数变为0的时候,纹理所占用的内存自然就会被释放掉。这也是为什么在收到内存警告的时候,会调用CCTextureCache的removeUnusedTextures方法。此方法会将所有引用计数为1的纹理对象全部释放掉。单从字面上看,Cache,即缓存的意思。它以牺牲一定的内存压力为代价,带来的是游戏性能的提升。这种cache技术,在游戏开发中比比皆是。注:IO操作对游戏性能影响非常大,要极力避免。二段构建模式构建模式指的是:将一个对象的构建分为两个步骤来进行:分配内存和初始化。在游戏开发中使用此模式的方法为:在使用cocos2d-x的时候,如果你继承CCSprite实现自定义的精灵,你也需要按照“二段构建”的方式,为你的类提供一个静态工厂方法,同时编写相应的初始化方法。当然,命名规范最好和cocos2d-x统一,即静态工厂方法[14]为create,而初始化方法为initXXXX。管理者模式管理者模式指的是:管理者类(cache类)可以简化一些可以重用的资源(比如字体、纹理[15]、精灵帧等)的创建和管理工作。管理者模式其实是个混合模式,它综合了单例模式、外观模式和工厂模式。该模式在游戏开发中比较常见,很多需要提升游戏运行性能的场合都运用了此模式。此模式提供一个统一的接口来管理一组相关对象的实例化和访问。在cocos2dx游戏开发中,经常需要使用CCAnimate动作来播放动画,这些动作的创建运行时开销是比较大的,一般采用的方式都是在node的init方法中创建好,然后retain。之后需要使用的时候直接引用此动作即可,前提是你得声明许多CCAnimate对象的弱引用。这里,我们可以为之创建一个CCAnimateCache类,专门用来管理这些动画动作实例。这样对于游戏中经常变换状态需要更换不同的动画时,可以从此CCAniamteCache类中获取相应动画引用,非常方便,同时可以提高游戏性能。相应的,也可以为Action创建相应的类。但凡那些对象,在运行时创建的时间开销特别大时,而又要经常重复使用时,都可以采取此模式来提高运行时性能。外观模式[16]外观模式指的是:为子系统中的一组接口提供一个一致的界面,它定义了一个高层接口,这个接口使得子系统更加容易使用。它很好地体现了“最少知识原则”。它的本质是:封装交互、简化调用。游戏开发过程中,暂时还没发现此模式的明显用法。不过,模式不是说学习了一定要马上就用到,那样会导致过度设计。如果读者开发游戏过程中,积累出一套比较成熟的框架,而这个框架又可以划分多个子系统,比如碰撞子系统、网络子系统、数据持久化子系统等。当外部使用此子系统时,操作的类过多,理解起来特别复杂时,这时候就可以考虑引入一个Façade类,来简化客户程序与子系统之间的调用关系。防御式编程模式防御式编程模式指的是:子程序应该不因传入错误数据而被破坏,哪怕是由其他子程序产生的错误数据。防御式编程是提高程序代码质量的一种手段,实际上它不能算是真正意义上的模式。我们一般可以采用以下手段来进行防御式编程:1)检查每个子程序的入口参数,记住“垃圾进、垃圾出”这个隐喻。必要的时候可以使用断言来确保函数的先验条件是符合假定的。因为很多时候,我们编写代码都是隐藏了一系列的假定的,只是你自己没有感觉到,有时候,这些假定没有关系,出了bug也容易找出来。但是,有时候,就不是那么幸运了。2)不要直接使用文字常量,比如“Hero.png”这种常量。尽可能地定义const定义常量或者使用宏定义。3)尽可能让函数返回一些东西,这样如果当函数运行出现问题时,可以根据返回值做一些处理。如果全部设计成void类型的函数,那么出现异常要么就是try—catch,要么就是直接让程序崩溃了。由于c++的异常机制[17]并不是那么完善,所以,也一直为人们所诟病,cocos2d-x里面几乎没有使用c++的异常处理机制。最后,必要的时候要检查函数里面调用其它子程序时的返回值。观察者模式观察者模式指的是:对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。在cocos2dx游戏开发中,我们考虑cocos2d-x中一个非常典型的应用场景,你的GameScene里面有两个layer,一个gameLayer,它包含了游戏中的对象,比如玩家、敌人等。另一个层是HudLayer,它包含了游戏中显示分数、生命值等信息。如何让这两个层相互通信。观察者模式是实现MVC模式[18]的重要组成部分,一个model可以对应多个views,model就是目标对象,而view则是观察者,当model改变的时候,要通知所有的view也相应的改变。组合模式组合模式指的是:将对象组合成树形结构以表示“部分整体”的层次结构。组合模式使得用户对单个对象和使用具有一致性。因为游戏开发不是设计框架,基本上使用组合模式的情形不多。但是,如果有递归[19]或者树形结构[20]的对象关系,都可以考虑使用组合模式。中介者模式中介者模式指的是:用一个中介对象来封装一系列的对象交互。中介者使得各对象不需要显式地相互引用,从而使其松散耦合,而且可以独立地改变它们之间的交互。游戏世界里的对象关系非常复杂,如果设计得不好,极容易形成强耦合。而游戏天生又是需要经常更新、修改bug和升级的,这就导致了游戏程序的维护和扩展非常地难。使用中介者模式可以减少游戏世界里面对象之间的多对多关系,使之转变成多对一的关系。关于中介者的实现,可以把AppDelegate类设计成中介者对象,也可以自定义中介者对象,比如GameManager类。把此类设计成单例类,可以方便访问,同时,此类可以拥有像gameScene,levelSaver等类的引用,方便其它对象与这些对象进行交互。中介者模式的实现可以采用单例模式,同时,在处理同事对象之间的交互的时候,可以采用观察者模式。游戏总体分析与设计游戏规则玩法介绍玩家可以通过移动鼠标,拖拽道具到地图上,将道具放在相应的位置上,根据不同的道具有不同的功效,玩家采用不同的道具去捕捉病鸡,但消灭完所有的病鸡,游戏过关,当病鸡的数量到达了15只,或是总鸡数达到了20只,闯关失败。鸡类介绍总共有四种颜色的小鸡,分别为红色,黄色,蓝色,紫色,其中红色和黄色的小鸡为健康的,蓝色和紫色的小鸡为感染H7N9病毒的,而红色和紫色的小鸡为母鸡,黄色和蓝色的小鸡为公鸡。于此同时,还有一些母鸡刚下下来的鸡蛋(白色),以及刚孵化出来的小鸡。捕捉成功率这是根据道具的功能以及拖拽道具到一定位置上病鸡的数量来决定的。道具介绍玩的过程中用户可以使用道具去捕捉小鸡,总共有三种道具,分别是炸弹,骷髅头和药水,炸弹的威力最大,一个炸弹可以涉及到的位置是地图上的9格,也就是以炸弹为中心的九宫格,它可以消灭到这格区域内所有的小鸡,骷髅头是可以消灭它所在地方的一只小鸡,而药水则是可以使得感染上病毒的小鸡恢复健康。游戏关卡关卡场景一共有4个关卡场景,分别是:绿色平原、枫叶树林、寒冬之岭和黄金之路,关卡的难度依次上升,主要体现在病鸡的数量上,病鸡的数量愈多,难度越大。关卡限定首次进入游戏时,只有绿色平原这个关卡场景是可以进入的,其他的均不可进入,只有完成了上一关卡,下一关卡才可以进入,也就是开始我们只是可以看到游戏中总共有的场景,而每个场景的布局是未知的。关卡数组每个关卡场景中,由于是有障碍物的,小鸡们是不可以穿过障碍物,因此为每个关卡场景都定义了一个数组,此数组用来记录每个关卡中是否有障碍物,每个关卡的地图都是由12*16个小格子组成,每个小格子由数组中的相应的元素构成,元素的值为1或是0,1则表示此小格上有障碍物,小鸡们不能在此处行走,只能绕道而行,0代表此处为空闲地带,小鸡们可以自由的行走。游戏总体设计根据进行的游戏规则和游戏关卡分析,我们根据分析结果开始进行总体设计。在设计过程中,我们遵循了软件工程的原理和方法;先采用抽象机制将系统模块化,同时运用面向对象的思想,将模块细化,依此进行开发工作。系统的设计实现及其运作模式都体现了这些原理和方法的应用。游戏设计流程游戏用场景树的形式表现出来,包括有菜单场景、关卡选择场景和游戏场景,这三个场景由导演管理。菜单场景包括有背景精灵、进入关卡菜单项、游戏介绍菜单项、结束游戏菜单项;关卡选择场景包括返回菜单项和滚动图层,儿滚动图层有由背景精灵、挥动序列精灵和进入游戏选项卡构成;游戏场景则有背景精灵、小鸡精灵、返回菜单项、重新开始菜单项构成。其结构如图3.1所示:图3.1游戏设计流程图游戏逻辑流程游戏开始后进入到菜单场景,在菜单场景中玩家可以选择结束游戏、游戏介绍、或是进入到游戏关卡选择中,进入到关卡选择场景后,玩可以根据自己的需要进行关卡的选择,不够这个选择也是有条件的,等级选择完成后,玩家进入到相应的游戏场景中,进入到游戏场景后,四种小鸡在允许移动的地方运动,但公鸡与母鸡走到同一位置,便有一个鸡蛋生成,玩家需要通过移动右边的道具到地图上去消灭染有病毒的鸡。其流程如图3.2所示:菜单场景中主要是menu的选择。游戏开始选择点击按钮当选择游戏介绍按钮时,进入到游戏介绍的页面当选择退出游戏按钮时,为了防止是玩家不小心的动作,从而中间又加入了一个判断,若是选择退出游戏,则结束游戏,若否,则有回到最初的页面当选择进入游戏关卡按钮时,直接进入到游戏选择关卡场景其流程图如图3.3所示:图3.2游戏逻辑流程图图3.3Menu选择流程图关卡选择流程如下:1、进入关卡选择场景2、进行关卡的选择3、若点击绿色平原,则进入到绿色平原游戏场景中,否则可以向右滑动屏幕到枫叶树林关卡4、若玩家之前已通过了绿色平原关卡且点击了枫叶树林关卡,则进入到枫叶树林游戏场景中5、若没有点击枫叶树林关卡,则可以向左滑动屏幕到绿色平原关卡,或者向右滑动屏幕到寒冬之岭关卡6、若玩家之前已通过了枫叶树林关卡且点击了寒冬之岭关卡,则进入到寒冬之岭游戏场景中7、若没有点击寒冬之岭关卡,则可以向左滑动屏幕到枫叶树林关卡,或者向右滑动屏幕到黄金之路关卡8、若玩家之前已通过了寒冬之岭关卡且点击了黄金之路关卡,则进入到黄金之路游戏场景中9、若没有点击黄金之路关卡,则可以向左滑动屏幕到寒冬之岭关卡其流程图如图3.4所示:游戏场景中主要是用定时器来控制小鸡、鸡蛋、道具的产生以及消息和道具的移动。1、新关卡开始2、根据不同的关卡在不同的位置产生不同数量的小鸡3、产生道具4、每隔一定的时间改变小鸡的位置(小鸡不允许在障碍物上行走)5、移动道具时,实时的控制道具的移动位置6、每隔一定的时间同种已用的道具再次出现其流程图如图3.5所示:玩家捕鸡流程如下:1、玩家在相应的道具上点击,拖动道具到地图上2、若道具是火,则在以拖动到的位置为中心的九宫格的地方进行爆破,爆破的地方所有的小鸡和激动都会死亡,小鸡死亡的同时,此道具也会消失3、若道具是骷髅头,则在道具拖动的位置上的小鸡或是小鸡移动到此处的小鸡将会死亡,小鸡死亡的同时,此道具也会消失4、若道具是药剂,则在道具拖动的位置上的感染上病毒的小鸡将会痊愈5、当总共小鸡和鸡蛋的数量达到了20只或是感染上病菌的小鸡和鸡蛋的数量达到了15只,游戏将会结束,显示为闯关失败6、当地图上的小鸡和鸡蛋全为健康的时候,游戏结束,显示为过关,同时下一关卡将被开启其流程图如图3.6所示:图3.4关卡选择流程图图3.5定时器控制小鸡及道具图图3.6玩家捕鸡流程图游戏详细设计和实现菜单场景的实现菜单场景的主要作用是供玩家的选择,菜单场景中提供了游戏介绍、退出游戏、进入游戏关卡三个菜单项。结构图如图4.1所示:图4.1菜单场景结构图场景中采用的是单例模式,直接由一个静态的函数去创建一个场景,再将自己所定义的层加入到场景的孩子节点中,这里所用到的是cocos2d-x节点管理,cocos2d-x使用节点组成一棵树,渲染的时候要遍历这棵树。实现代码如下:CCScene*scene=CCScene::create();GameStart*layer=newGameStart(); layer->init(); scene->addChild(layer); layer->release(); returnscene;初始化的界面1、背景精灵的创建,所使用的是一张名为的图片区创建的,实现代码如下:CCSprite*b_Sprite=CCSprite::create("StartBackground.jpg"); b_Sprite->setPosition(ccp(WIDTH/2,HEIGHT/2)); this->addChild(b_Sprite,0); 2、三个菜单项的创建,实现代码如下:CCMenuItemImage*pCloseItem=CCMenuItemImage::create( "back.png","back2.png",this,menu_selector(GameStart::menuCloseCallback)); pCloseItem->setPosition(ccp(WIDTH-50,50)); CCMenuItemImage*sItem=CCMenuItemImage::create( "Start.png","Start.png",this,menu_selector(GameStart::get_start)); sItem->setPosition(ccp(WIDTH/2,HEIGHT-40)); CCMenuItemImage*rItem=CCMenuItemImage::create( "help.png","help.png",this,menu_selector(GameStart::get_instruction)); rItem->setPosition(ccp(50,50));3、创建菜单,将上述的三个菜单项加入其中,进行统一的管理,实现代码如下: CCMenu*rMenu=CCMenu::create(rItem,NULL); rMenu->setPosition(CCPointZero); this->addChildpCloseItem(pCloseItem,sItem,rMenu,1); …菜单场景的效果图如图4.2所示:图4.2菜单场景效果图按钮回调1、游戏介绍的回调函数,首先将此层中所有的孩子节点删除掉,再重新构造此层的孩子节点,主要包括了一个背景精灵一个一个返回上一层的按钮鸡菜单,实现代码如下: removeAllChildren(); CCSprite*b_Sprite=CCSprite::create("InstructionBackground.png"); b_Sprite->setPosition(ccp(WIDTH/2,HEIGHT/2)); this->addChild(b_Sprite,0); CCMenuItemImage*rItem=CCMenuItemImage::create( "back2.png","back1.png",this,menu_selector(GameStart::get_restart)); rItem->setPosition(ccp(WIDTH-50,50)); CCMenu*rMenu=CCMenu::create(rItem,NULL); rMenu->setPosition(CCPointZero); this->addChild(rMenu,1); 此返回按钮的回调函数的实现体就是将刚创建的孩子节点全部清除,再重新的初始化界面 this->removeAllChildren(); init();游戏介绍的效果图如图4.3所示:图4.3游戏介绍效果图2、退出游戏的回调函数,首先将初始化退出游戏的界面,实现代码如下: 背景精灵的创建: b_Sprite=CCSprite::create("opsity.png"); b_Sprite->setPosition(ccp(WIDTH/2,HEIGHT/2)); b_Sprite->setOpacity(150); this->addChild(b_Sprite); b_SpriteBg1=CCSprite::create("exitbg1.png"); b_SpriteBg1->setPosition(ccp(WIDTH/2,HEIGHT/2)); b_SpriteBg1->setOpacity(100); this->addChild(b_SpriteBg1); b_SpriteBg2=CCSprite::create("exitbg2.png"); b_SpriteBg2->setPosition(ccp(WIDTH/2,HEIGHT/2)); this->addChild(b_SpriteBg2); b_SpriteBg3=CCSprite::create("exitbg3.png"); b_SpriteBg3->setPosition(ccp(WIDTH/2,HEIGHT/2)); this->addChild(b_SpriteBg3); 确定退出游戏菜单项的创建: CCMenuItemImage*pYesItem=CCMenuItemImage::create( "Yes.png","Yes.png",this,menu_selector(GameStart::menuYesCallback)); pYesItem->setPosition(ccp(WIDTH/2-100,HEIGHT/2-100)); 取消退出游戏菜单项的创建: CCMenuItemImage*pNoItem=CCMenuItemImage::create( "No.png","No.png",this,menu_selector(GameStart::menuNoCallback)); pNoItem->setPosition(ccp(WIDTH/2+100,HEIGHT/2-100)); pMenu=CCMenu::create(pYesItem,pNoItem,NULL); pMenu->setPosition(CCPointZero); this->addChild(pMenu); 而最终的退出游戏的实现代码则是: CCDirector::sharedDirector()->end();退出游戏的效果图如图4.4所示:图4.4退出游戏效果图3、关卡选择按钮的实现则是进行场景的切换,使得有菜单场景切换到关卡选择场景,实现代码如下: CCDirector::sharedDirector()->setDepthTest(true); CCDirector::sharedDirector()->replaceScene(CCTransitionProgressInOut::create(0.5,GameChoose::scene()));关卡选择场景的实现在关卡场景中主要是关卡的选择,关卡包括有:绿色平原、枫叶树林、寒冬之岭、黄金之路,闯关的等级是用xml文件来记录的,每次进入到关卡选择场景时都需要读取xml文件中的内容,因为根据闯关的等级的不同,能进入到的游戏场景也是不同的,只有当上一等级通过了,下一等级的关卡才会被打开。当玩家滑动屏幕时,将会浏览到不同的关卡菜单,点击不同的菜单精灵,处理不同的事件。由于本场景中用到了滑动列表,因此,需创建一个CCScrollView的对象,4个关卡精灵,4个点精灵,一个返回按钮等。实现代码如下:将此层设置为可触屏的层,通过重写底层的4个虚函数实现。virtualvoidregisterWithTouchDispatcher();virtualboolccTouchBegan(CCTouch*touch,CCEvent*event);virtualvoidccTouchMoved(CCTouch*touch,CCEvent*event);virtualvoidccTouchEnded(CCTouch*touch,CCEvent*event);将此层设置为滑动列表的层,通过重写底层的2个虚函数实现。voidscrollViewDidScroll(CCScrollView*view);voidscrollViewDidZoom(CCScrollView*view);初始化此层时,需要进行读取档案(m_curGameLevel变量指的是所闯关的等级,初始值为1)。CCUserDefault*pUserDefault=CCUserDefault::sharedUserDefault();m_curGameLevel=pUserDefault->getIntegerForKey("curGameLevel",m_curGameLevel);添加一个CCScroView(其中创建了一个CCLayer层,用来存放CCScroView的容器;4个关卡菜单精灵;设置了CCScroView的显示域的范围,范围为800*480,总的大小800*4*480*4,既有4个这样的大小)CCLayer*pLayer=CCLayer::create();charhelpstr[30]={0};有四个关卡,因此有四个循环体,主要是用来创建关卡场景的背景的 for(inti=1;i<=4;++i) {CCSprite*m_pBGSprite=CCSprite::create("bg1.png"); m_pBGSprite->setPosition(ccp(visibleSize.width*(i-0.5f),visibleSize.height/2)); pLayer->addChild(m_pBGSprite); sprintf(helpstr,"screenBg%d.png",i); CCSprite*pSpritebg=CCSprite::create(helpstr); pSpritebg->setPosition(ccp(visibleSize.width*(i-0.5f),90)); pLayer->addChild(pSpritebg); sprintf(helpstr,"level%d.png",i); CCSprite*pSprite=CCSprite::create(helpstr); pSprite->setPosition(ccp(visibleSize.width*(i-0.5f),visibleSize.height/2)); pLayer->addChild(pSprite);根据玩家所闯的等级数来确定关卡上是否加锁,加了锁的关卡表示玩家无法进入到此关卡所对应的游戏场景中 if(m_curGameLevel<i) { CCSprite*pSprite=CCSprite::create("suo.png"); pSprite->setPosition(ccp(visibleSize.width*(i-0.5f),visibleSize.height/2)); pSprite->setOpacity(200); pLayer->addChild(pSprite); } } m_pScrollView=CCScrollView::create(CCSizeMake(800,480),pLayer); m_pScrollView->setTouchEnabled(false); m_pScrollView->setDelegate(this); m_pScrollView->setDirection(kCCScrollViewDirectionHorizontal); pLayer->setContentSize(CCSizeMake(800*4,480)); this->addChild(m_pScrollView);}四个点精灵的创建,为了节省加载资源的时间,组成游戏的图片不是单独的,而是将几张图片合成一张大的图片加载进来,当需要用到那些单独的图片时,用plist文件将其中的小图片分割出来或者直接利用CCRectMake对图片进行切割。创建一个缓存精灵的实例,用来缓存后面的图片CCSpriteFrameCache*pCache=CCSpriteFrameCache::sharedSpriteFrameCache();缓存四个点精灵pCache->addSpriteFrame(CCSpriteFrame::create("dotnumber.png",CCRectMake(0,0,21,21)),"button_normal.png");pCache->addSpriteFrame(CCSpriteFrame::create("dotnumber.png",CCRectMake(21,0,21,21)),"button_selected1.png");pCache->addSpriteFrame(CCSpriteFrame::create("dotnumber.png",CCRectMake(21*2,0,21,21)),"button_selected2.png");pCache->addSpriteFrame(CCSpriteFrame::create("dotnumber.png",CCRectMake(21*3,0,21,21)),"button_selected3.png");pCache->addSpriteFrame(CCSpriteFrame::create("dotnumber.png",CCRectMake(21*4,0,21,21)),"button_selected4.png"); 四个点精灵的创建 for(inti=1;i<=4;++i) { CCSprite*pPoint=CCSprite::createWithSpriteFrameName("button_normal.png"); pPoint->setTag(i);pPoint->setPosition(ccp(origin.x+(visibleSize.width-4*pPoint->getContentSize().width)/2+pPoint->getContentSize().width*(i-1),origin.y+30)); this->addChild(pPoint); }CCSprite*pPoint=(CCSprite*)this->getChildByTag(1); pPoint->setDisplayFrame(pCache->spriteFrameByName("button_selected1.png"));根据玩家滑动的距离来确定执行的程序当滑动的距离大于10时,也就是滑动页面的时候pPoint->setDisplayFrame(pCache->spriteFrameByName("button_normal.png")); if(offset<0) m_nCurPage++; else m_nCur;当当前页数小于1和大于4的时候应该做相应的处理,因为当前的页数的值只能在1到4这个范围内 if(m_nCurPage<1) m_nCurPage=1; if(m_nCurPage>4) m_nCurPage=4; else { 根据当前的页数去确定不同的点精灵 pPoint=(CCSprite*)this->getChildByTag(m_nCurPage); if(m_nCurPage==1) pPoint->setDisplayFrame(pCache->spriteFrameByName("button_selected1.png")); elseif(m_nCurPage==2) pPoint->setDisplayFrame(pCache->spriteFrameByName("button_selected2.png")); elseif(m_nCurPage==3) pPoint->setDisplayFrame(pCache->spriteFrameByName("button_selected3.png")); elseif(m_nCurPage==4) pPoint->setDisplayFrame(pCache->spriteFrameByName("button_selected4.png")); 实现页面滑动时候的效果 CCPointadjustPos=ccp(origin.x-visibleSize.width*(m_nCur1),0); m_pScrollView->setContentOffset(adjustPos,true); }当滑动的距离小于10时,也就是点击当前以页面的时候,当当前页面小于或是等于所闯关的等级的时候,进行场景的切换,或者不进行处理if(m_nCurPage==1&&m_curGameLevel>=m_nCurPage) { CCDirector::sharedDirector()->setDepthTest(true); CCDirector::sharedDirector()->replaceScene(CCTransitionProgressInOut::create(0.5,GameScene::scene(1))); } elseif(m_nCurPage==2&&m_curGameLevel>=m_nCurPage) { CCDirector::sharedDirector()->setDepthTest(true); CCDirector::sharedDirector()->replaceScene(CCTransitionProgressInOut::create(0.5,GameScene::scene(2))); } elseif(m_nCurPage==3&&m_curGameLevel>=m_nCurPage) { CCDirector::sharedDirector()->setDepthTest(true); CCDirector::sharedDirector()->replaceScene(CCTransitionProgressInOut::create(0.5,GameScene::scene(3))); } elseif(m_nCurPage==4&&m_curGameLevel>=m_nCurPage) { CCDirector::sharedDirector()->setDepthTest(true); CCDirector::sharedDirector()->replaceScene(CCTransitionProgressInOut::create(0.5,GameScene::scene(4))); }当点击返回按钮时,进行场景的切换,又返回到菜单场景中CCDirector::sharedDirector()->setDepthTest(true);CCDirector::sharedDirector()->replaceScene(CCTransitionProgressInOut::create(0.5,GameStart::scene()));当此场景的生命周期介绍前,完成内存的回收以及进行存档CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);CCLayer::onExit();CCSpriteFrameCache::sharedSpriteFrameCache()->removeUnusedSpriteFrames();CCUserDefault*pUserDefault=CCUserDefault::sharedUserDefault();pUserDefault->setIntegerForKey("curGameLevel",m_curGameLevel);关卡选择场景的效果图如图4.5所示:图4.5选择关卡场景效果图游戏场景的实现游戏场景是游戏中主要的模块。在这个场景中,为了更好的去管理场景下的一些元素,自定义了些类,包括了World(地图)、Number(生命值)、ChickenManager(小鸡管理器)、PropManager(道具管理器)结构图如图4.6所示:图4.6游戏场景结构图World(地图)地图也就是小鸡行走的位置,地图上有障碍物和空地,障碍物和空地的值是由1和0来表示的,游戏中有四个关卡,对应4个地图,每张地图都对应着一个16*12的二维数组,数组记录的是地图的行走的信息。声明数组:staticintrocks[WIDTHNUM][HEIGHTNUM];地图转化为数组的实现代码:if(num==2) { inta[12][16]= { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,0,0,1,0,1,0,1,0,1,0,0,0,1,0, 0,1,0,0,0,0,1,0,0,1,0,1,0,0,0,0, 0,1,0,1,1,1,1,1,1,1,1,1,1,0,1,1, 0,1,0,1,0,0,0,1,1,0,0,0,1,0,0,0, 0,1,0,0,0,1,0,1,1,0,0,0,0,0,1,0, 0,1,0,0,0,0,0,1,1,0,1,0,0,0,1,0, 0,0,0,1,0,0,0,1,1,0,0,0,1,0,1,0, 1,1,0,1,1,1,1,1,1,1,1,1,1,0,1,0, 0,0,0,0,1,0,1,0,0,1,0,0,0,0,1,0, 0,1,0,0,0,1,0,1,0,1,0,1,0,0,1,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, }; for(inti=0;i<16;i++) for(intj=0;j<12;j++) rocks[i][j]=a[11-j][i]; }Number(生命值)生命值记录的是游戏过程中鸡的数量的改变,生命值由两个值组成,一个是病鸡的数量,一个是健康鸡的数量,下面的是病鸡的血条,上面的则是建康鸡的血条,当病鸡的血条满时或是病鸡的血条加上健康鸡的血条占满了生命值的整个空间是,游戏结束,闯关失败,当病鸡的血条为0时,游戏结束,闯关成功。实现代码如下:if(ill_num>15||ill_num+health_num>20) returnfalse; inti; for(i=0;i<ill_num;i++) { CCSprite*m_sprite=CCSprite::create("ill_num.png"); m_sprite->setPosition(ccp(NUMLOC,79+20*i)); addChild(m_sprite); } for(;i<ill_num+health_num;i++) { CCSprite*m_sprite=CCSprite::create("health_num.png"); m_sprite->setPosition(ccp(NUMLOC,79+20*i)); addChild(m_sprite); }returntrue;ChickenManager(小鸡管理器)小鸡管理器中管理着病鸡、建康鸡、病蛋、健康蛋。结构图如图4.7所示:图4.7小鸡管理器结构图容器的声明:vector<IllChicken*> ills; vector<HealthChicken*> healths; vector<Egg*> eggs; vector<HealthEgg*> health_eggs; vector<IllEgg*> ill_eggs; vector<CCPoint*> temp_loc; vector<int> temp_type; vector<CCSprite*> fires;小鸡的产生,其中的变量type为小鸡的类型,0代表的是感染上病毒的小鸡,1代表的是健康的小鸡。inits函数的参数的含义依次为:产生鸡的位置、方向、性别。实现代码如下:if(type==0) { IllChicken*i=newIllChicken(); i->inits(a,d,s); ills.push_back(i); addChild(i,3); } elseif(type==1) { HealthChicken*h=newHealthChicken(); h->inits(a,d,s); healths.push_back(h); addChild(h,3); }小鸡的创建,sex指的是性别,0代表的是公鸡,1代表的是母鸡,dir指的是方向,0代表的是向上,1代表的是向左,2代表的是向下,3代表的是向右。这里是根据不同的性别不同的方向由不同的图片在不同的位置上创建小鸡精灵。实现代码如下:if(sex==0) { if(dir==0) p_sprite=CCSprite::create("illmaleup.png"); elseif(dir==1) p_sprite=CCSprite::create("illmaleleft.png"); elseif(dir==2) p_sprite=CCSprite::create("illmaledown.png"); elseif(dir==3) p_sprite=CCSprite::create("illmaleright.png"); } elseif(sex==1) { if(dir==0) p_sprite=CCSprite::create("illfemaleup.png"); elseif(dir==1) p_sprite=CCSprite::create("illfemaleleft.png"); elseif(dir==2) p_sprite=CCSprite::create("illfemaledown.png"); elseif(dir==3) p_sprite=CCSprite::create("illfemaleright.png"); } p_sprite->setPosition(ccp((loc->x+0.5)*BOXSIDE,(loc->y+0.5)*BOXSIDE)); addChild(p_sprite,3);鸡蛋的产生,其中的变量temp_loc为一个CCPoint类型的容器,inits为蛋的创建函数,主要是蛋精灵的创建,以及添加到父节点中,第一个参数为鸡蛋所在的位置,第二个为鸡蛋的类型,0代表的是由病菌的蛋,1是健康的蛋。实现代码如下:for(inti=0;i<temp_loc.size();i++) { Egg*egg=newEgg(); egg->inits(temp_loc[i],temp_type[i]); eggs.push_back(egg); addChild(egg,1); } temp_type.clear(); temp_loc.clear();当两只小鸡走到同一位置时,总共有四种情况,分别是:病鸡与病鸡相撞、病鸡与健康鸡相撞、健康鸡与病鸡相撞、健康鸡与健康鸡相撞,这里只列出了一种情况,病鸡与病鸡相撞,其他的情况类似,只是产生的鸡蛋的类型不一样,病鸡与病鸡相撞孵化出来的是病鸡,健康鸡与健康鸡相撞孵化出来的是健康鸡,而其他两种则是随机的,可能是病鸡也可能是健康的鸡,而孵化出来的鸡的性别是随机的,代表的是小鸡停留的时间,母鸡停留的时间会是公鸡停留的时间的3倍。代码的实现如下:for(intk=0;k<ills.size();k++){if(k!=i&&ills[i]->sex!=ills[k]->sex&&ills[i]->loc->x==ills[k]->loc->x&&ills[i]->loc->y==ills[k]->loc->y) { if(ills[i]->sex==1) { ills[i]->delay=3; ills[k]->delay=1; } else { ills[i]->delay=1; ills[k]->delay=3; } creat_egg(ills[i]->loc,0); }}当小鸡与道具相撞时,根据小鸡的类型与道具的类型,会有不同的动作。这里只举了病鸡与道具骷髅头和道具药剂相撞的例子,type为0指的是道具为药剂,type为1指的是道具为骷髅头,其中get_healthy函数是将病鸡治愈为健康的鸡,这些主要是对容器的操作,后面再根据容器的大小,值进行不同的显示。实现代码如下:for(intj=0;j<ills.size();j++){ for(inti=0;i<sp.size();i++) if(sp[i]->loc->x==ills[j]->loc->x&&sp[i]->loc->y==ills[j]->loc->y) { if(sp[i]->type==0) { get_healthy(j); sp[i]->remove_sprite(); sp.erase(sp.begin()+i); break; } elseif(sp[i]->type==1) { this->removeChild(ills[j]); ills.erase(ills.begin()+j); sp[i]->remove_sprite(); sp.erase(sp.begin()+i); break; } }}判断地图上的点是否可走,有蛋的地方不能行走,地图上有障碍物的地方不能行走,w->get_on_location(x,y)。得到的是地图上在点(x,y)点处的值,这个值只为0或是1,1为不可走。WIDTHNUM、HEIGHTNUM分别代表的是地图的宽度和高度实现代码为:if(x>=WIDTHNUM||x<0||y>=HEIGHTNUM||y<0) returnfalse; if(w->get_on_location(x,y)!=1) { for(inti=0;i<eggs.size();i++) if(eggs[i]->loc->x==x&&eggs[i]->loc->y==y) returnfalse; for(inti=0;i<ill_eggs.size();i++) if(ill_eggs[i]->loc->x==x&&ill_eggs[i]->loc->y==y) returnfalse; for(inti=0;i<health_eggs.size();i++) if(health_eggs[i]->loc->x==x&&health_eggs[i]->loc->y==y) returnfalse; returntrue; } else returnfalse;得到鸡所能走的方向,并随机的让小鸡向可以行走的方向行走,locx、locy、locx1、locy1、locx2、locy2分别为径直方向上的横纵坐标,左边的横纵坐标,右边的横纵坐标,is_available(locx,locy,w)就是上面所说的判断鸡所能走的点。实现代码为:locx=i->get_straight_loc().x;locy=i->get_straight_loc().y; locx1=i->get_left_loc().x;locy1=i->get_left_loc().y; locx2=i->get_right_loc().x;locy2=i->get_right_loc().y; 当3个方向都可以行走时,随机的选择一个方向 if(is_available(locx,locy,w)+is_available(locx1,locy1,w)+is_available(locx2,locy2,w)==3) { intnum=rand(); if(num%3==0) i->turn_left(); elseif(num%3==1) i->turn_right(); } 当只有两个方向可以行走时,随机选择一个方向行走 elseif(is_available(locx,locy,w)+is_available(locx1,locy1,w)+is_available(locx2,locy2,w)==2) { 径直方向不能行走时,随机选择向左或是向右行走 if(is_available(locx,locy,w)==false) { if(rand()%2==0) i->turn_left(); else i->turn_right(); } 向左方向不能行走时,随机选择向右或是向前行走 elseif(is_available(locx1,locy1,w)==false) { if(rand()%2==1) i->turn_right(); }向右方向不能行走时,随机选择向左或是向前行走 else { if(rand()%2==1) i->turn_left(); } } elseif(is_available(locx,locy,w)+is_available(locx1,locy1,w)+is_available(locx2,locy2,w)==1) { if(is_available(locx1,locy1,w)==true) i->turn_left(); elseif(is_available(locx2,locy2,w)==true) i->turn_right(); }Number(道具管理器)道具管理器重管理中骷髅头、火、药剂。结构图如图4.8所示:图4.8游戏场景结构图三种道具的实现方法类似,在这里只讨论药剂的。由于是将道具设置为可触碰的,故应重载下面的3种方法,同时在初始化时,将是否可点击设置为true,setTouchEnabled(true) virtualboolccTouchBegan(cocos2d::CCTouch*pTouch,cocos2d::CCEvent*pEvent); virtualvoidccTouchMoved(cocos2d::CCTouch*pTouch,cocos2d::CCEvent*pEvent); virtualvoidccTouchEnded(cocos2d::CCTouch*pT

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论