




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
-.z.学院课程设计课程:智能手机软件开发技术题目:基于安卓的植物大战僵尸学院:信息与电子工程学院专业班级:12软件工程1班学生**:4学生:梁庆目录一、安卓手游概述手机游戏,就是指在手机上运行的游戏软件。目前用来编写安卓手机程序使用最多的是Java语言。随着科技的快速开展,目前手机的硬件更新速度越来越快,功能也越来越强大。而现在的手机游戏也不是诺基亚时代风行全球的那些依托于掌上游戏机的"俄罗斯方块〞、"贪吃蛇〞等画面简陋,规则简单的游戏,进而开展到了可以和掌上游戏机媲美,具有很强的娱乐性和交互性的复杂形态。作为运行在手持移动终端设备上的应用程序,手机的硬件特征决定了手机游戏的特点:首先是其庞大的潜在用户群,据最新调查统计,2015年底全球使用智能手机的人口即将到达25亿,超过全球人口的三分之一,而且这个数字每天都在不断增加,另外,Android市场份额占84.7%。在除美国之外的各个兴旺国家,手机用户都比计算机用户多。手机游戏潜在的市场比其他任何平台都要大。其次是其便携性,在控制台游戏时代,掌上游戏机热销的一个原因就是便携性——人们可以随时随地沉浸在自己喜欢的游戏中。和游戏控制台或者PC相比,手机虽然可能不是一个专业的游戏设备,但毕竟人们总是随时随身携带,这样手机游戏很可能成为人们消遣时间的首选。更重要的是其支持网络,由于手机是网络设备,在一定限制因素下可以实现多人在线游戏。为什么要开发Android版本的游戏。一是源于其技术优势:一方面是其稳定性,现在已有公认最稳定版本Android5.0操作系统Lollipop〔棒棒糖〕。另一方面是程序员技术入门快,对有一定Java语言根底的人来说,学习和掌握Android开发技术非常快。二是源于Android手机操作系统的市场优势:自Google在2008年9月正式发布Android1.0系统以来,Android系统在短短的3年时间就占据全球智能机市场48%的份额,如今已经增长至84.7%,远远超过IOS,稳坐全球第一。更需要特别说明的一点:开发周期短,是一个很大的优势。熟悉手机游戏市场的人都知道,手机游戏形式更新换代的周期很短,如果一旦错过了最正确发布时间,即使开发出来的产品再好,也只能成为废品。二、开发工具的介绍开发此款游戏主要使用到的工具有四种:Eclipse,是一个开放源代码的、基于Java的可扩展开发平台;ADT,是Eclipse平台下用来开发Android应用程序的插件;AndroidSDK,是Android专属的软件开发工具包;Fireworks,是Adobe推出的一款图形编辑软件。2.1EclipseEclipse是著名的跨平台的自由集成开发环境〔IDE〕。其本身只是一个框架平台,但是众多插件的支持使得Eclipse拥有其他功能相对固定的IDE软件很难具有的灵活性。许多软件开发商以Eclipse为框架开发自己的IDE,因此得到了众多组织定力支持。2.2ADT这是Eclipse插件,作用是关联AndroidSDK,使Eclipse能够新建Android工程。2.3AndroidSDKAndroidSDK全称为AndroidSoftwareDevelopmentKit,它提供了在Windows/Linu*/Mac平台上开发Android应用的开发组件。包含了在Android平台上开发移动应用程序的各种工具集,主要是由以下5个局部组成:Andriod模拟器〔AVD
Manager.e*e〕:运行在计算机上的虚拟移动模拟器,可以使用模拟器来在一个实际的Android运行环境下设计,调试和测试应用程序。调试监视效劳〔ddms.bat〕:它集成在Dalvik(Android平台虚拟机)中,用于管理运行在模拟器或设备上的进程,并协助进展调试。可以用它来去除进程,选择一个特定程序来调试,生成跟踪数据,查看堆和线程数据,对模拟器或设备进展屏幕快照等。Android调试〔adb.e*e〕:它用于向模拟器或手机设备安装应用程序的apk文件和从命令行访问模拟器或手机设备.也可以用于将标准的调试器连接到运行在android模拟器或手设备上的应用代码。SQLite3数据库(sqlit3(sqlite3.e*e)):Android应用程序可以创立和使用SQLite数据文件,开发者和使用者也可以方便的访问这些数据文件创立SD卡工具(mksdcard(mksdcard.e*e))
2.4FireworksFireworks是Macromedia公司发布的一款专为网络图形设计的图形编辑软件,它大大简化了网络图形设计的工作难度,无论是专业设计家还是业余爱好者,使用Fireworks都不仅可以轻松地制作出十分动感的GIF动画,还可以轻易地完成大图切割、动态按钮、动态翻转图等。三、技术介绍该设计主要使用了SurfaceView游戏框架,采用双缓存技术防止屏幕出现闪烁。3.1SurfaceViewSurfaceView可以直接从存或者DMA等硬件接口取得图像数据,是个非常重要的绘图容器。它的特性是:可以在主线程之外的线程中向屏幕绘图上。这样可以防止画图任务繁重的时候造成主线程阻塞,从而提高了程序的反响速度。在游戏开发中多用到SurfaceView,游戏中的背景、人物、动画等等尽量在画布Canvas中画出。3.2双缓存窗体在刷新时,总要有一个擦除原来图象的过程,它利用背风光填充窗体绘图区,然后再调用新的绘图代码进展重绘,这样一擦一写造成了图象颜色的反差,造成闪烁。闪烁是图形编程的一个常见问题。需要多重复杂绘制操作的图形操作会导致呈现的图像闪烁或具有其他不可承受的外观。当数据量很大时,绘图可能需要几秒钟甚至更长的时间,闪烁现象会更加严重,为了解决这些问题,可采用双缓冲技术来绘图。3.3Cocos2d-android游戏引擎cocos2d是一个基于MIT协议的开源框架,用于构建游戏、应用程序和其他图形界面交互应用。可以让你在创立自己的多平台游戏时节省很多的时间。Cocos2D也拥有几个主要版本,包括Cocos2D-iPhone、Cocos2D-*,以及被社区普遍看好的Cocos2D-HTML5和JavaScriptbindingsforCocos2D-*。同时也拥有了非常优秀的编辑器〔独立编辑器〕,例如SpriteSheetEditors、ParticleEditors、FontEditors、TilemapEditors。另外,2012年发布的CocoStudio工具集是开源游戏引擎Cocos2d-*开发团队官方推出的游戏开发工具,目前已经进入稳定版。CocoStudio吸取了他们自己在游戏制作中的经历,为移动游戏开发者和团队量身定做,旨在降低游戏开发的门槛,提高开发效率,同时也为Cocos2D-*的进一步开展打下根底。四、系统功能系统主要有以下几个功能4.1工程概述本工程分为五个主要局部:常规、夜晚、无尽三个模式进展游戏,和游戏设置与查看帮助。用例图如图2.1。图2.1系统用例图4.2工程概述4.2.1常规模式此局部主要实现玩家在游戏背景为白天的情况下玩游戏。该局部具体情况如表2.1。表2.1常规模式用例名称常规模式功能简述在常规模式下进展游戏前置条件玩家进入游戏后置条件进入常规模式开场游戏根本流点击主菜单页面"常规模式〞按钮,进入常规模式开场游戏点击"返回〞按钮,用例终止4.2.2夜晚模式此局部主要实现玩家在游戏背景为夜晚的情况下玩游戏。该局部具体情况如表2.2。表2.2夜晚模式用例名称夜晚模式功能简述在夜晚模式下进展游戏前置条件玩家进入游戏后置条件进入夜晚模式开场游戏根本流点击主菜单页面"夜晚模式〞按钮,进入夜晚模式开场游戏点击"菜单〞按钮游戏暂停并进入主菜单点击"夜晚模式〞回到游戏点击"返回〞按钮,用例终止4.2.3无尽模式此局部主要实现游戏玩家在常规或者夜晚模式通关的情况下玩游戏。该局部具体情况如表2.3。表2.3无尽模式用例名称无尽模式功能简述在无尽模式下进展游戏前置条件玩家在常规或者夜晚模式通关后置条件进入常规模式开场游戏根本流点击主菜单页面"无尽模式〞按钮,进入无尽模式开场游戏点击"菜单〞按钮游戏暂停并进入主菜单点击"无尽模式〞回到游戏点击"返回〞按钮,用例终止4.2.4游戏设置此局部主要实现对游戏背景音乐、效果音的开启和关闭。该局部具体情况如表2.4。表2.4无尽模式用例名称游戏设置功能简述翻开、关闭游戏背景音乐或者效果音前置条件想要对游戏进展设置后置条件游戏属性改变根本流点击主菜单页面"选项〞按钮,进入"游戏设置〞界面在游戏设置界面中,根据需要进展设置设置之后自动返回主菜单或者不设置点击"返回〞按钮,用例终止4.2.5关卡选择此局部主要实现玩家根据自己喜好选择在哪个游戏关卡下玩游戏。但是不能选择没有通过的关卡。4.2.6查看帮助此局部主要实现游戏玩家查看帮助。五、概要设计5.1游戏设计5.1.1游戏背景人类与僵尸之间的仇恨由来已久,为了争夺生存空间,僵尸一有时机就向人类发起攻击。但是人类也不会束手就擒,他们培养出了可以对僵尸造成伤害的植物,当僵尸进攻时这些植物就是人类保卫家园的武器。5.1.2游戏逻辑〔1〕僵尸是进攻方,人类通过种植培育出的各种进攻,防御型植物来抵抗僵尸的进攻。想要植物成长来攻击,防御僵尸需要相应的值。〔2〕不同的关卡中,供选择的植物不同,僵尸进攻的单位也不同。例如第一关只有普通僵尸进攻,第二关就会出现两种僵尸。〔3〕在交战区,玩家要种植进攻,防御单位是需要植物的,所以还需要种植产生的生产单位。〔4〕每关都有相应的敌人数量,全部消灭之后过关。如果有敌人穿过交战区域到达人类前方,则判定游戏失败。5.1.3僵尸作战单位〔1〕普通僵尸。移动速度1p*/帧,生命值3,吃掉植物需要3s。〔2〕戴帽子僵尸。移动速度1p*/帧,生命值4,吃掉植物需要3s。〔3〕戴铁桶僵尸。移动速度1p*/帧,生命值5,吃掉植物需要3s。〔4〕运发动僵尸。移动速度2p*/帧,生命值3,吃掉植物需要3s。〔5〕佩戴铁网僵尸。移动速度1p*/帧,生命值6,吃掉植物需要3s。5.1.4植物作战单位〔1〕向日葵。消耗值50,能够生产,每10s生产的值为50,没有攻击力。〔2〕普通豌豆射手。消耗值100,每5s发射一颗子弹,攻击力为1。〔3〕冰冻豌豆射手。消耗值175,每5s发射一颗子弹,攻击力为1。〔4〕加强型豌豆射手。消耗值200,每5s发射两颗连续的子弹,每颗子弹攻击力为1。〔5〕土豆卫士。消耗值50,可以抵挡僵尸3s,为其他攻击植物争取时间。5.1.5每关进攻的僵尸及可以种植的植物说明第一关,进攻的僵尸有普通僵尸,可以选择种植向日葵,普通豌豆射手。第二关,进攻的僵尸有普通僵尸,戴帽子僵尸,可以选择种植向日葵,普通豌豆射手,冰冻豌豆射手。第三关,进攻的僵尸有普通僵尸,戴帽子僵尸,戴铁桶僵尸,可以选择种植向日葵,普通豌豆射手,冰冻豌豆射手,加强型豌豆射手。第四关,进攻的僵尸有普通僵尸,戴帽子僵尸,戴铁桶僵尸,运发动僵尸,可以选择种植向日葵,普通豌豆射手,冰冻豌豆射手,加强型豌豆射手,土豆卫士。第五关,进攻的僵尸有普通僵尸,戴帽子僵尸,戴铁桶僵尸,运发动僵尸,佩戴铁网僵尸,可以选择种植向日葵,普通豌豆射手,冰冻豌豆射手,加强型豌豆射手,土豆卫士。5.1.6关卡说明总共有五条防御路线。每条防御路线最多可以放九个单位。僵尸在屏幕之外生成,随机出现在五条路线中的一条,之后缓缓向人类前方前进。每关都有相应的僵尸数量,全部消灭之后就过关。如果敌人穿过交战区域到达人类前方,则判定游戏失败。5.1.7碰撞逻辑说明僵尸从屏幕右方向左移动,当僵尸生成之后,如果该条路线种植了攻击性植物,将开场发射子弹。子弹,植物与僵尸碰撞大小区域即为图片大小区域,当两者发生接触后即发生碰撞。子弹与僵尸碰撞之后随即消失,僵尸生命值随即相应减少。子弹超过屏幕右边界后消失。5.1.8状态播放规则所有植物素材均为8帧,僵尸素材为7帧。每100ms播放一帧,播放完毕之后自动从第一针开场重新播放,如此循环。5.2软件架构根据前面的需求分及用户的根本要求,软件的总体构造设计包括有软件加载、主界面、主要功能选择、模式选择、开场游戏、游戏设置等。软件的总体架构如图3.1。图3.1软件总体架构图软件加载:用户翻开游戏后进展游戏加载欢送用户使用该软件;主界面:主要展现游戏整体的功能界面;模式选择:玩家根据自身喜好决定并选择在何种模式下进展游戏;开场游戏:实现植物大战僵尸的功能;游戏设置:实现对游戏各种属性进展设置的功能。5.3软件功能构造图根据总体设计例图,分析出程序功能主要包括:游戏加载、游戏模式选择、关卡选择、游戏设置、游戏帮助。主要根据软件根本设计模块来设计这些功能,软件总体功能构造如图3.2。图3.2软件功能构造图5.4软件具体功能模块根本介绍根据游戏的具体功能模块:主要功能选择、游戏音效开关、模式选择、关卡选择、查看帮助帮助等功能模块。植物大战僵尸游戏功能模块有以下功能:5.4.1主要模块选择功能该模块其实就相当于植物大战僵尸游戏的主菜单,在该模式下,玩家可以对游戏属性进展设置,根据自己的喜好选择如何开场游戏,以及查看游戏帮助等所有该游戏提供应玩家的功能。游戏状态为MENU时激活该模块,之后根据玩家在不同位置的触屏事件调用相关的功能模块,在玩家点击设备返回按钮时退出游戏。功能选择模块流程如图3.3。5.4.2游戏声音开关功能游戏默认关闭背景音效和效果音,玩家可以根据自己爱好选择是否开启背景音乐或者游戏效果音。在主菜单中点击"选项〞按钮,玩家则进入声音设置功能,因为默认关闭背景音,这时会显示开启音乐,如果音乐开启后再次进入声音设置功能将显示关闭音乐。游戏效果音显示与背景音效一样。图3.3功能选择模块流程图5.4.3模式选择功能该游戏分三种模式,常规、夜晚和无尽模式。翻开游戏后因为还没有通关〔总共五个关卡〕,所以不能选择无尽模式游戏。这时玩家可以在常规模式和夜晚模式中进展选择,在通过所有关卡之后,将封锁常规和夜晚模式,玩家只能选择无尽模式。不管哪种模式,选择之后自动开场游戏。5.4.4关卡选择功能游戏分为5个关卡,每关有不同数量的僵尸且依次递增,玩家通过种植植物道具来消灭僵尸,待本关所有僵尸均消灭之后游戏自动进入下一关,并且玩家得到的奖励将显示在屏幕中的种子栏中,显示之后玩家就可以选择它进展种植,当然前提是值大于等于该植物所需要消耗的值,可以通过种植向日葵来得到,种的越多获得值的速度越快。为了防止作弊,关卡选择只对玩家通过的关卡有效。5.4.5查看帮助功能每款软件都具有帮助功能,该游戏也不能例外。在查看完帮助之后点击屏幕或者设备返回键将会自动转到主菜单界面。六、界面设计软件用户界面是指软件用于和用户交流的外观、部件和程序等等。为了使该游戏在界面上到达吸引眼球的目的,结合了图形和版面设计的相关原理对其界面进展了美化、规化的设计。6.1构造设计根据对软件架构的分析,知道游戏应该有以下界面:欢送界面〔游戏加载〕、游戏主菜单、关卡选择界面、游戏设置界面、查看帮助界面、胜利界面、失败界面、游戏界面。翻开软件之后显示到欢送界面、点击"开场游戏〞之后界面转到主菜单界面,之后用户根据需要选择各种功能后转到相应界面,不同界面之间的跳转关系如图4.1。图4.1界面跳转关系图6.2交互设计该游戏为Android中文版,因此界面语言选择使用中文。每个页面都添加有onTouch()函数和onKeyDown()函数以响应用户触屏和点击按键事件,其功能都是退出本页面,在欢送、主菜单界面点击退出按钮则是退出游戏,这么设置主要是为了程序方便退出。主菜单实现了程序功能选择功能,其实它就相当于实现了程序导航功能。主菜单界面设计如图4.2。游戏界面有一个种子收集栏,点击该区域相应种子之后将其拖动到种植区域就能将植物种植,种植区分为五个横着的跑到,每行都有僵尸进攻。游戏界面设计如图4.3。6.3视觉设计游戏采用绿色为主色调,这是大局部植物的颜色,色彩与容符合。角色造型使用卡通设计表现形式显得滑稽、得意。图4.2主菜单界面设计图图4.3游戏界面设计图七、详细设计与实现植物大战僵尸游戏采用面向对象的方法进展设计,在对象设计过程中将程序中各种事物都看成是对象,复杂的对象可以由比拟简单的对象以*种方式组合而成。把对象划分为对象类,为他们定义数据与方法。建立子类与父类的构造关系。将需要使用的图片准备好,需要修改的用Fireworks修改,最后使用Java代码将该游戏各个局部描述出来。5.1搭建游戏根本骨架5.1.1SurfaceView框架在Android系统中创立植物大战僵尸游戏的实现方法,需要使用到SurfaceView游戏框架,它主要是用来开发复杂的游戏,在要求程序执行效率很高时,例如对速度要求很高的游戏,可以使用双缓冲来显示。游戏中的背景、人物都绘制在一个画布上,而Surfaceview可以直接访问一个画布。因为系统默认建立竖屏工程,所以首先在AndroidManifest.*ml配置文件的<Activity>里添加代码android:screenOrientation="landscape"将屏幕设置为横屏显示。定义一个类"MainSurfaceView〞,此类继承SurfaceView,除此之外还要实现和Runnable接口。在其中定义了一个SurfaceHolder类的实例,该类可以为提供SurfaceView的大小,格式等,并且主要用于监听SurfaceView的状态。我们是通过SurfaceHolder来控制SurfaceView的,使用lockCanvas()函数来获取到SurfaceView的Canvas对象,再通过在Canvas上绘制容来修改SurfaceView中的数据。为了防止SurfaceView在绘制过程中被修改、摧毁等发生的状态改变,要用lockCanvas()函数对Canvas画布进展加锁,在绘制完成后还要使用unlockCanvasAndPostt()函数来解锁画布和提交。因此绘画函数总是在这两个函数之间进展调用。根据界面设计,在该类中定义表示游戏各种状态的整型常量:GAME_MUNU、GAME_WELE、GAME_INGDAY、GAEM_WIN、GAME_LOST、GAME_SELECT等将他们初始化。定义画图函数myDraw(),里面使用switch()语句实现在不同游戏状态下的游戏绘图。onTouchEvent()函数同样这么处理。在游戏中,根本不会等用户每次触发了按键事件、触屏事件才去重绘画布,而是会固定一个时间去刷新画布,比方僵尸单位前进时向前迈步、植物单位的动态显示、子弹前进等并不会跟玩家交互,但是这些元素都是动态的。所以游戏开发中,要设置一个线程不停的去重绘画布,实时的更新游戏元素的状态。因此在实现run()方法时,要使用while循环在循环标志为真的情况下每隔一段时间调用绘画函数,这一段时间到底要多长呢?无疑这必须要根据人眼视觉暂留的特性来确定。比方一个视频,如果帧数到达24帧,则这个视频播放起来人眼是感觉不到卡顿的。24帧意思就是每秒播放24图片。为了让程序到达每秒绘制将近24次,让程序每次开场绘制到下一次开场绘制的时间保持在50ms之,一秒绘制20次,这已经能够满足该游戏的需求了。接下来修改MainActivity类,onCreate(BundlesavedInstanceState)函数,用setContentView(newMainSurfaceView(this))让其显示自定义的SurfaceView视图,使用requestWindowFeature(Window.FEATURE_NO_TITLE)隐去标题栏,再使用getWindow().setFlags()函数隐去状态栏。定义init()函数将Config类中定义的各种位图初始化。5.1.2Wele类这是定义的欢送界面的类,定义了开场游戏按钮的横纵坐标等,它的draw()函数绘制了欢送界面背景和图片按钮。onTouchEvent()函数的功能是玩家在图片按钮区域触发ACTION_DOWN事件后,控制显示表示按钮被按下的图片。当玩家在按钮区域触发ACTION_UP事件后,按钮图片显示为未按下状态并使用MainSurfaceView.gameState=MainSurfaceView.GAME_MENU代码将游戏转到主菜单界面。5.1.3Menu类游戏主菜单,其中用boolean类型定义了所有按钮是否按下的状态,并将它们全部初始化为false。将"常规模式〞、"夜晚模式〞、"无尽模式〞、"退出〞等按钮按照主菜单界面设计中的布局绘制好。在ACTION_DOWN或者ACTION_MOVE事件中检测每个按钮的状态〔是否被按下〕,如果是,则在draw()函数中绘制被按下状态的相应图片按钮。在ACTION_UP事件中将被释放按钮的状态修正并转到相应的游戏状态,比方点击"帮助〞后调用MainSurfaceView.gameState=MainSurfaceView.GAME_HELP改变游戏状态。如果点击"退出〞,调用System.e*it(0)直接退出游戏。5.1.4Option类实现游戏声音设置功能。绘制完背景之后再绘制未按下状态的声音开关按钮。玩家在按钮区域点击一次该按钮,onTouchEvent()函数将变量Config.isPlayMusic取反,如果该值为真则播放背景音乐,如果为假则停顿播放背景音乐,并调用MainSurfaceView.backgroundMusic.prepare()函数为下一次开启背景音乐做准备。完成这些动作之后将游戏转到主菜单。5.1.5Help类Help类是给玩家提供帮助信息,把帮助容写在一图片上,玩家需要帮助时翻开该功能,该类把帮助图片绘制在屏幕上,玩家可查看帮助。看完之后点击屏幕触发ACTION_UP事件,游戏转到主菜单界面。5.1.6Select类该类为玩家提供选择关卡功能。玩家点击屏幕并在相应关卡位置触发ACTION_UP事件后,程序判断现在已通过最高关卡Config.tempLevel是否大于或者等于用户选择的关卡,如果成立,则将游戏设置为玩家选择关卡,否则弹出消息提示用户"该关卡还没解锁〞。接着在MainSurfaceView类中将游戏状态gameState初始化为GAME_WELE,定义上述类的对象并初始化,在myDraw(),onTouchEvent()函数相应的游戏状态下分别调用这些对象的draw()和onTouchEvent()函数。到此游戏根本骨架搭建完成,类图如图5.1。图5.1游戏框架相关类图5.2游戏model包5.2.1TouchAble接口Android手机可见的按键非常少,很多除了开机键,音量键就只有功能键、主菜单键、返回键,玩家在玩游戏时都是使用手指触屏进展操作,所以每个操作对象都会响应触摸事件。为了满足程序的这个要求,定义了TouchAble接口方便有要求的类实现。5.2.2Plant接口植物单位是需要拖动种植的,而种植就需要坐标,当然这个坐标不能随便选取,因为在之前的分析中就强调了在植物和僵尸的交战区域被分为了五条路线,每条路线有九个格子可以种植植物单位,植物只能种植在这些规定好的格子中,这四十五个格子就必须固定,而且一个格子只能种植一种植物,不能重复,即使是同一种植物在同一个格子里也不能种植两个。给这个格子编号用来记录是否种植过植物并且记录每个植物种植的位置。所以定义该接口以实现getMapInde*()方法。5.2.3BaseModel类在游戏中,不管是植物单位,僵尸单位还是种子栏中的种子图片,他们都有一些共同的属性或者方法,比方他们的坐标,即这些图片应该出现的位置,还有所有对象想要在设备屏幕中显示出来都要调用一个绘画方法来把自己画出来。根据面向对象的继承性〔这个性质无疑给程序带来了许多突出优点〕,为了减少冗余信息,应当抽取相似类的公共属性和公共效劳。所以要为程序中一局部类建立父类BaseModel。5.2.4Config类虽然说要尽量防止使用全局变量,不过现在的设备性能越来越高,和以前老机器不可同日而语,所以我认为这个问题不是现在最关注的问题。Config类就是存放游戏中需要使用的各种全局变量的。比方屏幕的宽度和高度,产生阳关、僵尸、子弹的时间等。为什么要这么做是由原因的,因为开发过程中需要跑测试,为了快速完成这个过程,要修改上述这些变量,如果没有设置全局变量将浪费大量时间做重复的修改操作。该类还定义了游戏中各种对象所使用的图片素材。普通类中是不能从图片工厂中获得图片,普通类需要使用图片只能从构造函数中传递进去,如果在每个使用上述普通类的地方都去定义图片素材并加载图片,这将使程序显得相当混乱,不好管理。该类还定义了所有适合种植植物点的集合,并将交战区域定义为五条路线并准备对它们的竖坐标进展记录。5.3游戏具体实现及相关的实体类5.3.1太阳花种植及产生实现SeedFlower类为种子栏中的太阳花卡片,继承自BaseModel,实现了TouchAble接口。除了定义其显示的坐标、是否存在的成员变量外,还定义了一个矩形的触摸区域。其成员变量及成员方法如图5.2。图5.2SeedFlower类成员变量及成员方法示意图SeedFlower():SeedFlower类的构造函数,其中将所有属性初始化,需要特别说明的是isAlive默认为true。drawSelf():绘画函数,主要实现太阳花种子图片在各种情况下的显示情况。具体实现描述如下。在能够显示该种子卡片的情况下,如果当前值Config.sunshineValue小于种植太阳花所需要的值Config.flowerCost,将画笔Alpha值设置为100,画太阳花。为了不影响其他对象使用画笔还需要在画完太阳花后将画笔Alpha值复原为255。onTouch():触屏处理函数,在该函数中首先记录捕捉的触摸点坐标,检测touchArea.contains(point*,pointY)&&Config.sunshineValue>=Config.flowerCost,如果成立则在该坐标显示一个即将被种植的植物,这个功能需要使用定义在Game类里的apply4EmplacePlant(intlocation*,intlocationY)函数来实现。该函数会检测即将种植哪种植物并新建一个即将被种植的植物对象。EmplaceFlower类是将被种植的太阳花类,同样继承自BaseModel,实现TouchAble接口。touchArea:手指触屏移动跟随区域,根据构造函数接收的参数初始化为即将种植太阳花大小的区域。onTouch():触屏函数,触发ACTON_MOVE事件时,对该类的横纵坐标进展修正,使触摸点在图片中心,并使touchArea随着触摸点的移动而移动。响应ACTION_UP事件时,将isAlive变量赋值为false,在移除该对象后调用Game类中apply4Plant(intlocation*,intlocationY,BaseModelbaseModel)函数种植植物。在该函数会检测种植哪种植物,这里种植太阳花,所以会新建Flower类对象。Flower类是屏幕上种植的太阳花,继承自BaseModel,实现了Plant接口。除了具有从父类继承来的变量,还具有自己的新整型成员变量:frameInde*,mapInde*和长整型变量lastShineTime,他们分别表示太阳花位图数组下标,所在格子编号,上一次产生的时刻。如图5.3。图5.3Flower类成员变量及成员方法示意图drawSelf():绘图函数,绘制当前帧的图片,当前帧自加一后对8取余,当现在时刻减去上一次产生时刻的时间差大于系统产生时间CSunshineTime,将上次产生时刻赋值为现在时刻,调用Game类中produceSunshine(intlocation*,intlocationY)函数来产生有光,在该函数中新建Sunshine类对象。种植植物流程如图5.4。图5.4种植植物流程图Sunshine类是太阳花每隔10s生产出来的。产生之后生存5s,如果在这5s之点击了,会移动到值记录处,并将值增加50,如果超过5s没有点击,它会自动消失。为了防止在移动时没有到达终点就消失,它存在的时间只在显示状态有效。其实这种情况是存在的,比方玩家点击了*个生存4.99s的,理想的效果是它会从改点移动到终点然后消失,但是因为它的生存时间只有5s,在这仅剩的0.01s里它还没有来得及移动到终点就消失,这种情况是不允许的。从上述设计可以看出有两种状态,一种是显示状态,另一种是移动状态。该类中定义了枚举类型的状态sunshineState,可取值SHOW,MOVE。SHOW表示生命时间对其有效,MOVE表示生命时间对其无效。drawSelf():如果该还存活的状态下,它处在SHOW状态时,判断存活时间是否超过5s,如果超过,isAlive赋值为false,如果没有不进展操作。处在MOVE状态时,它的横纵坐标分别以*Speed,ySpeed速度递减,当纵坐标小于屏幕上边界时,值加50,并将isAlive赋值为false。需要说明的是用户点击时它的状态就被设置为MOVE,并计算它运动起点到终点的横纵距离,分别用*Distance,yDistance表示,要在5帧后使它完成移动就要将*Speed,ySpeed分别设置为*Distance/5f,yDistance/5f。状态图如图5.5所示。图5.5的状态图5.3.2豌豆射手种植及射击实现同太阳花一样定义其相关实体类SeedPea、EmplacePea、Pea、Bullet其中前三个类与太阳花相似,这里不做描述。Bullet,子弹类,继承自BaseModel,不需要实现已定义接口。*Speed表示子弹横向移动速度,初始化为5。在它的drawSelf()函数中,先画出子弹后将它的横坐标加上*Speed,这样每一帧连接起来就会看到子弹以匀速向右移动,当他超过屏幕右边界时,isAlive置为false。因为子弹需要与僵尸发生碰撞,所以定义getModelWidth()方法获取子弹图片宽度以对碰撞进展控制。5.3.3生成僵尸的实现僵尸类Zombie继承BaseModel,不需要实现接口。构造方法参数需要传递生成所在位置坐标,还需要传递一个整型变量raceWay,它表示跑道,也就是前面分析提到的僵尸行进路线,僵尸在做碰撞检测时只需要检测本跑道的子弹或者植物,不用其他跑道的事情,这也是划分5条跑道的好处。因为僵尸是在边播放自己的动画帧边向屏幕左方运动,所以在drawSelf()函数中不仅在绘制每一帧之后要把动画帧下标加一,还要将它的横坐标减去僵尸前进速度*Speed,当然每次动画帧加一后要对7取余,因为僵尸动画有7帧。为了对碰撞进展处理也需要定义getModelWidth()来获取僵尸图片宽度。为了对生成僵尸进展管理还需要定义ZombieManager类来控制僵尸的产生。为了控制每个一段时间产生一个僵尸定义长整型变量lastBirthTime=0,在drawSelf()函数中判断如果上次产生僵尸时刻到现在大于15s,则向Game类申请apply4AddZombie()在屏幕中产生僵尸。5.3.4游戏大管家定义Game类的draw()函数,在其中先绘出背景图片、种子栏,在游戏屏幕添加一个菜单点击按钮,作为游戏暂停功能。在游戏屏幕添加一个菜单点击按钮,作为游戏暂停功能。然后在MainSurfaceView类中定义Game对象并初始化,在myDraw(),onTouchEvent()中相应状态下调用Game类对象的draw(),onTouchEvent()函数。运行后可得到游戏进展中界面。由于游戏是通过不断绘制图片进展的,因此先画与后画必须分得非常清楚,不然导致非正常的覆盖将影响游戏视觉效果。最后画的元素在屏幕最上层,规定其为第一层,之后依次类推。在种植植物而拖动种子时,种子图片将随着手指的移动而移动,这个时候种子图片应该显示在所有屏幕对象的最上边,即它能够覆盖其他元素而不能被任何元素覆盖,所以应该为第一层,在绘图函数中应该最后画。植物种子规定为第二层,规定为第三层,最后植物、僵尸、子弹为第四层。当然还有游戏背景和种子栏,因为没有单独为他们设计类,所以直接在函数中画出。定义容器gameLayout1,gameLayout2,gameLayout3分别表示第一层、第二层、第三层容纳的单位。用gameLayout4plant0,gameLayout4zombie0分别表示第四层第一条跑道容纳的植物单位和僵尸单位。剩下的跑到依次类推。定义createElement()方法为值Config.sunshineValue赋初值200,对各种容器初始化,并在该方法中新建SeedFlower、SeedPea类对象seedFlower、seedPea,将他们初始化到种子栏中相应位置,用gameLayout2.add()添加到第二层。实现apply4EmplacePlant()方法。首先对MainSurface.sfh加锁,防止意外访问。程序是在不断循环的,当点击植物种子后,有可能会创立假设干个将要被种植的植物,所以要检测gameLayout1.size()是否为0,如果为零判断将要种植哪种植物,调用gameLayout1.add(newEmplace***(location*,locationY))创立并添加到第一层。在draw()方法中遍历gameLayout1,调用其中元素的drawSelf()方法。创立之后并不能将该对象搁置不管,要在用户触发ACTION_UP事件时做两件工作。第一:将其isAlive属性赋值为false并清理掉该对象。因此需要新定义removeEmplacePlant()方法以遍历gameLayout1,如果其中有不需要的元素则将其添加到deadList容器中,之后再遍历deadList将其销毁。这时gameLayout1.size()值为零,为下一次种植做准备。第二:调用apply4Plant()种植选取的植物。实现apply4Plant()方法,要实现该方法需要做一些准备工作。根据概要设计是要将交战区划分为45个格子,每个植物必须种植在格子中间,不能出现在其他地方。使用下面的代码计算交战区45个格子坐标并保存。privatevoidcreateElement(){……for(inti=0;i<5;i++){for(intj=0;j<9;j++){Config.plantPoints.put(i*10+j,newPoint((j+2)*Config.screenW/11-Config.screenW/11/2,(i+1)*Config.screenH/6-10));if(j==0){Config.raceWayYpoints[i]=(i+1)*Config.screenH/6-10;}}}}外层循环用来控制跑道的行数,层循环用来控制跑道的列数。认为游戏背景左侧非交战区占1.5倍格子的宽度,右侧非交战区大约占0.5个格子的宽度,上册非交战区高度占一个单元格的高度,因此一个格子的宽度和高度大约分别占整个游戏背景宽度的十一分之一,高度的六分之一。上面代码i*10+j表示第几个格子,j+2表示忽略前两列,之后再减去0.5个格子的宽度就就是i行每个格子的横坐标。i+1表示忽略一个单元格的高度,Config.screenH/6–10中的减去10是对纵坐标进展的修正。if语句记录跑道的纵坐标。在添加植物方法中先遍历plantPoints集合,找到离Eplace***类对象最近的种植点并计算该点在那个跑道,确定跑道之后才能将要种植的植物添加到相应跑道的植物容器中。该功能代码如下:publicvoidapply4Plant(intlocation*,intlocationY,BaseModelbaseModel){……for(Integerkey:Config.plantPoints.keySet()){point=Config.plantPoints.get(key);if((Math.abs(location*-point.*)<Config.screenW/11/2)&&(Math.abs(locationY-point.y)<Config.screenH/6/2)){intraceWayInde*=6;for(inti=0;i<Config.raceWayYpoints.length;i++){if(point.y==Config.raceWayYpoints[i]){raceWayInde*=i;} }……}}}将要被种植植物图片左上角坐标横坐标与plantPoints集合中每个点横坐标相减,如果他们的绝对值小于半个格子的宽度并且这两个点纵坐标之差的绝对值小于半个格子高度,则此时遍历到的点就是植物最适宜种植的点,接下来遍历raceWayYpoints数组寻找该适宜点在第几个跑道。在添加植物时还要判断该适宜种植点是否已经存在植物,如果有植物时放弃种植。isE*istPlant(intkey,intraceWayInde*)方法实现了该功能。根据得到的跑道数,对该跑道植物集合进展遍历,如果是Plant接口的子类,如果在集合中*个植物的key与适宜种植点的key值一样则这个点已经存在植物,现在不能再这里种植。如果遍历完所有对象都没有找到则返回一个true表示可以种植。让屏幕出现僵尸,在Game类中的处理比添加植物简单多了。在Game类中新建ZombieManager对象zombieManager并初始化后在,draw()方法中调用该对象的的drawSelf()方法,最后只需要实现apply4AddZombie()方法。取随机数Math.random(),(int)(Math.random()*10)%5处理之后赋值给新定义的局部变量raceWay,根据raceWay,新建僵尸添加进相应跑道中僵尸容器后就实现了生成僵尸的方法。下面是其实现代码:publicbooleanisE*istPlant(intkey,intraceWayInde*){switch(raceWayInde*){case0:for(BaseModelmodel:gameLayout4plant0){if(modelinstanceofPlant){if(key==((Plant)model).getMapInde*())returnfalse; }}break;……}returntrue;}5.3.5根据有无僵尸判断是否射击现在要实现只有当跑道有僵尸时豌豆射手才发射炮弹,当该跑道的所有僵尸死亡或者还没有产生僵尸时豌豆射手停顿射击处于休息状态即不发射炮弹。首先在Pea类中定义布尔变量isShoot,初始化为false,定义其get与set函数,在该类中只有当isShoot为true时才调用shootBullet()函数。在大管家Game类apply4AddZombie()中当产生僵时遍历该产生僵尸的跑道是否有豌豆射手存在,如果有就将豌豆射手isShoot设置为true,假设果没有不做处理。运行程序之后发现假设果先种植豌豆射手再产生僵尸一切正常没有问题,如果该跑道没有种植豌豆射手之前已经产生僵尸,再种植豌豆射手后豌豆射手将不会攻击,除非这时该跑道又产生一个僵尸。分析之后发现不应该在产生僵尸时判断是否有豌豆射手,而是应该在豌豆射手发射炮弹时判断该跑道是否有僵尸,假设果有才发射,否则不发射。这样在Pea类中就不需要定义isShoot变量,直接在shootBullet()中判断是否发射。5.3.6过关奖励对玩家过关进展奖励,分别新建SeedSnowpea、EmplaceSnowpea、Snowpea类,与之前pea类似。只有一点区别在于SeedSnowpea类在构造函数初始化isAlive为false。在Game类定义SeedSnowpea对象seedSnowpea,当玩家过关Config.level增加到2时,调用seedSnowpea.setAlive()将isAlive设置为true。加强型豌豆射手,土豆卫士做相似处理即可。5.3.7游戏失败未谋胜,先谋败。因此这里先做失败的功能,前面已经说过当僵尸超过屏幕左边界时判定游戏失败,所以在每次僵尸向左移动之后都要判断僵尸的location*是否小于0〔屏幕最左侧横坐标为0〕,如果小于0,则游戏失败,游戏转到失败状态,显示并提示玩家游戏失败。考虑到游戏失败玩家可能还要继续游戏,所以还要单独定义一个失败类。其中要实现draw()函数,画出Config.bmpLost,显示"僵尸吃掉了你的脑子!〞当玩家点击屏幕时响应MotionEvent.ACTION_DOWN事件,这里为了简单,就不多设计up与down的不同之处。想要到达预期效果还需要实现onTouch()函数。5.3.8游戏胜利接着要做胜利界面,建立Win类与Lost类根本一样,只是在draw()函数中画出胜利图片,点击事件触发时将游戏状态设置为GAME_WIN,在MainSurfaceView建立Win对象win,然后在myDraw(),onTouchEvent()分别调用win对象的draw()、onTouchEvent()函数。到这里重要的问题出现了,那就是游戏如何判定玩家胜利,根据该游戏的规则,在玩家没有输掉游戏之前消灭掉一定数量的僵尸则判定玩家胜利,先试着在Config.java文件中定义一个level0ZombieCount整型变量来表示通关要消灭的根底僵尸数量,为了测试简单,暂时先赋值为3。这只是胜利要消灭的僵尸数量,还要在Game类中定义deadZombieCount整型变量来表示已经消灭僵尸的数量,如果该值等于level0ZombieCount则判定游戏胜利,在Game类中checkCollision()中当僵尸生命值小于或者等于0时判断++deadZombieCount是否大于等于Config.level0ZombieCount,如果成立则将游戏状态设置为GAME_WIN。当然这里有个问题,那就是游戏每隔15s产生一个僵尸,而现在是死亡deadZombieCount个僵尸之后游戏完毕,这就会出现屏幕还有僵尸没有被消灭游戏也会完毕,这样处理:每个关卡产生一定僵尸,其数量由根底数量level0ZombieCount乘以当前关卡level的积确定。用zombieCount记录其当前数量,当产生的僵尸还没有到达规定的数量时才能继续产生,否则停顿生成僵尸。每当有僵尸死亡时判断死亡僵尸数量是否到达通过该关卡所需要的数量〔用deadZombieCount%(Config.level0ZombieCount*Config.level)==0判断〕,假设成立,Count.level++,并将deadZombieCount、zombieCount都赋值为0,之后进展下一关〔在屏幕上方显示当前关卡〕。游戏总共分为5个关卡,通过所有关卡〔level>=6时将游戏状态设置为胜利)后游戏才会胜利。5.3.9无尽模式游戏在常规模式或者夜晚模式中退出时回到主菜单并将游戏初始化,当这两种模式之一通关之后要对玩家开放无尽模式,同时,常规模式和夜晚模式将不对玩家开放。无尽模式通过Config.level>=6判断,不成立点击无尽模式不能进入游戏。在无尽模式中没有关卡概念,只有玩家得分,分数根据消灭僵尸而增加。定义全局变量score=0,在Game类draw()函数中当游戏状态为无尽模式时显示得分,将游戏胜利条件改为:在常规模式或者在夜晚模式时Config.level>=6;5.3.10僵尸碰到植物停顿当吃掉植物后继续前进实现僵尸碰到植物停顿前进,当吃掉植物后继续前进功能。在Zombie类中定义布尔变量isMove表示僵尸是否移动并初始化为true、长整型变量eatTime记录僵尸碰撞植物瞬间系统时间戳,并设置两个成员变量get(),set()属性。在僵尸横向移动代码上添加条件语句:只有isMove为真时僵尸向左移动。在Game类中碰撞函数检测到僵尸与植物相遇时,如果僵尸处于移动状态,使其停顿前进,将这一刻系统时间戳使用zombie.setEatTime(System.currentTimeMillis())记录。当僵尸处于静止状态并且该僵尸停留时间超过3s时,将植物isAlive赋值为假,并且把僵尸移动状态改为真。5.4调试5.4.1吃掉植物后僵尸不前进运行游戏发现僵尸遇到植物后停下,3s之后植物消失,但此时僵尸同样停顿不动。在代码中添加log.i()检测,代码根本不按照预想路线走。在一个地方执行很多遍,这段代码预计只有碰撞之后才执行一遍,但实际情况是碰撞之后屡次执行碰撞函数,碰撞条件自身是不可能错的,则只能是其他隐藏条件的问题。僵尸停顿超过3s将植物isAlive赋值为假,植物从屏幕消失,紧接着僵尸移动状态被赋值为真〔这里使用log.i()检测到isMove已被赋值为真〕,但是僵尸并没有移动,说明isMove又被赋值为假,也就是说已经从屏幕消失的植物又和僵尸发生碰撞,则该植物根本就没有消失,它还在原地,只是处于"隐身〞状态,想到这里真相大白,在将其从屏幕移除时应该紧接着将该植物remove掉〔这里是调用update()函数,这样调用会造成程序异常〕。碰撞超过3s植物消失,僵尸继续前进。该问题解决。5.4.2僵尸生命值丧失异常将僵尸生命值设置为4,每次被炮弹击中一次生命减少1,当生命减少到0时,僵尸死亡,将其isAlive设置为false,在碰撞检测函数中当碰撞一次时通过--zombie.lifeValue但是运行效果是僵尸碰到
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025至2030中国脊柱解剖模型行业发展研究与产业战略规划分析评估报告
- 2025至2030中国管理服务方案行业发展研究与产业战略规划分析评估报告
- 2025至2030中国碎细胞松花粉粉行业发展研究与产业战略规划分析评估报告
- 三方装修合同【三篇】
- 实验室安全考试试题及答案
- 健康教育知识测试题及答案
- 医疗器械考试题及答案
- 会计知识竞赛题及答案
- 农艺知识竞赛题及答案
- 2025口腔执业医师考试《口腔修复学》试题及答案
- 厂房分割租赁协议书
- 会计中级职称《财务管理》电子书
- GB/T 45345-2025金属及其他无机覆盖层工程用直流磁控溅射银镀层镀层附着力的测量
- 无人机教员聘用协议书
- 药物非临床研究质量管理规范
- 脑科生理病理图谱解读
- 足球教练员的职业素养与道德规范
- 产地证培训讲义
- 《南京理工大学化工》课件
- 养殖场远程视频监控解决方案
- 二手车转让免责协议书范本
评论
0/150
提交评论