完整版基于JAVA的游戏毕业设计论文Word下载.docx
《完整版基于JAVA的游戏毕业设计论文Word下载.docx》由会员分享,可在线阅读,更多相关《完整版基于JAVA的游戏毕业设计论文Word下载.docx(25页珍藏版)》请在冰点文库上搜索。
Java平台演进到Java2后,Java平台分别针对不同领域的需求被分成四个版本,亦即J2EE、J2SE、J2ME以及JavaCard(其结构示意图见图1.1)。
图1.1Java结构图
J2SE就是Java2的标准版,主要用于桌面应用软件的编程;
J2ME主要应用于嵌入是系统开发,如手机和PDA的编程;
J2EE是Java2的企业版,主要用于分布式的网络程序的开发,如电子商务网站和ERP系统。
StandardEdition(标准版)J2SE包含那些构成Java语言核心的类。
比如:
数据库连接、接口定义、输入输出、网络编程。
EnterpriseEdition(企业版)J2EE包含J2SE中的类,并且还包含用于开发企业级应用的类。
EJB、Servlet、JSP、XML、事务控制。
MicroEdition(微缩版)J2ME包含J2SE中一部分类,用于消费类电子产品的软件开发。
呼机、智能卡、手机、PDA、机顶盒。
通过本次设计可以综合运用J2SE所拥有的API,初步掌握面向对象编程的基本思想,掌握Eclipse开发J2SE程序的基本方法。
掌握Eclipse调试程序的方法。
简单的应用了设计模式等概念。
第2章开发环境及相关技术的介绍
2.1开发环境
操作系统:
MicrosoftWindowsXP
程序语言:
Java2
开发包:
Java(TM)2StandardEdition(build1.7.1)SunMicro.
IDE:
Eclipse-SDK-3.4.1
2.2Java语言的特点
1、平台无关性
Java引进虚拟机原理,并运行于虚拟机,实现不同平台之间的Java接口。
使用Java编写的程序能在世界范围内共享。
Java的数据类型与机器无关。
2、安全性
Java的编程类似C++,但舍弃了C++的指针对存储器地址的直接操作,程序运行时,内存由操作系统分配,这样可以避免病毒通过指针入侵系统。
它提供了安全管理器,防止程序的非法访问。
3、面向对象
Java吸收了C++面向对象的概念,将数据封装于类中,实现了程序的简洁性和便于维护性,使程序代码可以只需一次编译就可反复利用。
4、分布式
Java建立在TCPIP网络平台上,提供了用HTTP和FTP协议传送和接收信息的库函数,使用其相关技术可以十分方便的构建分布式应用系统。
5、健壮性
Java致力与检查程序在编译和运行时的错误,并自动回收内存,减少了内存出错的可能性。
Java取消了C语言的结构、指针、#define语句、多重继承、goto语句、操作符、重载等不易被掌握的特性,提供垃圾收集器自动回收不用的内存空间。
2.3关于ECLIPSE
Eclipse是一个开放源代码的、基于Java的可扩展开发平台。
就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。
幸运的是,Eclipse附带了一个标准的插件集,包括Java开发工具(JavaDevelopmentTools,JDT)。
虽然大多数用户很乐于将Eclipse当作JavaIDE来使用,但Eclipse的目标不仅限于此。
Eclipse还包括插件开发环境(Plug-inDevelopmentEnvironment,PDE),这个组件主要针对希望扩展Eclipse的软件开发人员,因为它允许他们构建与Eclipse环境无缝集成的工具。
由于Eclipse中的每样东西都是插件,对于给Eclipse提供插件,以及给用户提供一致和统一的集成开发环境而言,所有工具开发人员都具有同等的发挥场所。
这种平等和一致性并不仅限于Java开发工具。
尽管Eclipse是使用Java语言开发的,但它的用途并不限于Java语言;
例如,支持诸如CC++、COBOL和Eiffel等编程语言的插件已经可用,或预计会推出。
Eclipse框架还可用来作为与软件开发无关的其他应用程序类型的基础,比如内容管理系统。
就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建。
第3章程序结构、思想和相关技术
3.1本程序需解决的有关技术问题
1、游戏程序是一项精度要求很高的程序系统,因为其代码利用率很高。
一个实时运行的最终作品,每秒都会运行成千上万行程序,绘图事件、键盘事件都会以极高的频率在后台等待响应,若有丝毫的差别都将很容易导致程序在运行不久后可能出现严重错误,甚至死循环。
因此,其逻辑设计应当相当严谨,需将所有可能发生的事件及意外情况考虑在设计中。
2、游戏中为了美观,适用性强,可能需要采用外部文件引入的图片贴图,有关贴图,在MIDP2.0中提供了用于增强游戏功能的game包,使得解决静态或动态、画面背景、屏幕刷新的双缓冲等都有较好的解决方案。
3、己方坦克的运行可以通过键盘响应事件控制,但敌方则因为是自动运行,就需要有一定其一定的智能性;
同时,出现在屏幕上的敌方可能会有较多的数量,这需要为每个敌方开辟一个线程以便能让其独立运行。
Java的多线程能力为实现这样的游戏提供了可能。
敌人坦克的运行算法也需要进行适当的设置,以免游戏过于简单,单调。
4、对于双方坦克发出的子弹的控制也需要对其跟踪控制,子弹也需要处在独立的线程中。
敌方子弹仅需要扫描用户坦克,而用户坦克需要在每一步扫描所有的敌方坦克。
这需要对所有的对象有较好的控制。
另外,子弹在运行过程中也需要实时扫描是否碰撞到了相关障碍物或屏幕边界。
如此过多的线程同时在本来效率就不高的KVM虚拟机上运行,也许会导致程序的缓慢。
5、双方的坦克在前进时也需要考虑到是否碰撞到相关物体或对方坦克,以免重叠运行,造成许多物理上不可能的情况,缺乏真实感。
每一次刷新页面、每前进一步都需要将所有的周围环境都进行扫描。
6、游戏的结束、开始、动态信息画面作为构成一个完美程序都是必不可少的重要部分。
良好的用户界面更是吸引用户的硬指标,相关的美术构图也需要有一定的考虑。
7、游戏的地图不可能通过绘图来解决。
否则,不仅难于控制和处理过多的元素,也会因过多的大型图片而不能限制程序的大小,失去程序的原则和Java的优势。
同时,地图关卡不宜保存占用过多的内存,而最好采取外部文件的读入读出方法。
8、用户运行游戏时需要有分数记录的可能。
如何采用合理的记分标准,需要进行适当的设计。
记录分数的存储方式也需要有较好的解决方案。
手机中由于处理器和内存空间、存储空间都十分有限,其数据库系统与普通PC大相径庭。
其数据库结构较为简单,被称之为RMS系统。
9、本程序应用的技术
多态Polymorphism;
单例模式Singleton;
责任链模式ChainofResponsibility;
工厂模式FactoryMethod;
简单工厂模式SimpleFactory;
抽象工厂模式AbstractFactory;
策略模式Strategy;
调停者模式Mediator;
门面模式Facade等概念与技术并将一些属性信息抽象了除了以配置文件的方式出现,从而方便用户更改。
以上相关技术细节和整体流程将分别在以下小节阐述。
3.2程序截图
开始界面
游戏界面
坦克混战
狂轰滥炸
图3.1程序截图
3.3程序流程
本程序采用面向对象的设计模式,对游戏中的所有物体赋予对象的概念和属性。
运行程序后允许用户选择执行选项菜单,在开始游戏后将先从外部文件载入地图文件,对背景的所有物体进行绘图。
在主程序运行的线程中,画面刷新将以一定的频率采用双缓冲技术对屏幕重绘,实时反映整个游戏的进行状态。
用户控制的坦克运行在主线程中,随屏幕刷新的频率而步进。
敌方坦克将在游戏开始时逐渐新增线程,每增加一个敌方对象就新增加一条线程,一旦线程数满到最大值,就不允许敌人再继续出现。
用户坦克自诞生之时起将拥有一发子弹,子弹虽然开在单独的线程中,但运行结束后(比如撞到相关物体或敌方坦克时)并不结束子弹对象,只是将其线程终止。
用户再次发射子弹时只是将终止的线程再次激活。
在屏幕重绘的主程序中,将在每次的循环中判断若干事件。
如:
用户坦克的生命是否已完全用尽,敌方坦克数是否已经为零,屏幕上的坦克数量是否少于仍剩下的坦克数量等。
以便程序进入相关的分支执行相关的反应代码,结束游戏或统计分数等。
主程序流程如图3.2所示。
3.4相关技术
3.4.1多态
多态性是继数据抽象和继承后,面向对象语言的第三个特征。
Java的多态性它的突出优点是使程序具有良好的扩展性。
它通过继承,可以派生出任意多个新类型,或向基类增加更多方法时,无须修改原有对基础类进行处理的相关程序。
就是扩展性好。
3.4.2单例模式
作为对象的创建模式[GOF95],单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
这个类称为单例类。
图3.3单例模式图
显然单例模式的要点有三个;
一是某各类只能有一个实例;
二是它必须自行创建这个实例;
三是它必须自行向整个系统提供这个实例。
在下面的对象图中,有一个"
单例对象"
,而"
客户甲"
、"
客户乙"
和"
客户丙"
是单例对象的三个客户对象。
可以看到,所有的客户对象共享一个单例对象。
而且从单例对象到自身的连接线可以看出,单例对象持有对自己的引用。
如图3.3所示。
3.4.3责任链模式
多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
适用范围:
1、有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
2、你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
3、可处理一个请求的对象集合应被动态指定。
com.cz.tank包下的ColliderChain类用责任链模式遍历所有游戏物体做碰撞检测。
3.4.4工厂模式
工厂模式为系统结构提供了灵活的动态扩展机制,减少工作量方便维护,方便维护。
com.cz.tank类GameFactoryMgr应用了工厂模式。
3.4.5简单工厂模式
专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
它又称为静态工厂方法模式,属于类的创建型模式。
简单工厂模式的UML类图如图3.4所示:
图3.4简单工厂模式
简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。
该模式中包含的角色及其职责。
用户在使用时可以直接根据工厂类去创建所需的实例,而无需了解这些对象是如何创建以及如何组织的。
有利于整个软件体系结构的优化。
3.4.6抽象工厂模式
抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品具体类型的情况下,创建多个产品族中的产品对象。
这就是抽象工厂模式的用意。
每个模式都是针对一定问题的解决方案。
抽象工厂模式面对的问题是多产品等级结构的系统设计。
3.4.7策略模式
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。
策略模式让算法独立于使用它的客户而独立变化。
本程序的坦克外观使用了策略模式。
com.cz.tank.strategies的DrawTankStrategy类。
3.4.8调停者模式
用一个中介对象来封装一系列的对象交互。
中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
com.cz.tank类GameMediator使用了调停者模式。
3.4.9门面模式
外部与一个子系统的通信必须通过一个统一的门面(Facade)对象进行,这就是门面模式。
3.4.10PNG格式
PNG具体格式由PNGSpecificationVersion1.0定义的。
PNG格式提供透明背景的图像,这对绘制游戏画面和被操纵主角极有帮助。
坦克之间或与障碍物碰撞时就不会因为背景有特定的颜色,显示出的效果像贴上的图片而缺乏真实感,物体之间轻微重叠时最上层图片也不会覆盖超过其有效象素外的部分。
PNG格式图片中包含许多定义其图片特性的冗余部分(Chunks)。
这些代码包含在每一个单独的PNG格式图像中,然而如果将多个PNG图像合并在一张幅面稍大一些的整图中,多个chunks就可以得到精简,图片的大小可以得到控制。
使用Image类中的createImage函数可从整图中分割出所需要的元素。
在Game包中的TiledLayer和Sprite类都整合了这样的功能。
本程序中的地图元素都集成在一张MAP.png图片中,实现了方便的管理和程序体积的精简。
3.4.11AWT绘制的基本原理
AWT的绘制与界面更新使用了一个单独的线程,称为AWT线程。
paint、repaint、update三个方法关系如图3.5所示:
图3.5双缓冲原理示意图
3.4.12双缓冲
进行游戏绘图一般需要手动编程使用双缓冲。
需要在paint()方法内所想要画的图形画在一张预先准备好的背景,等所有绘图操作都完成后再将背景的数据拷贝到实际的屏幕上。
Image类提供了一个建立背景的静态方法createImage(intwidth,int)。
当敌人坦克完全死亡时(enemyNum为0),需调用System类的currentTimeMillis()赋值给结果的时间。
接着调用setCurrent()显示统计分数的画面,为了进入下一关,统计画面只是停留四秒,就重新转回BattleCanvas画面。
当然,如果当前已是最后一关,就不会再转回。
进入下一关时,许多变量需要重新被初始化,如地图的绘制、敌人出现位置的重置、敌人的数量、玩家坦克的当前位置。
如果游戏未结束,则需判断屏上坦克是否已小于还剩坦克的总数,如果是这样,就需要再提供一辆坦克。
提供新坦克之前,在屏幕上设置了一个专用指示的闪光符号,它继承了Sprite,运行在单独的线程中。
以在两秒钟内反复闪现两次为一个生命周期。
当它闪光完毕后,敌人就会从闪光位置出现。
这样可提示玩家具体敌人将在什么时刻出现,以便做好准备。
闪光位置设置了三处坐标,由于敌人不能同时出现,便设置了enemyOutDelay的倒数计时,每次屏幕刷新会减少一次计数,直到为0时就准备一辆坦克。
本程序设置的两次坦克出现的最小间隔为2秒。
如果玩家已经死亡,就需要使用LayerManager的insert()将gameover字样插入到最上层,以免被其他物体覆盖。
在检测用户输入的input()函数中,当按方向键时,玩家坦克就将向不同的方向运行,这调用了UserSprite的go()函数;
当开炮时,就调用其fire()函数,作出相应的行为。
在出现正式画面前设置了一个loadingstate*字样的单独屏幕,调用了loadinglevel()函数,并停滞了1500毫秒,提示用户做好准备。
在绘图的render()过程中,除了要重绘坦克、地图、子弹外,还会在右边空白处绘出一个生命统计栏。
并反复使用Graphics的drawLine()、drawImage()绘画出一个三维的效果,增强视觉感。
该三维栏的上方为白色,下方为黑色,就创造了立体感。
在每次刷新绘图页面时,应使用GameCanvas的flushGraphics()将屏幕后台的缓冲区内的图象刷新到前台来。
在允许敌人出现前,需要检测给即将出现的敌人分配一个数组序号。
在程序中调用了getNullEnemyIndex()进行测试,当返回为-1时说明没有序号可以分配,否则,将返回空的序号。
4.2坦克的共同行为
在TankSprite中定义了所有坦克(包括敌方坦克和玩家坦克)的共同行为和属性。
EnemeySprite和UserSprite都继承了该类以简化结构。
在transformDirection[]中定义了坦克四个方向分别应将原始图片旋转的角度,分别为TRANS_NONE,TRANS_ROT90,TRANS_ROT180,TRANS_ROT270,以便在后来的setTransform()中将这些常量代入。
构造函数中创建了每个坦克必须拥有的一颗子弹,这些子弹就将只跟随自己的坦克调动。
为了能提前预测碰撞,调用了defineCollisionRectangle()将碰撞矩形向前设置了一个象素,具体原理见第二章。
在setBulletDirection()中,将根据坦克当前的方向确定子弹出膛后的方向,其中setRefPixelPosition()将子弹的参考点设置在其未变形状态的底部,setXY()将其放置到炮口的位置,setTransform()将其图片方向转到需要使用的位置。
canPass()函数将返回坦克是否能够向前前进,考虑到的因素有边界、障碍物。
它返回一个boolean值,提供给go()函数,做进一步的判断。
getTileIndex()将检测传递来的象素处是什么类型的障碍物,它将象素除以8(即障碍物的象素宽度),取整,再通过getCell()得到。
在得到障碍物属性后,判断其序号是否与草相同,或是否为空(序号为0)。
因为所有的障碍物中只有草不会阻碍坦克的向前运行。
4.3玩家坦克的功能属性
构造函数中需要将坦克方向设置为向上,因为刚出现时就是这样的状态。
当开炮时,调用BulletSprite的setLayerManager()将子弹与layerManager联系起来。
需要联系的还有自身坦克、地图。
这些都由坦克传递给子弹。
因为子弹是属于坦克的,它的属性需要跟当前的坦克保持一致。
接着使用append()将子弹贴到layerManager上显示出来。
最终调用其start()开始子弹自己的线程。
子弹一旦开始运行,就脱离了当前坦克的控制,直到其生命周期终止。
无论子弹是属于敌人还是玩家的,它都必须记录自己的来源和攻击的对象。
在玩家坦克发射的子弹中,就必须将攻击对象设置为所有的敌人。
这样,它才能有扫描的目标。
在setShootCheck()的参数中,传给子弹的是敌人的数组,子弹的对象就被确定了。
die()、resetPosition()、getLife()都是很简短的函数,但却提供必不可少的功能。
他们可被外部调用,以取得生命值、死亡记数、重置位置。
在go()函数,每个方向在走前都须用if(canPass(UP)&
&
!
collidesEnemy())
检测是否可以行走。
canPass()检测是否有障碍物及是否到边界。
collidesEnenmy检测是否前方有坦克阻碍行动。
当可以行走时,就在当前方向的坐标上增加或减少一个象素。
在collidesEnemy()函数中,将有一个for循环按照敌人数组的序号依次检测6次。
有一点非常重要:
在检测前,需要将敌人的检测矩形区域设置为与原来图片一样大小。
否则,当玩家向上走,而有敌人从左方向右走,并且已经碰撞到玩家坦克时,玩家坦克会因为被判定已与敌人发生碰撞而不允许前进。
事实上,敌人坦克此时并没有阻碍玩家前进。
这样的判断必须排除在考虑范围外。
当然,在设置完成后,必须将将检测区域设置回原先的状态,否则敌人在往后自己的检测中将发生错误。
4.4敌人坦克的功能属性
由于和UserSrite同属于一个TankSpr