当前位置:文档之家› java 编写 的坦克大战的游戏

java 编写 的坦克大战的游戏

java 编写 的坦克大战的游戏
java 编写 的坦克大战的游戏

第一章绪论

1.1 手机软件现状

在信息社会中,手机及其他无线设备越来越多的走进普通百姓的工作和生活,随着信息网络化的不断进展,手机及其他无线设备上网络势在必行。但是传统手机存在以下弊端:1. 传统手机出厂时均由硬件厂商固化程序,程序不能增加、删除,有了错误也不能更新、修改,若要增加新功能必须另换一部手机。

2. 传统手机访问互联网是通过W AP(Wireless Application Protocal),所有网络资源必须接通网络才能在线访问,非常耗时、费用亦很高。

而Java技术在无线应用方面的优势非常明显:

1. 应用程序可按需下载,而不是购买由硬件商提供的套件,可升级空间大。

2. Java技术提供了一个类库,它使的应用开发商可以创建更为直觉、丰富的用户界面(GUI);

3. Java技术使网络带宽的应用更为有效,因为应用程序可以下载到器件上,并在本地运行,仅仅是在连接到服务器时才会占用网络带宽。

基于以上分析,Java手机将是未来手机的发展方向,是业界的热点。

1.2 游戏业务及J2ME概况

虽然Java 已经被用到许多企业级软体上,可是其实骨子里面还是非常适合用在嵌入式系统

之中。Java平台演进到Java2后,Java平台分别针对不同领域的需求被分成四个版本,亦即J2EE、J2SE、J2ME以及JavaCard(其结构示意图见图1-1)。其中J2ME定位在消费性电子产品的应用上。这个版本针对资源有限的电子消费产品的需求精简核心类库,并提供了模块化的架构让不同类型产品能够随时增加支持的能力。这个版本的应用层面相当广泛,会是未来Java平台发展的重点项目。J2ME 在设计其规格的时候,遵循着“对各种不同的装置而造出一个单一的开发系统是没有意义的事”这个基本原则。于是J2ME 先将所有的嵌入式装置大体上区分为两种:一种是运算功能有限、电力供应也有限的嵌入式装置(比方说PDA、手机);另外一种则是运算能力相对较佳、在电力供应上相对比较充足的嵌入式装置(比方说冷气机、电冰箱、电视机上盒(set-top box))。因为这两种型态的嵌入式装置,所以Java 引入了一个叫做Configuration 的概念,把上述运算功能有限、电力有限的嵌入式装置定义在Connected Limited Device Configuration(CLDC)规格之中;而另外一种装置则规范为Connected Device Configuration(CDC)规格。也就是说,J2ME 先把所有的嵌入式装置利用Configuration 的概念区隔成两种抽象的型态。J2ME平台被认为是最杰出的手机游戏平台,它为开发者、设备制造商、网络通信公司和消费者广泛接受。它有一些非常重要的特征对所有组织都有益。因为J2ME应用在不同设备上都是便携式的,他们常常可在网络上下载和执行。如果没有正确的防范,它则为用户和无线通信公司冒着无数个安全的风险。幸运的是,Java被设计成一种安全的语言。所有字节码应用在执行之前都要校验;JVM在执行过程中监督应用的安全性和存储违反问题。MIDP v2 运行时间包括一个完全特征化的、基于域的安全管理员,它在应用的数字签名者鉴别的基础上赋予应用API级许可。

纵观IT产业的历史,就像军事的发展时常推动计算机的演化一样,计算机游戏已经成为技术创新背后的动力之一。计算机游戏者渴望更加强大的硬件计算能力;渴望不受不同的软件的限制——无论是将图形强制在人工智能(AI)上还是网络安全性。游戏开发者和玩家常常是前沿计算机技术的最早的采用者。由于他们的创新天性,游戏不再是由大型采购公司控制的技术产品——游戏领域总是有充足的空间给那些在这方面有天分的单个创新者。

手机游戏的盈利主要是由于它们的涉及面很广。手机已经与现代生活方式紧紧地结合在一起。他们是最普遍携带的个人用品中仅次于钥匙和钱包的东西。传统的台式机游戏将目标锁定在低级趣味的人和青少年身上,而手机游戏则每个人都可以访问的到——随时,随地。尽管每个手机游戏都不贵,但是巨大的使用量(如:每人每星期一个新游戏)将使得这个市场商机无限。但是,对于开发者来说,将控制台游戏迁移到手机游戏工程很大。因为他们所面向的对象、生活方式和分布式模型都有着极大的区别。

一个成功的手机游戏大多具有以下特征:

·易于学习: 既然手机游戏面向的是普通消费者而不是计算机专家,那么他们不可能深入的学习游戏技巧。消费者不会花几个小时去研究一个3元的手动操作的游戏。保持游戏的简单是最基本的要求。

·可中断性: 多任务处理是手机生活方式的基本特征。手机用户常常在任务(如等一个电子邮件或者等车)之间有一小段时间。而游戏、日历管理、通讯和工作数据访问使用的是同一个设备。所以一个好的手机游戏应该提供短时间的娱乐功能,并且允许用户在游戏和工作模式之间顺利切换。

·基于订阅:手机游戏的盈利成功取决于他们巨大的使用量。一开始开发和设计每个游戏都是昂贵的。如果一个手机游戏开发者要赢利的话,重要的是:同一个游戏引擎,多个标题,基本的故事情节类似。基于订阅的游戏是不断产生收入的最好方法。

·丰富的社会交互: 不管一个游戏设计得多好,只要玩家找到了它的根本模式或者玩完了所有的游戏路径很快就会厌烦这个游戏。对于一个基于订阅的游戏,重要的是与别的玩家合作以增强所玩游戏的智力和随机性。在今天纷繁复杂的多玩家游戏中具有丰富社会交互的游戏证

明是成功的。

·利用手机技术的优点:巨额的手机技术研发费用都花在提高设备和网络的可用性和可靠性上面。因此,手机设备硬件和网络协议与桌面/控制台世界(如全球定位系统(GPS)扩展、条形码扫描仪、和短消息服务(SMS)/多媒体信息服务(MMS)通讯)有着非常大的差别。好的手机游戏应该利用那些更新的设备特征和网络基础设备的优点。

·无违法内容:既然所有年龄/性别的人群都玩手机游戏并且常常在公共/工作场合,就应该避免明显的暴力或者色情内容。

1.3 任天堂(Nintendo)的8位FC机器和Battle City背景介绍

FC(Family Computer)主机在欧美又称Nintendo Entertainment System(可译作任天堂娱乐平台即NES)。FC主机在游戏业界造成的巨大冲击众所周知,这款主机在当时事实上几乎占领了世界各地多个国家的整个游戏市场,并使得逐渐没落的北美游戏市场再度复苏。这款主机的性能比当时的多数主机都要强大,而价格上却便宜得多。主机所采用得处理器为CMOS 6502,一款已经淘汰的70年代中期产品。由于其价格便宜且极易使用,经过任天堂的改造后又焕发了全新活力。6502 芯片cpu 主频为8 bit,12 MHz,内存8k,画面52色,同屏最多显示其中的13色,声音2个矩波,1个三角波,1个杂音,1个PCM音频(见图1-2)。Battle City是其发售卡带中的一款力作,设置了35个关卡,可以双人操纵,画面设置了若干种类的建筑物和阻挡物,以消灭所有敌人为通关条件,并有接宝物等增加游戏效果的设置,画面精美,音效杰出,在PC机的80386处理器仍未面世的当时,能在硬件上运行这样的2D 程序不得不令人惊叹,难怪常有人说游戏程序是最大限度发挥硬件水平的载体。其游戏界面如图1-3所示。

1.4 本章小结:

引言和第一章中介绍了手机在无线应用方向的当今概况,并介绍了游戏业务在当前社会的发展潜力。分析了J2ME在手机软件开发中起的重要作用,描述了本论文的相关背景。

第二章开发环境及相关技术的介绍

2.1 开发环境

操作系统:Microsoft Windows XP

程序语言:Java 2

开发包:Java(TM) 2 Standard Edition (build 1.4.1_02-b06) Sun Micro. J2ME Wireless Tool Kit 2.1

IDE: Borland Jbuilder 9

2.2 Java语言的特点

1. 平台无关性

Java引进虚拟机原理,并运行于虚拟机,实现不同平台之间的Java接口。使用Java编写的程序能在世界范围内共享。Java的数据类型与机器无关。

2. 安全性

Java的编程类似C++,但舍弃了C++的指针对存储器地址的直接操作,程序运行时,内存由操作系统分配,这样可以避免病毒通过指针入侵系统。它提供了安全管理器,防止程序的非法访问。

3. 面向对象

Java吸收了C++面向对象的概念,将数据封装于类中,实现了程序的简洁性和便于维护性,使程序代码可以只需一次编译就可反复利用。

4. 分布式

Java建立在TCP/IP网络平台上,提供了用HTTP和FTP协议传送和接收信息的库函数,使用其相关技术可以十分方便的构建分布式应用系统。

5. 健壮性

Java致力与检查程序在编译和运行时的错误,并自动回收内存,减少了内存出错的可能性。Java取消了C语言的结构、指针、#define语句、多重继承、goto语句、操作符、重载等不易被掌握的特性,提供垃圾收集器自动回收不用的内存空间。

2.3 关于JBuilder9

JBuilder是目前最好的Java开发工具之一,在协同管理、对J2EE和XML的支持等方面均走在其他产品的前面。JBuilder是遵循Sun公司J2EE标准的可视化集成开发工具。Jbuilder是一种处于市场领先地位的跨平台环境,主要用于构建具有行业实力的企业Java应用程序。JBuilder集成了Borland公司开发工具系列的优秀特性,使得使用过C++Builder,Delphi的程序员很容易的过度到JBuilder的开发环境当中。由于Java技术的发展迅速,经常有新的组件推出或新的错误修正,致使JBuilder的版本升级很快。当两年前还是JBuilder6时,现今已推出了9、10的版本。

2.4 关于Wireless Tool Kit

WTK(Wireless Tool Kit)是Sun公司针对J2ME推出的用于手机和Palm等移动设备的开发包,是除手机厂商的专用开发包外唯一的手机模拟器开发包。它通用性高,开发出的应用程序可保证能运行在大部分设备上,而不像专用厂商具有一定的不兼容性。虽然它没有强大的功能和完善的调试手段,但它提供运行模拟器的最基本组件,是其他IDE需集成采用的必备元素。

2.5 Java Appication Manager

手机中负责调配程序运行资源的管理后台是Java Application Manager。它所使用的传输媒体可以是红外线、网络、以及其他可用来传输的媒体。Java Application Manager 会从网络上下载代表该Application Suite 的JAR 档,接着在手机上安裝此MIDlet Suite,然后在手机开始执行该应用程序。整个详细的运作流程如图2-1所示。

2.6 本章小结:

第二章介绍了Java语言的特点、本程序的开发环境及其相关工具的原理和使用。

第三章程序结构、思想和相关技术

3.1 本程序需解决的有关技术问题

1. 游戏程序是一项精度要求很高的程序系统,因为其代码利用率很高。一个实时运行的最终作品,每秒都会运行成千上万行程序,绘图事件、键盘事件都会以极高的频率在后台等待响应,若有丝毫的差别都将很容易导致程序在运行不久后可能出现严重错误,甚至死循环。

因此,其逻辑设计应当相当严谨,需将所有可能发生的事件及意外情况考虑在设计中。

2. 游戏中为了美观,适用性强,可能需要采用外部文件引入的图片贴图,有关贴图,在MIDP2.0中提供了用于增强游戏功能的game包,使得解决静态或动态、画面背景、屏幕刷新的双缓冲等都有较好的解决方案。

3. 己方坦克的运行可以通过键盘响应事件控制,但敌方则因为是自动运行,就需要有一定其一定的智能性;同时,出现在屏幕上的敌方可能会有较多的数量,这需要为每个敌方开辟一个线程以便能让其独立运行。Java的多线程能力为实现这样的游戏提供了可能。敌人坦克的运行算法也需要进行适当的设置,以免游戏过于简单,单调。

4. 对于双方坦克发出的子弹的控制也需要对其跟踪控制,子弹也需要处在独立的线程中。敌方子弹仅需要扫描用户坦克,而用户坦克需要在每一步扫描所有的敌方坦克。这需要对所有的对象有较好的控制。另外,子弹在运行过程中也需要实时扫描是否碰撞到了相关障碍物或屏幕边界。如此过多的线程同时在本来效率就不高的KVM虚拟机上运行,也许会导致程序的缓慢。

5. 双方的坦克在前进时也需要考虑到是否碰撞到相关物体或对方坦克,以免重叠运行,造成许多物理上不可能的情况,缺乏真实感。每一次刷新页面、每前进一步都需要将所有的周围环境都进行扫描。

6. 游戏的结束、开始、动态信息画面作为构成一个完美程序都是必不可少的重要部分。良好的用户界面更是吸引用户的硬指标,相关的美术构图也需要有一定的考虑。

7. 游戏的地图不可能通过绘图来解决。否则,不仅难于控制和处理过多的元素,也会因过多的大型图片而不能限制程序的大小,失去手机上程序的原则和Java的优势。同时,地图关卡不宜保存在手机有限的内存中,而最好采取外部文件的读入读出方法。

8. 用户运行游戏时需要有分数记录的可能。如何采用合理的记分标准,需要进行适当的设计。记录分数的存储方式也需要有较好的解决方案。手机中由于处理器和内存空间、存储空间都十分有限,其数据库系统与普通PC大相径庭。其数据库结构较为简单,被称之为RMS 系统。

9. Java是基于虚拟机的半解释型编译系统,其执行效率较C++等完全编译后的程序会低很多,程序如果不进行精简和优化,将可能导致运行的不流畅。除开发过程中对结构上的控制、变量的使用、算法的优化等优化外,还可以使用混淆器(Obfuscator)进行程序打包后的优化。以上相关技术细节和整体流程将分别在以下小节阐述。

3.2 程序流程

MIDlet suite是MIDP应用程序的最小单位,JAM负责将手机内的MIDlet suite以图形化的方式呈现,让用户能够选取欲执行的MIDlet suite,一旦选取了某个MIDlet suite,操作系统就会激活KVM执行里面的MIDlet。MIDlet及相关的支持类组成了MIDP应用程序的实际内容。

每个MIDlet都必须继承javax.microedition.midlet.MIDlet这个抽象类。在MIDP规格中定义了MIDlet的生命周期,以及可以存在的三种状态,包括Paused、Active以及Destroyed,每一个MIDlet在任何时刻只可能处于其中的一个状态。这三种状态的转换关系如图所示:

本程序采用面向对象的设计模式,对游戏中的所有物体赋予对象的概念和属性。运行程序后允许用户选择执行选项菜单,在开始游戏后将先从外部文件载入地图文件,对背景的所有物体进行绘图。在主程序运行的线程中,画面刷新将以一定的频率采用双缓冲技术对屏幕重绘,实时反映整个游戏的进行状态。用户控制的坦克运行在主线程中,随屏幕刷新的频率而步进。敌方坦克将在游戏开始时逐渐新增线程,每增加一个敌方对象就新增加一条线程,一旦线程

数满到最大值(本程序暂设置为6),就不允许敌人再继续出现。用户坦克自诞生之时起将拥有一发子弹,子弹虽然开在单独的线程中,但运行结束后(比如撞到相关物体或敌方坦克时)并不结束子弹对象,只是将其线程终止。用户再次发射子弹时只是将终止的线程再次激活。在屏幕重绘的主程序中,将在每次的循环中判断若干事件。如:用户坦克的生命是否已完全用尽,敌方坦克数是否已经为零,屏幕上的坦克数量是否少于仍剩下的坦克数量等。以便程序进入相关的分支执行相关的反应代码,结束游戏或统计分数等。主程序流程如图3-2所示:

程序为需要完成独立功能的需显示的模块设置了单独的类。TankMain类是继承自MIDlet的控制主程序启动的首先被载入系统的部分。载入程序后首先启动的是程序介绍的信息画面。闪过后载入StartChoice类,为用户提供可选择的选项。在选择开始后,将运行BattleCanvas 类中的总流程控制。它决定了游戏何时该结束,何时分配敌人数量,GameOver字样的闪现规则,地图的绘制及整个游戏的调度。

图3-3是程序中类之间的UML分析图。敌方坦克与用户坦克的相关功能和具体行为分别定义在EnemySprite和UserSprite类中,它们都继承自TankSprite公共类,以简化程序的代码、理清结构。

在每关的结束或死亡后都将载入ScoreScreen类,统计当前的分数。如果已死亡或完成所有的关数,程序将用户所得的分数记载到RMS数据库中,进行永久性保存。载入过程中将对所得分数与以往历史比较,放置到合适的位置中,形成排序。

3.3 绘图与MIDP2.0新增的GameCanvas包

3.3.1 提供低级绘制的Canvas类

为了能有程序开发人员控制接口的外观和行为,需要使用大量的初级用户接口类,尤其在游戏程序中,几乎完全依赖的就是Canvas抽象类进行绘图。从程序开发的观点看,Canvas类可与高级Screen类交互,程序可在需要时在Canvas中掺入高级类的组件。Canvas提供了键盘事件、指点杆事件(如果设备支持),并定义了允许将键盘按键映射为游戏控制键的函数。键盘事件由键代码指定,但这样控制游戏会导致缺乏通用性,并不是每个设备的键盘布局都适合游戏的操作。应当将键代码转换为游戏键的代码,以便硬件开发商能定义他们自己的游戏键布局。本程序中,操纵用户坦克运行的按键都定义为游戏控制键,这样便能适应所有的机器。

3.3.2 Graphics类

Graphics类提供了简单的2D绘图功能。它具有24位深度色彩的绘制能力,以三原色分别各占一个字节表示其颜色。程序只能在paint()函数中使用Graphics绘制,GameCanvas可调用getGraphics()函数直接绘制在缓冲区上,可以在任何时间请求传输到前台。其对象会被传给Canvas的paint()函数,以便最终显示。

3.3.3 PNG格式

PNG(Portable Network Graphics)格式是MIDlet唯一支持的图象格式,PNG具体格式由PNG Specification,V ersion 1.0定义的。PNG格式提供透明背景的图象,这对绘制游戏画面和被操

纵主角极有帮助。坦克之间或与障碍物碰撞时就不会因为背景有特定的颜色,显示出的效果像贴上的图片而缺乏真实感,物体之间轻微重叠时最上层图片也不会覆盖超过其有效象素外的部分。

PNG格式图片中包含许多定义其图片特性的冗余部分(Chunks)。这些代码包含在每一个单独的png格式图象中,然而如果将多个png图象合并在一张幅面稍大一些的整图中,多个chunks 就可以得到精简,图片的大小可以得到控制。使用Image类中的createImage函数可从整图中分割出所需要的元素。在Game包中的TiledLayer和Sprite类都整合了这样的功能。本程序中的地图元素都集成在一张tile.png图片中,实现了方便的管理和程序体积的精简。

3.3.4 Game包中的新功能

MIDP自2.0以后新增了Game包,为游戏的开发带来了极大的便利。地图绘制、主角的动态显示、按键的检测、图层的控制等游戏专属的特性都得到了在移动设备上最大的发挥。

LayerManager(以下简称LM)提供控制整体画面层的控制。它包括了一系列自动获取了代号和位置的层,简化了各层加入游戏画面的过程,提供了自动排序和绘制的能力。LM存储了一个层的列表,新的层可以用append函数附加、删除和插入。层的序号相当于坐标的Z轴,0层表示最接近用户视觉,层数越高,离用户越远。层号总是连续的,即使有中间的层被移除,其他层的序号会作相应的调整以保持整体的完整性。LM中的View Window 控制着与LM相对坐标的可视区域。改变View Window的位置可以制造出滚动屏幕的效果。本程序中所有的地图、坦克都采用LM控制,敌方坦克的生成由附加一个EnemySprite对象得到。唯有界面右侧的计分栏由Graphics类绘制。

Sprite类是继承自Layer的用于存储多桢的基本可视元素。不同的frame可交相显示,构成动态的效果。图片可翻转、颠倒、由一个主角图片就可以方便的得到所有方向的显示状态,相比原先只能使用Canvas绘图,需要将所有方向的主角图象都绘制在png图象中简化了许多。Sprite也可以从整合的图象中读图,读图时将把大图分解为若干等宽等高的小图。每个小图按照其排列顺序有相应的序号,在程序中调用其序号,就可以绘制出相应的图片。本程序中的双方坦克、子弹都由Sprite继承得到。在有些情况下,控制主角的翻转,尤其是多幅图片配合显示的过程,如果将多图的共享定位点设置在通常的左上角,将很不容易控制,因为许多翻转都是以其他点为参考电的(比如,中心点)。由此,引入参考点的概念。参考点由defineReferencePixel函数确定未翻转图片状态时的坐标。默认是(0,0)点,如果需要,可将参考点设置在画面边界之外。本程序中的坦克的参考点定义在图片正中,以便简便的实现转向等功能。子弹的参考点设置在子弹底部的中心,因为子弹一出炮筒的时候紧挨着坦克的象素就是其底部中心。

TiledLayer是有一组图象格元素(grid of cells)组成的整块虚拟图象。该类使不需要高分辨率的图象就能创建大幅图面成为可能。这项技术通常应用在2D游戏平台的滚动背景的绘图。一块整图可被分割成等大小的图象格,每块格有其对应的序号,按照行列递增。多块格可由大块同时替换组合而模拟动态的背景,这不需要逐块替换所有的静态图象格而显得非常方便。

本程序中的地图即为游戏背景。每块障碍物都有其响应的代号,其中,用户需保护的总部因为体积稍大,使用了四块图象格显示。地图背景分为20*22个图象格,每个格使用一个字节表示其中的障碍物,图象文件存储在外部文件中,以16进制的整数串表示,因此每个地图的大小为固定的440字节。如果整块地图均由绘图产生,将导致体积迅速增加,且对坦克与障碍物的碰撞也难以检测。J2ME中并没有J2SE中的File类,获取外部文件的手段很有限,仅仅在Class类中提供了一个getResourceAsStream函数,将外部文件获取为输入流,再由

InputStream的继承类读出。

3.3.5 有关绘图的一些技术

在没有MIDP2.0前,进行游戏绘图一般需要手动编程使用双缓冲。需要在paint()方法内所想要画的图形画在一张预先准备好的背景,等所有绘图操作都完成后再将背景的数据拷贝到实际的屏幕上。Image类提供了一个建立背景的静态方法createImage(int width, int height),再利用getGraphics()方法取得属于这个背景的Graphics对象,所进行的绘图操作都会作用在背景上,等到全部的绘图操作完成后,再调用drawImage()方法将背景的数据复制到实际显示的屏幕上。

这样的技术在绘制动画时特别有用。绘制动画时经常需要不断地更新画面,而更新画面的操作就是先将屏幕以fillRect()的方式清除,再将下一张图片画在屏幕上,然而反复的清除及重绘会造成屏幕的闪烁现象(flicker),因此使用双重缓冲的好处就是在背景进行这个清除及重绘的操作,再将完成的绘图拷贝到屏幕上,由于用户看不到清除的操作,因此就不会出现闪烁的现象了。不过在某些MIDP的实现上已经加上了双重缓冲的支持,因此在处理前应先利用Canvas类的isDoubleBuffer()方法来判断。

3.4 坦克的控制和敌方的智能运行

GameCanvas中提供了与以往MIDP1.0不同的键盘采样功能。Canvas类中采取响应键盘事件的方法,每次执行周期时会读取keyPressed函数中需执行的代码。这样的机制并不适合某些游戏场合。在某些不支持keyRepeat功能的设备上,反复执行的按键,比如发射子弹,将不能因为长时间按压而自动重复,这样就需要用户高频率的手动击键,这在操纵空间非常有限的移动设备上是非常困难的。同时,事件的执行周期也并不一定适合游戏的场合,也许需要更高频率执行的按键却只能在指定的周期内规律的响应。对此,针对游戏的开发,Game 包提供的键盘状态功能将显得十分有效。

GameCanvas提供getKeyStates函数可获取当前键盘上的信息。将以位的形式返回键盘上所有键的按与释放的状态,当bit为1时,键就是被按下的状态,为0时则为释放状态。只需要此一个函数的返回值就可以返回所有键的状态。这保证了快速的按键和释放也会被循环所捕捉。同时,这样的机制也可检测到几个键同时按下的状态,从而提供斜向运行等相应功能。

敌方按照规则不能和用户坦克重合,则它每行走一步就需要把用户坦克扫描一次,判断其是否碰撞到了用户的坦克。Sprite类中提供了collidesWith函数,用于判断是否与某个TiledLayer、Sprite、Image的对象有图象上的重合(即游戏中的碰撞)。然而不能仅仅将用户坦克作为其Sprite参数传递给敌人的类进行判断。因为如果发生碰撞,collidesWith成立,则两辆坦克已经发生了图象重合,违反了规则,甚至若再进行collidesWith判断的话,其结果将永为真。为了提前预知碰撞,可以将所有坦克的碰撞范围设定为一个比坦克图片稍大一些的矩形,此矩形仅在坦克前方比坦克图形多出一个象素。在多出的11个象素中,按照每个象素依次检查此象素是否于外界发生碰撞,如果不是按照象素检查,则当坦克与障碍物错位并同时与两种物体接触时将有可能忽略检测其中的一样物体。这样,就可以提前一步判断。如果发生碰撞,则坦克应当选择掉转方向,此时,两辆碰撞的坦克又因为其矩形区域不重合而不符合collidesWith的条件,就可以继续正常运行了。

敌方坦克由于需要具有一定的智能性,以便对玩家攻击,使之具有一定的可玩性。敌人可以

自动行走,但是应当在以下适当的情况下转向:首先是是否超出界面的边界,其次是是否与地图障碍物发生了碰撞,再次是是否与用户坦克发生了碰撞。需要指出的是,当发生阻碍不能在不变方向的情况下继续行走时,并不一定立即需要采取转向的对策。如果一定发生转向,试想,当敌方碰到玩家时,如果它立即转向,将不会对玩家发射射向他的子弹,就不构成任何威胁,当然,也不能永远不转向。本程序设置为:当碰撞到障碍物或边界时立即转向,但碰到玩家坦克时需要有一个等待的时间,这个时间由碰撞前随机取得的在某方向上的持续行走步数决定,当发生坦克间碰撞时,此随机数将在下一次循环前减少为原来的2/3,这样就实现了加快转向的时间,避免死锁在一个方向上静止的停留过长的时间。另外,坦克的发炮间隔和转后的具体方向都由随机数决定。坦克之间由以上道理也不会发生重叠,但当某坦克正从上方生成而正巧有另一辆阻碍在其生成点处,这将导致不可避免的重合。这是允许的,但需要对他们标注状态,即当坦克刚出现时暂时允许重合,一旦在某个时间他们脱离了重合状态,就不能在允许重合,如果不设置这样的判断,刚出现的坦克将会因为受到阻塞而永远不能前进,坦克将混成一团。本程序中并未使用过多复杂的人工智能算法,如有时间,将可能再此方面加以完善。

3.5 子弹的运行和控制

每一个坦克都有他自己的一颗子弹,这颗子弹在任何一辆坦克被构造时就一直存在,直至此坦克生命的结束,子弹的再次只是将屏幕上暂时掩盖的图象重新置于坦克炮筒才恰当位置,并使其显示出来,这与现实中每个子弹都是单独的个体有所不同。

子弹所需要完成的任务有:

它是一个继承了Runnable虚类的可运行单独线程的对象。在其出现在屏幕上的运行周期中,每一步都需要循环检测以下条件:

是否与某坦克发生了碰撞,即击中了这辆坦克。子弹使用的是象素级的碰撞检测,因为子弹的图片形状不规则,如果使用矩形碰撞检测,将有可能在子弹尚未接触到物体时就已返回碰撞的真值。分为两种情况,如果此子弹来自于敌方,将只检测玩家坦克,因为敌方之间的子弹必须允许可以透明的穿过,以保证不会在敌人之间发生子弹的消减。如果来自玩家,则每一步需扫描所有的敌方坦克,检查是否发生碰撞,这可能会花费不少的CPU时间。

其次,子弹之间需要检测是否碰撞。敌人之间显然,如上已经提过,不需要检测,但敌人与玩家之间应当可以互相消除子弹,以便在狭窄的路口中仍有存活的机会。玩家的子弹需要在每一步检测所有敌人的子弹的运行状态。这样较多的运算也将不可避免的耗费大量CPU时间。

子弹对不同障碍物将有不同的反映。对砖墙将有能力将其击毁,使之在画面上消失;对水泥钢筋将不能发生作用,子弹也不能通过;对于河流,坦克不可以通过,但子弹可以;对于草丛,子弹和坦克都可以通过。

3.6 RMS数据库系统

MIDP为MIDlets提供了一种永久存储和后来读出数据的数据库解决方案,被称为Record Managerment System(RMS),是一种类简单的基于记录的数据库。

很显然,手机上的数据库系统不可能有PC上的强大功能。微小的存储空间也限制了它们的结构不能过于复杂。RMS是专门针对移动设备的服务的。

RMS包中包括RecordStore类。在一个MIDlet suite包里的所有MIDlet都允许创建多个记录集,只要它们赋有不同的名称。当MIDlet包从平台中被移除后,所有与该包有关的的记录

集都同时会被移除。同一个包内的MIDlets可以直接互相访问它们的记录集,不同包内也可产生共享,但这需要有包的授权属性决定。访问模式会在准备提供共享的RecordStore被建立时被创建。访问模式允许私有使用或访问。

RecordStore的API采用了时间戳的概念,其长整型变量由System的currentTimeMillis()函数返回决定。Record store 每次被修改后都会自动在其属性上附加上时间戳,这为同步化引擎和程序的控制都极为有效。

记录是字节数组。开发者可以利用InputStream的派生类DataInputStream、DataOutputStream 以及ByteArrayInputStream、ByteArrayOutputStream将不同种类的数据类型打包,以字节流的形式发送和接收。

区别记录的唯一标记是他们的ID值,作为记录集的主键。第一项记录的ID是1,其后的每个记录ID递增。

Record是以字节为基本单位来存放的,所以所有要写入record的数据都必须先将其转为字节才能写入,从record所读出来的数据也是字节,必须将其转换为原先写入时的数据类型才有意义。

然而读取或写入的字节数组都只能代表一个字段的信息,如果需要读取或写入多个字段就必须要将数据转换成字节信息,并且提供适当的机制来分隔这些信息。主要有两种方法:

标记法。

将所有要存放的数据用字符串表示,但是在字段和字段之间以一个特殊的符号作为分隔。符号不能和字段内的数据相同的字符。

2.利用输入/输出流

这一种方法较上一种复杂,但是较为实用。方法一中所有的字段只能以字符串的形式存储,要对这些字段作进一步的处理非常麻烦。利用输入输出流可以写入及读取不同数据类型的数据,做法是在写入数据时先将一个DataOutputStream数据流对象串接到一个ByteArrayOutStream数据流对象,然后再依字段的数据类型用writeInt()、writeBoolean()等方法写入,最后把ByteArrayOutputStream内的元素数据写入record中。反之若要读取数据,则先要串接一个DataInputStream对象和ByteArrayInputStream,依字段的数据类用readInt()、readBoolean()等方法读取。

本程序中主要存放在永久区的内容为用户得到的最高分数的记录。一共可以存储10条最高分。每次有新的更高的记录就会插入进相应的位置,将最低一名排挤出记录。在输入记录前,要求用户在TextField框中写入他自己的名字。返回的getString可以将名字输送给字节流。因为每个记录包括用户名和分数,因此需要使用多字段的方式编入。打印到屏幕上时,记录ID号即为排名,因此将显示三项数据。

3.7 内存使用的最佳化

通常在MIDP应用程序的手机执行环境中,所牵涉的内存有下列三种:

﹡应用程序存储内存

﹡RecordStore存储内存

﹡执行时期内存(Java Heap)

其中前两种是持久性的内存,关闭电源后还能保持数据的正确性,通常这两种内存所能存储的容量是合并计算的,这个上限对每种手机都不一样,大部分在一两百KB内。在这样的情况下需要在不影响原有功能的情况下适当的缩减JAR文件的大小,除了可以克服内存空间的限制外,也能大幅度缩短下载的时间(费用也降低了),势必会有更多的人愿意下载所开发的程序。其方法有:

第一,就是尽量缩短命名的长度。在应用程序内,对于所建立的类、接口、方法及变量名而言,都需要赋予一个识别的名称,所命名的名称每多一个字符就会在类文件内多产生一个字节,对于一个较复杂的应用程序而言就会增加为数不小的数据量。所有这些可以借助混淆器来帮助实现。

第二是减少复杂的程序结构,为一些共同的行为建立一个抽象类(Abstract Class) 来表示继承的子类的共通性。

第三是减少图形数据的大小。将PNG格式的小分辨率图象合并在一张大的高分辨率图象中,由于减少了chunks,将比合并前的总大小减少许多。

3.8 混淆器(Obfuscator)的使用

Java 语言并没有完全编译成二进制可执行文件,编译出的.class文件是一种介于源程序和二进制之间的一中基于半解释的字节码,需要虚拟机来执行。它包括了所有的信息。然而这样会导致.class很容易被反编译为源代码,从而不能保护作者的知识成果。目前流行的如decode,JAD等反编译工具可以以很快的速度生成源文件。如果不加以施行有效的措施,将造成严重的后果。

由此引入混淆器的概念。混淆器将代码中的所有变量、函数、类的名称变为简短的英文字母代号,如果缺乏相应的函数名指示和程序注释,即使被反编译,也将难以阅读。

混淆器的作用不仅仅是保护代码,它也有精简编译后程序大小的作用。由于以上介绍的减少变量、函数的命名长度的关系,编译后也会从.class文件中减少这些冗余的信息。混淆后,体积大约能减少25%,这对当前费用较贵的无线网络传输是有一定意义的。

为了能与各种IDE集成,就像Java2 SDK一样,混淆器采用命令行参数的形式,以便可被其调用。目前流行的Obfuscator有RetroGuard等。

3.9 模拟器的相关调试

IDE整合的Wireless Tool Kit提供了许多在运行时监视运行状态的工具。包括内存状况的检测(手机上的内存空间十分有限,必须时刻关注机载内存是否大于程序所能使用到的最大可能的内存空间),网络状况的检测,运行函数的跟踪等。如图3-4,是内存跟踪测试随时间变化的调试器。其中,允许强制垃圾回收(Garbage Collection)。由于Java语言中,不像许多其他的如C++语言,不需要指定回收函数中特定不使用的资源,资源回收机制将自动清空无效变量占用的空间。在程序运行中也可以调用System类的gc()函数手动收回废弃的内存。

3.10 本章小结:

第三章中介绍了程序的流程、相关技术的思想及其在本程序中的应用。分别对绘图、数据库、游戏基本算法等做了详细叙述。具体算法的代码实现和详细流程将在下章介绍。

第四章程序分析和具体实现

4.1 游戏进入前的选择

每个MIDlet程序都必须有一个主类,该类必须继承自MIDlet。它控制着整个程序的运行,并且可以通过相应函数从程序描述文件中获取相关的信息。该类中拥有可以管理程序的创

建、开始、暂停(手机中很可能有正在运行程序却突然来电的情况,这时应进入暂停状态。)、结束的函数。

进入时,首先载入画面的不是游戏运行状态,而是提供选项,当再次选择Start Game时才正式运行。运行画面如图4-1所示。因此,在TankMain的构造函数中分配了StartChoice类,即选项画面的内存空间。在startApp()函数中,随即调用了Displable的setCurrent()函数将当前屏幕设置为startChoice。在显示高级用户界面前,建造了一个Alert类。Alert对象用于显示提示、警告等告之用户信息的临时闪现的屏幕,它可作为setCurrent的参数,提前显示在最终需要显示的屏幕前。当将FOREVER作为Alert的参数时,将永久显示,直到用户点击相应按钮手动结束。但是当显示的画面元素超过一屏大小时,将自动转换为永久状态。在此,由于贴在Alert上的图片大小超出了其范围,故已成为永久状态。效果如图4-2所示。startChoice继承了接口commandListener,这样,就可以使用高级界面的Command按钮。继承了commandListener的类必须拥有commandAction(),以决定对按键采取什么样的行为。即按钮事件触发后需执行的函数。在设置好commandlistener后,需要调用setCommandListener()以将按钮事件激活。键盘事件中,可用getCommandType()返回的Command类型来确定选择的是什么按钮。

startChoice继承了List类,用于显示列表选项,使用其append()函数可将选项加入到列表中。getSelectIndex()可检测到选择的项目的序号,序号从0开始递增。其中,当选择第一项时将载入正式游戏画面BattleCanvas类,第二项将显示帮助信息(效果如图4-3),第三项则是重新显示与作品和作者相关的logo画面。

4.2 主游戏逻辑及其涉及到的若干类

BattleCanvas主管着所有类之间的协调,决定何时死亡,何时分配新的敌人,及控制敌人出现处的闪光图标、游戏结束后的动态Gameover字样。它运行在独立的线程中,以恒定的频率刷新画面。刷新速度需大于30/秒才能使画面显示因人眼的暂时停留效应流畅运行。本程序设置为20毫秒。其主逻辑如图4-4所示。

程序中建立了另外的两个类,分别表述了敌人坦克和玩家坦克的功能。它们分别为:EnemySprite和UserSprite。这两个类均在BattleCanvas中建立了对象,以便进行统一调度。BattleCanvas包括了LayerManager,这样所有静态和动态的图象都不需要手动刷新,只需要在LayerManager中加入所有的需控制的元素,再统一由LayerManager刷新即可。因此,有必要在其中创立一个LayerManager的对象。

其他,如Sprite类的gameover字样、记分统计画面也都需在此主逻辑中建立相应对象。还需保存的变量有,游戏开始时间、结束时间(用于统计分数)、敌人的总数、屏幕上敌人的数量、下一个敌人需要出现的位置(总共允许在三个不同的位置出现,分别位于屏幕的左、中、右方)、游戏是否已成功结束或是否已死亡。

构造函数中,需初始化地图。地图实际即为TiledLayer的一个对象,可调用setCell设置其具体的图象格内容。地图由外部文件读入。外部文件分别命名为level*.png,利用MIDP 中唯一获取外部文件为程序内资源的getResourceAsStream()函数将地图文件读入程序。在创建了InputStream类的map对象后,使用read()函数可将流中的下一个字节读出,并返回此字节代表的整数。每个整数代表一种障碍物。用二维循环将读出的每个整数,通过setCell()将整幅地图画出即可。地图文件可用十六进制的文本编辑器生成,如本程序使用的Ultraedit。绘出地图后,可用LayerManager的append()将地图放置在第一层。这是很有必要的。因为地图上的障碍物之一——草,在坦克运行中时是必须处于坦克的上层的,否则将失去真实性。为此,地图必须首先载入。

由于敌人将依次出现在屏幕上,同时出现的数量应当受到控制。本程序设置为6。所以在构造函数中,也应当分配6个EnemySprite对象的内存空间。构造坦克时,将把坦克的png图片作为参数传递给EnemySprite和UserSprite,BattleCanvas中创建坦克仅调用createEnemy()和createUser()实现。

在构造函数自己调用了线程的start后,程序将开始循环运行,直至跳出while的循环。每次循环中将检测是否死亡,屏幕上坦克的数量,是否该过关统计分数,检测用户输入的按键、重绘整个屏幕及回收垃圾内存(Garbage Collection)。

当敌人坦克完全死亡时(enemyNum为0),需调用System类的currentTimeMillis()赋值给结果的时间。接着调用setCurrent()显示统计分数的画面,为了进入下一关,统计画面只是停留四秒,就重新转回BattleCanvas画面。当然,如果当前已是最后一关,就不会再转回。进入下一关时,许多变量需要重新被初始化,如地图的绘制、敌人出现位置的重置、敌人的数量、玩家坦克的当前位置。

如果游戏未结束,则需判断屏上坦克是否已小于还剩坦克的总数,如果是这样,就需要再提供一辆坦克。提供新坦克之前,在屏幕上设置了一个专用指示的闪光符号,它继承了Sprite,运行在单独的线程中。以在两秒钟内反复闪现两次为一个生命周期。当它闪光完毕后,敌人就会从闪光位置出现。这样可提示玩家具体敌人将在什么时刻出现,以便做好准备。闪光位置设置了三处坐标,由于敌人不能同时出现,便设置了enemyOutDelay的倒数计时,每次屏幕刷新会减少一次计数,直到为0时就准备一辆坦克。本程序设置的两次坦克出现的最小间隔为2秒。

如果玩家已经死亡,就需要使用LayerManager的insert()将gameover字样插入到最上层,以免被其他物体覆盖。效果如图4-5所示。

在检测用户输入的input()函数中,当按方向键时,玩家坦克就将向不同的方向运行,这调用了UserSprite的go()函数;当开炮时,就调用其fire()函数,作出相应的行为。

在出现正式画面前设置了一个loading state*字样的单独屏幕,调用了loadinglevel()函数,并停滞了1500毫秒,提示用户做好准备。效果如图4-6所示。

在绘图的render()过程中,除了要重绘坦克、地图、子弹外,还会在右边空白处绘出一个生命统计栏。并反复使用Graphics的drawLine()、drawImage()绘画出一个三维的效果,增强视觉感。该三维栏的上方为白色,下方为黑色,就创造了立体感。在每次刷新绘图页面时,应使用GameCanvas的flushGraphics()将屏幕后台的缓冲区内的图象刷新到前台来。

在允许敌人出现前,需要检测给即将出现的敌人分配一个数组序号。在程序中调用了getNullEnemyIndex()进行测试,当返回为-1时说明没有序号可以分配,否则,将返回空的序号。

游戏的最终运行状态如图4-7所示。

4.3 坦克的共同行为

在TankSprite中定义了所有坦克(包括敌方坦克和玩家坦克)的共同行为和属性。EnemeySprite和UserSprite都继承了该类以简化结构。在transformDirection[]中定义了坦克四个方向分别应将原始图片旋转的角度,分别为TRANS_NONE,TRANS_ROT90,TRANS_ROT180,TRANS_ROT270,以便在后来的setTransform()中将这些常量代入。构造函数中创建了每个坦克必须拥有的一颗子弹,这些子弹就将只跟随自己的坦克调动。

为了能提前预测碰撞,调用了defineCollisionRectangle(0,-1,11,12)将碰撞矩形向前设置了一个象素,具体原理见第二章。

在setBulletDirection()中,将根据坦克当前的方向确定子弹出膛后的方向,其中setRefPixelPosition()将子弹的参考点设置在其未变形状态的底部,setXY()将其放置到炮口的位置,setTransform()将其图片方向转到需要使用的位置。

canPass()函数将返回坦克是否能够向前前进,考虑到的因素有边界、障碍物。它返回一个boolean值,提供给go()函数,做进一步的判断。getTileIndex()将检测传递来的象素处是什么类型的障碍物,它将象素除以8(即障碍物的象素宽度),取整,再通过getCell()得到。在得到障碍物属性后,判断其序号是否与草相同,或是否为空(序号为0)。因为所有的障碍物中只有草不会阻碍坦克的向前运行。

4.4 玩家坦克的功能属性

构造函数中需要将坦克方向设置为向上,因为刚出现时就是这样的状态。当开炮时,调用BulletSprite的setLayerManager()将子弹与layerManager联系起来。需要联系的还有自身坦克、地图。这些都由坦克传递给子弹。因为子弹是属于坦克的,它的属性需要跟当前的坦克保持一致。接着使用append()将子弹贴到layerManager上显示出来。最终调用其start()开始子弹自己的线程。子弹一旦开始运行,就脱离了当前坦克的控制,直到其生命周期终止。无论子弹是属于敌人还是玩家的,它都必须记录自己的来源和攻击的对象。在玩家坦克发射的子弹中,就必须将攻击对象设置为所有的敌人。这样,它才能有扫描的目标。在setShootCheck()的参数中,传给子弹的是敌人的数组,子弹的对象就被确定了。

die()、resetPosition()、getLife()都是很简短的函数,但却提供必不可少的功能。他们可被外部调用,以取得生命值、死亡记数、重置位置。

在go()函数,每个方向在走前都须用if (canPass(UP)&&!collidesEnemy())

检测是否可以行走。canPass()检测是否有障碍物及是否到边界。collidesEnenmy检测是否前方有坦克阻碍行动。当可以行走时,就在当前方向的坐标上增加或减少一个象素。

在collidesEnemy()函数中,将有一个for循环按照敌人数组的序号依次检测6次。有一点非常重要:在检测前,需要将敌人的检测矩形区域设置为与原来图片一样大小。否则,当玩家向上走,而有敌人从左方向右走,并且已经碰撞到玩家坦克时,玩家坦克会因为被判定已与敌人发生碰撞而不允许前进。事实上,敌人坦克此时并没有阻碍玩家前进。这样的判断必须排除在考虑范围外。当然,在设置完成后,必须将将检测区域设置回原先的状态,否则敌人在往后自己的检测中将发生错误。

4.5 敌人坦克的功能属性

由于和UserSrite同属于一个TankSprite的继承类,其功能就与UserSprite有很大的相似之处,但也有其自身的特别属性。其主要功能流程图见图4-8。

首先,EnemySprite继承了Runable接口。因为敌人的运行是自动的,需要有设定的程序让它可自己控制,而不像UserSprite完全通过每次输入的键盘信号来做出反映。因此,它可以运行在单独的线程中。

setEnemyShootCheck()函数与UserSprite中的一样,设置了攻击的对象,并且此函数将继续把参数传递给自身的子弹,以便子弹可以识别攻击对象。此函数由BattleCanvas调用。getRandomDirection()以当前系统时间作为种子,调用了Random类的nextInt()产生一个随机的整数,此整数取除4的余数的绝对值作为随机的方向。

Random random=new Random(System.currentTimeMillis());

return Math.abs(random.nextInt())%4+1;

此时返回的值的范围就确定在1~4之间,正好对应四个方向。将他们代入需要使用方向的函数中就可以使用了。

getRandomStep()的原理类似:

Random random=new Random(System.currentTimeMillis());

return (Math.abs(random.nextInt())%4)*50;

只是需要乘以每秒会刷新的屏幕的次数。这样就相当于允许在某一个方向运行0~3秒钟的时间。

每个敌人还需要拥有一个内部的所有敌人的数组元素。这样,它们才可以自动检测自己是否与同伴发生了碰撞,以便采取躲避、转向等行动。

collidesWithOtherTank()将检测是否与其他坦克(包括敌人和玩家)。一个循环将依据敌人的序号查找5次。if(i==number)break ;语句将避免检测到自己,永远返回真。collidesInOtherTank()虽与上面的函数很相似,但仍有一些细微不同,那就是不需要在检测前设置被检测方的矩形区域。因为不需要进行预先检测。此函数用来检测是否在刚出现时就与其他坦克发生碰撞的。如果一出现,出口就被堵死,显然,不能永远不出现,那就应采取其他的办法,否则两辆坦克将因为都处在碰撞状态中而无法移出。

在运行的线程中,需在每前进的一步骤中循环做下列事件:

如果坦克已死亡,立刻退出。(由boolean值destroyed决定)。

如果不是刚出现(由isBeginner决定),判断是否与将其他坦克发生碰撞,就向当前方向前进一步骤,否则,将需要循环检测的当前随机步数减少为原先的2/3(为了加速离开的时间)。如果刚出现,就直接走一步,具体如何行走将在go()函数中决定,并且此go()与UserSprite 中的有所区别。

当随机发炮数减少到0时,就进行发炮的动作。发炮后应立即重新赋值给随机发炮数,以便重新倒数计算。

当所有的步骤走完后,因为需要转动方向,于是,调用一次随机取得方向的函数再次获值。其他的随机值也应当重置。

在go()函数中首先检测是否正处于碰撞状态中,如果不是,就需要取消Beginner的状态,因为不需要Beginner这样的特殊身份,让别的坦克不检测了。

在运行在某个方向上,当确定为canPass时,应再检测是否为Beginner。如果是,就不应该受到其他坦克的影响而直接改变坐标,但若不是,就应当远地不动。

4.6 子弹的运行和控制

子弹继承了Runnable,运行在独立的线程中。它拥有一个很重要的变量,isFromEnemy。它标识了该子弹是属于玩家的,还是敌人的,这样可以控制子弹在脱离坦克管束后的运行状态中的行为。其主要功能流程图见图4-9。

checkHit(int x,int y)调用了getTileIndex(x,y)获取当前子弹击中的是什么障碍物,如果返回了false就表示没有击中任何东西。当击中了需要作出反映的物体时,就分别采取措施:击中草时,由于没有定义相关函数,就不会有任何反映,会重合在草上正常通过;击中砖块时,将产生爆炸,调用setCell将当前块置为空,并产生爆炸效果。爆炸效果由tileExplode(x,y)根据需要爆炸的坐标点生成,其中将一个Sprite图片在界面上闪现150毫秒。爆炸效果需要将图片insert进第0层,这样才不至于被其他景物所覆盖,爆炸结束后layerManager会自动相应调整。击中钢筋时,将只产生爆炸效果。

setShootCheck(EnemySprite enemySprite[]);setUserSprite(UserSprite userSprite);setEnemySprite(EnemySprite enemySprite)

都是将相关的坦克传入到子弹类里来,以便确认来源或攻击目标。

在线程的循环中while ( (x < 155) && (x >=5) && (y >=5) && (y < 171))作为循环的条件可以控制子弹出界的范围。这几项参数在编写时很容易出错。它们反映了象素级处理的技巧。如果程序在子弹已经到达X轴的155坐标时仍允许子弹继续运行,子弹将一次性向右运行2个象素,到达157点。在随后的checkHit(RIGHT)调用中,它将检测它是否在x+3点,即160点击中了某个障碍物,但是160/8=20。地图的tiledLayer对象中并不存在序号为20的块,最大只为19。此时ArrayOutOfBoundException异常就会抛出,程序终止运行。

子弹运行中,将用collidesWith(tiledLayer,true)测试是否碰撞上了地图。如果为真,就继续检测碰撞上了什么样的物体。这将针对四个不同的方向分别以象素级检测。如果击中了某样物体,那么checkHit自然会处理,子弹的生命周期结束,以break退出循环。

如果没有击中物体,就继续检测是否击中了某辆坦克。这根据子弹的来源分为两种情况。当来自玩家时,将首先检测所有的敌人发出的子弹,当发生子弹间的碰撞时,用户的子弹将被移除,虽然按照道理敌人的子弹同时也应被移除,但敌人子弹是运行在另一线程中的,应当由它自己来控制为好,用户的子弹只需要管理好自己的状态就可以了。如果没有和子弹发生碰撞,就检测是否与敌人碰撞,发生碰撞时,将敌人从layerManager中移除,并置为null,产生爆炸效果,敌人数量减少一位,敌人屏幕上数量减少一位。

如果是来自敌人的子弹,将同样检测与玩家子弹的碰撞,及与玩家坦克的碰撞如有碰撞,玩家生命数减少一位,位置重置。如果玩家生命已死亡殆尽,就需要在进行以上操作的同时将玩家坦克的位置放置到屏幕外的部分。因为layerManager的remove函数并不会真正将层移除。只是用户看不见而已。如果不放置到屏外,敌人坦克仍会被阻挡,子弹仍会再次击中用户坦克。这将会是很荒唐的场面。

为了能控制一辆坦克在同一时间只能发射一发子弹,在子弹生命运行结束时候,将调用userSprite.enableShoot()恢复坦克继续发炮的能力。因为在发炮期间,坦克的再次发炮的功能是被锁定的。

4.7 记分系统

记分系统的功能指定在ScoreScreen类内。采用的是手机专用的一种简化的数据库RMS。在BattleCanvas请求调入分数统计的屏幕时,将首先调用initRs()初始化一些环境变量。RecordStore.openRecordStore("score",true)创建一个名为“score”的数据库。随后将分别建立ByteArrayOutputStream 和DataOutputStream以便实现多字段的记录。首先将循环调用dos.writeUTF("NoName") 和dos.writeInt(0),将记录中的条目的用户名置为NoName,所有的分数置为0。score=baos.toByteArray()将所得的被写入的数据流输送到score的字节数组中。Score将被循环调用10次,将记录中的10个最高记录初始化。

getScore()函数得到所需要序号的分数。其中dis.readUTF() ,score=dis.readInt()将分别读出用户名和分数,然而前者读出后并不加以利用,因为在比较分数的过程中,并不需要用到用户名。使用它只是为了将记录的指针向后推移到可以读出分数字段的位置。

insertRecord()可以将当前刚刚得到的最高成绩记录到数据库的指定位置,将最后一名排挤出局。其中rs.setRecord(i+1,record,0,record.length)将把已读出的当前位置的记录写入到下一条中,当发现移动完毕后当前序号即为所需要插入的位置时,就再次调用dos.writeUTF(name),dos.writeInt(score),rs.setRecord(i,record,0,record.length),将记录写入。并将所有相关的InputStream的继承类用close()关闭,以便释放内存资源。

drawList()函数绘画出当前的屏幕分数。它将所有数据库中的数据依次读出,再使用drawString以固定的格式写出。效果如图4-9显示。

由于ScoreScreen类继承了Canvas,所以必须有paint()函数。在这个在刷新屏幕时(repaint()被调用)需要执行的方法中,设置了一个整形的duration,用来记录完成一关所用的时间。时间将根据BattleCanvas中的beginTime的差除以1000后取整决定。每关的分数被设置为100000/duration。因此完成的时间越短,得到的分数就越高。如果BattleCanvas.dead成立,就不将当前关得到的分数加入到总分的计算里,否则就调用totalScore=totalScore+levelScore 进行累加。

如果通关或完全死亡后,将提示用户按pass按钮跳过该屏。如果需要进入下一关,则进入本关统计分数的显示。效果如图4-10,仅停留4秒种,供用户快速参考后便会跳入下一关的起始画面。按钮由addCommand()加入,并设置了commandListener()确定按键事件发生后的动作。这是低级绘图屏幕与高级用户界面相结合的一个应用。当用户的分数达到一定的高度可以写进记录时,将调用inputName=new Form("Congratulations")创建一个新的Form类的屏幕,其中包括一个TextField,允许用户输入自己的姓名,这样使用getString就可以将输入读出,写入到记录中。

4.8 本章小结:

第四章中按照相应的步骤描述了所有关键类的具体算法实现,引用了相关函数进行了具体流程的解释,并对原理稍复杂的函数做了详细的分析。对游戏有关的各运行界面也做了展示。第五章总结

5.1 本程序的总结和展望

本程序设计实现了手机上以J2ME为平台的坦克大战游戏的开发,采用从外部文件读取地图、自动控制敌人坦克运行的方式进行控制,具有一定的可玩性和复杂性。经过了细心的调试和排错解决了绝大部分的问题。

但几乎每一个计算机程序都会有这样那样的不足,尤其是未经过精心维护的非商业软件。即使是作为操作系统的各种版本的Windows也时常会发生许多类型的错误和漏洞。本游戏程序对于初涉此领域的毕业设计课题来说,尤其在开始初期,感觉逻辑复杂,难以控制,因此至今还有一些未能解决的bug。

目前发现的bug和未完善的功能列表如下:

1. 与敌人对子弹的时候有时候可能会出现当敌人死后,自己若仍在原地,子弹会发不出去。

2. 敌人的人工智能变化较少,不够理想。

3. 子弹和敌人经常会与画面的刷新的线程不同步,造成画面闪烁。

4. 由于每次子弹发射和每次坦克的移动的一个象素都会对所有坦克和所有子弹进行一次循环检查,并由于同时开的线程比较多,使得本来运行效率就不高的KVM运行异常缓慢。即使刷屏没有间隔也不会提高速度。

5. 最好有接宝物的设置,增强可玩性。

6. 当敌人和自己同时死亡时,仍会过关,但gameover字样会出现,下一关坦克不会出现,但可以隐身发炮。

已经解决的重要bug:

1. 当发出子弹到达边界并同时还在草丛中时会抛出数组边界异常。

2. 有时会莫名其妙的死机。

3. 当坦克在草丛中时,对方坦克发出的子弹不能将其击毁。

5.2 经验和感想

坦克大战作为毕业设计,是本人目前做过的最大的程序。虽然大学期间在TC++下设计过一个俄罗斯方块的游戏,并且经过反复的调试修改也达到了一定的精确性,但接手这个题目时仍感觉十分棘手。

本科期间做过很多课程设计,大多规模很小。在数据库、单片机、各种应用软件和游戏中,我仍觉得对游戏的设计有极大的热情。因为其各个模块间的联系十分紧密,代码重复执行率高,当经过无数次的调试、修改后,能最终看到成品,有无比自豪的心情。大学期间做过银行取款机、图书馆管理程序等简单的数据库管理系统的课程设计,思想大致相似,变化范围有限,没有太多自己可发挥的余地。大家作品的最终结果都离不开同一个模式。相比一些数据库软件,游戏的设计有很多人情色彩和艺术思想的发挥,正式商业的软件的人性化界面和各个游戏间迥异的结构每每会让人有去开发的冲动。

游戏程序最大限度的利用了硬件条件,因此展现出的画面往往多彩绚丽、效果惊人。成功的游戏融合了三维运算、人工智能、音效处理等计算机多媒体的精华部分。本毕业设计建立在Java平台上,是本人以前未曾接触过的领域。凭着探索新知识的热情,我选择了该设计题目。学习该平台背景和功能的时间远远超出了我想象的时间。在设计初期,为了画出一个简单的图形,需要花费一天的时间,为了使图形产生动态效果又会花费几天的努力。很多相关的技术,如需要使用到的线程、RMS数据库、Game包的新功能、高级、低级图形界面的使用、时钟的控制、贴图,每一项都需要花一定的时间去掌握和熟悉。更为困难的是,J2ME为一种刚出现仅几年的新技术,国内的参考资料非常少,仅有的几本也停留在简单的介绍阶段。台湾的王森写了两本较好的书,给了我很大的帮助,但对设计该游戏来说,仍只够入门。在发觉中文资料的稀少后,我不得不全篇阅读midp profile英文函数库,并为了日后查找和保留方便,将其中70%的内容摘要了部分重要内容翻译在笔记上,形成了论文要求外的10000多字的翻译内容。英文原版介绍的确比市面上所有的书籍都更为详细和准确。为了进一步探索深层次的技巧,我花费了大量时间在sun的Java主页上,阅读了几十篇英文的技巧和代码样例。

在终于可以照猫画虎的写出一小段动画的代码时,已经过去了相当长的准备时间。我原以为这样的速度将无法完成毕业设计,但当掌握了大部分应用技巧时,剩下的游戏思路的设计就显得不是最大的障碍了。指导老师说Java的上手比较困难,需要配置的环境和掌握的背景比较多。现在看来的确是这样。

我在一星期内写了1500行代码,经过了几百次的调试,终于完成了现在的程序。原先认为不可能的事,我发现,如果有不畏困难的信心和肯钻研的勇气,就一定会完成,甚至达到意想不到的效果。

本程序打包后体积23K,运行时如进行gc()内存回收可将运行时堆内存控制在50K以内,大小与目前大部分手机的100K左右的可使用内存和500K左右的存储空间。然而,回首80年代的红白机上的坦克大战原始游戏,将惊叹那样的商业软件的巧夺天工。华丽的界面,出色的人工智能,流畅的运行效果、多音效、双人操作控制,其二进制程序体积仅仅为24K。运行在12MHz,8K内存的硬件机器上仍不失流畅性和可玩性。而许多J2ME游戏程序需要200K的运行内存空间、200MHz的处理器,仍运行不够流畅。机器代码级和基于虚拟机的半解释性处理的程序在这里得到了最大的对比。

在被NCS公司录取为程序员后,我希望自己在毕业设计中所学习到的基础、思想和精神能够进一步应用在实际工作中,将潜力不断的发挥出来。

致谢

首先感谢我的指导老师薛峰博士,他在我的毕业设计过程中提出了指导性的方案和架构,并指引我阅读相关的资料和书籍,使我在不熟悉的领域中仍能迅速掌握新兴的技术。

感谢答辩组对本毕业设计的考核,如果可以得到专家的认可将对我的学习和工作给予极大的鼓励。你们客观的评价和建议我将牢记在心,在今后的发展中扬长避短,更加努力的严格要求自己。

感谢父亲在设计中对我的督促、鼓励和母亲为我创造的安静环境,家人的支持永远是个人发展的基石。

本科学习中的各科老师对提高我的编程素质有很大的帮助,我的同学在设计完成后对程序的测试,没有他们,也许就难以发现一些潜在的错误,在此一并表示感谢。

参考文献

[1] 手机程序设计入门,王森(台湾),中国铁道出版社,30~50页

[2] 循序渐进Java2教程(第三版)Rogers Cadenhead著,淡文刚于红梅译,人民邮电出版社,12~20页

[3] MIDP 图形编程简介,Nokia电子文档

[4] 精通Jbuilder9,飞思科技产品研发中心,电子工业出版社,2004,23~40页

[5] Java手机程序开发,微型爪哇人,中国铁道出版社,2003,20~100页

[6] J2ME in a Nutshell, Kim Topley,O'Reilly publish,2002

[7] Wireless Tool Kit, MIDP 2.0 profile,Sun Micro.

[8] https://www.doczj.com/doc/c78042525.html,

[9] https://www.doczj.com/doc/c78042525.html,/j2me

[10] https://www.doczj.com/doc/c78042525.html,

[11] https://www.doczj.com/doc/c78042525.html,

[12] https://www.doczj.com/doc/c78042525.html,

[13] Borland Jbuilder9 Help documents,Borland corporation.

[14] Creating 2D Action Games with the Game API, Sun公司网页中的Technical Articles and Tips, Jonathan Knudsen ,及其源代码。

[15] Record Management System Basics, Eric Giguere. Sun Micro.

附录源程序代码

BattleCanvas.java文件内容:

package tank;

import javax.microedition.lcdui.*;

import javax.microedition.lcdui.game.*;

import java.io.*;

public class BattleCanvas extends GameCanvas implements Runnable{

/** Constructor */

private UserSprite userSprite;

private LayerManager layerManager;

private EnemySprite enemySprite[];

private TiledLayer board;

private Sprite gameOver;

private ScoreScreen scoreScreen=new ScoreScreen();

private int enemyPosition=1;

public static int enemyNum=9; //total enemy number in current level;

public static int enemyOnScreen=0; //because one tank is served in the initialization.

private String level1="/tank/level1.png";

private String level2="/tank/level2.png";

public static int currentLevel=1; //define what level the game is in now.

private boolean isLoading=true; // whether game is in the state loading process;

public static long beginTime;

public static boolean dead=false;

public static boolean completed=false;

public static long endTime; // used to calculate how much time had been taken on a single level to determine the obtained score.

/*3 positions are defined at top of the screen each time the

enemy comes out.they are 1,2,3 respectively.enemy will take

turns to come out from these three ports. Default postion is 1. */

public BattleCanvas() throws IOException{

super(true);

layerManager=new LayerManager();

board=createTiledLayer();

createBoard(level1);

layerManager.append(board);

userSprite=createUser();

userSprite.setLayerManager(layerManager);

userSprite.setTiledLayer(board);

userSprite.resetPosition();

layerManager.append(userSprite);

enemySprite=new EnemySprite[6]; //allow 6 enemytanks appear on the battlefield simultaneously

userSprite.setShootCheck(enemySprite);

this.start();

}

public void start()

{

Thread t=new Thread(this);

t.setPriority(Thread.MAX_PRIORITY);

t.start();

}

UserSprite createUser() throws IOException

{

Java语言坦克大战游戏设计(附有代码和图片)

JISHOU UNIVERSITY 本科生毕业设计 题目:基于java语言坦克大战游戏开发作者: 学号: 所属学院:信息科学与工程学院 专业年级: 指导教师:职称: 完成时间: 吉首大学教务处制

目录 基于java语言坦克大战游戏开发 (1) 摘要 (1) Based on the development of Java language Tank Wars Game (2) 第一章游戏简要说明 (3) 第二章开发环境介绍 (4) 2.1 开发环境 (4) 2.2 java语言特点简介 (4) 2.3 Eclipse开发工具的简介 (5) 第三章系统总体设计 (6) 3.1程序功能的总和 (6) 3.2主体模块 (6) 3.3子弹模块 (6) 3.4坦克模块 (7) 3.5 墙模块 (7) 3.6血液模块 (7) 3.7爆炸模块 (8) 第四章游戏详细设计过程 (9) 4.1创建游戏窗口 (9) 4.2改变游戏背景颜色。 (11) 4.3创建坦克 (11) 4.4 让坦克动起来 (12) 4.5改变窗口的大小 (13) 4.6让坦克受控制 (14) 4.7创建一个Tank类 (15) 4.8让坦克向8个方向移动 (16)

4.9修改4.8中所设计的不足 (18) 4.10添加子弹类 (19) 4.11根据己方坦克的位置,打出子弹 (21) 4.12修改坦克停下来不能打出子弹的问题 (21) 4.13让坦克能够打出多发子弹 (23) 4.14解决炮弹不消亡和坦克出界的问题 (23) 4.15增加敌方坦克 (24) 4.16击毙出现的敌方坦克 (25) 4.17加入爆炸效果 (26) 4.18添加多辆敌方坦克 (27) 4.19让敌方坦克智能化 (29) 4.20建立游戏障碍物 (31) 4.21阻止坦克互相穿越 (32) 4.22为我方坦克添加大招和血条 (33) 4.23添加血块 (34) 4.24重新载入敌军或我军坦克 (35) 4.25加入图片 (35) 第五章游戏的可行性测试 (37) 5.1游戏界面介绍 (37) 5.2游戏运行测试 (40) 第六章总结 (43) 参考文献 (44)

韩顺平java坦克大战1.0版本_源代码

/**画坦克1.0 */ import java.awt.Color; import java.awt.Graphics; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import javax.swing.JFrame; import javax.swing.JPanel; public class MyTankGame extends JFrame { MyPanel mp=null; public static void main(String[] args) { MyTankGame mtk=new MyTankGame(); } public MyTankGame() { mp=new MyPanel(); this.add(mp);//把面板加入窗体 //注册监听 this.addMouseListener(mp); this.addKeyListener(mp); this.addMouseMotionListener(mp); this.addWindowListener(mp); this.setTitle("坦克大战");//窗体标题 this.setSize(600,400);//大小,宽,高(像素) this.setLocation(300,300);//显示位置。左边距,上边距 //禁止用户改变窗口大小 this.setResizable(false); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true);//显示 } } //我的面板 class MyPanel extends JPanel implements

项目坦克大战设计报告

《JA V A程序开发课程设计》项目设计 项目名称:TankWar 软件 专业:软件工程班级:13软工1班姓名:毛晨光学号:24 一、需求分析: 基本功能: 1.玩家控制的坦克能够四处移动并且打击敌方坦克; 2.敌方坦克能够随机四处移动并且打击玩家控制的坦克; 3.玩家控制的坦克拥有血量,而敌方坦克没有; 4.坦克受到攻击时血条会缩短; 5.敌方坦克被消灭完之后,提示游戏胜利; 6.用户方坦克被消灭后提示游戏结束; 特色功能: 1.坦克具有图片,不单单只是个圈圈。 2.增加了血包功能,地图上会随机出现一个血包,我方坦克开过会增加 血量。 二、系统设计: 类:实现游戏界面地图的初始化。 类:绘制和重绘功能。 :监听用户的键盘输入。 类:实现坦克的初始化,绘制,移动,发射等功能。 :实现敌方坦克的初始化,绘制,移动,发射等功能。 类:实现炮弹的初始化,绘制,移动,攻击功能。 类:实现爆炸的初始化。绘制功能,爆炸效果由绘制半径从小到大再到小的圆实现。 类:包含枚举。 类:用于实现血包的功能。 三、功能实现。 一.绘制地图功能: public class TankMap extends Frame{ tart(); }

制坦克功能:public class Tank { 方坦克的绘制方法 public class EnemyTank extends Tank{ 弹绘制方法public class Shell { ntersects())){

ntersects())){ "hittanks"); (false); =false; Explor ex=new Explor(x-3,y-3,; return true; } } return true; } }

funcode C++课程设计坦克大战

课程设计一坦克大战 一、游戏介绍 相信大部分同学都玩过或看过“坦克大战”这款经典游戏。现在,就由我们自己动手来开发它。只要大家具备了C++语言和面向对象的基础知识,然后按照实验指南的指导一步一步进行下去,相信我们每个同学都能把这款经典游戏做出来。 二、实验目标 综合运用C++及其面向对象的知识开发一款小游戏。 三、实验内容 在一个战场上,玩家控制坦克,消灭敌方坦克,并防止敌方坦克摧毁我方基地。游戏的具体要求如下: 1、游戏有一个初始页面,如下图。 2、按下任意键开始游戏,玩家控制坦克在战场上穿梭,碰到墙时,不能通过。 3、敌方坦克自由移动,每隔2秒改变一个方向,每隔3秒发射一发子弹。 4、敌方坦克每隔5秒出现一辆,从屏幕上方的左、中、右三个位置依次出现。 5、当玩家被消灭或者我方基地被摧毁或者游戏时间大于30秒的时候,游戏结束。 游戏开始前 进入游戏

四、游戏的整体框架 五、实验指南 实验准备 打开FunCode,创建一个新的C++项目。注意:项目名称必须为英文和数字,且不能有空格。 点击“项目”→“导入地图模板”,从对话框中选取名称为TankWar的模板导入。导入成功后,界面如下: 实验一游戏开始 【实验内容】 1、设置游戏标题 2、按空格键,提示图片消失,游戏进入开始状态. 【实验运行结果】 游戏开始前 按下空格键后 【实验思路】

按下空格键是键盘按下事件,可在CSystem::OnKeyDown函数中编写响应代码。为了保证程序结构的清晰、一致,更好的办法是在CGameMain类中添加一个相应的键盘按下事件处理函数,然后在CSystem::OnMouseClick函数中进行调用。 g_GameMain是CGameMain类的对象,它是全局变量,在程序运行时最先被创建。【实验指导】 1、C++程序的执行入口是主函数。FunCode的主函数名称叫WinMain,写在Main.cpp 文件中。CSystem::SetWindowTitle是设置程序运行窗口标题的函数,修改如下:CSystem::SetWindowTitle("坦克大战"); 2、参考CSystem::OnKeyDown函数,为CGameMain类创建一个OnKeyDown函数。 CGameMain类的头文件是LessonX.h文件,实现代码写在LessonX.cpp文件中。因此,先在LessonX.h文件对函数进行声明。函数的返回值和参数列表都与 CSystem::OnKeyDown函数保持一致。访问权限应该是public。代码如下: voidOnKeyDown(constintiKey,constboolbAltPress,constboolbShiftPress,cons tboolbCtrlPress); 3、接着,在Lesson.cpp文件中对该函数进行定义: voidCGameMain::OnKeyDown(constintiKey,constboolbAltPress,constboolbShif tPress,constboolbCtrlPress) { }

基于java的游戏坦克大战论文

基于j a v a的游戏坦克 大战论文 文件排版存档编号:[UYTR-OUPT28-KBNTL98-UYNN208]

目录 1 2 5 1

第一章绪论 课题研究的背景 如今我们的生活节奏越来越快,每个人的生活压力也在不断变大,长期紧绷着神经容易产生心理和生理上的双重伤害,人们需要在工作和学习之外放松自己,玩玩游戏正是放松自己的方式之一。 坦克大战,一个众所周知的小游戏,曾经在红白机时代风靡一时。其界面简单,耐玩,关卡多,可玩性高,没有局限的年龄层。 Java是现在全球最时髦的开发工具之一,它拥有庞大且完善的类库,内置了其他语言需要靠库甚至是操作系统才能支持的功能,拥有一个虚拟机,总之,Java的出现,确实给整个程序界带来了巨大的冲击,也许现在还无法准确评估Java为整个IT业带来的影响,但是有一点毋庸置疑—Java将不可避免的影响一带程序员。 使用Java作为开发工具,来做坦克大战这个小游戏,是一种很理性的选择。Java游戏可以在本地桌面系统下运行,也可以在Web浏览器下运行。 我在大学四年中学到了很多计算机的知识,JAVA语言,软件工程,数据结构,软件工程等课程。如今我将用我所学的知识来完成一个坦克大战游戏,来锻炼自己的动手能力,独立作出一个小程序。 课题研究的任务 本文中所做的主要工作如下: (1)介绍了制作坦克大战游戏的意义和目的。 (2)设计坦克大战游戏各个类,实现各类效果和目标。 (3)分析并解决游戏中的若干技术问题。 (4)完成坦克大战游戏,进行测试并分析结果.

第二章系统分析 课题的可行性分析 1、课题要求 (1)与实践活动和相关的文件和资料由教师提供。 (2)本课题要求学生有熟练的Java开发能力,有较强的自学能力。 (3)具体问题再做详细调查研究并与指导老师面谈。 2、可行性分析 技术可行性:游戏对机器没有多大要求,现在无论什么电脑,只要能安装J2SDK,就能在电脑上开发这款游戏。制作出来的游戏可以在本地桌面运行,也可在WEB上运行,现在JAVA语言非常成熟,完全能够完成这个游戏。 经济可行性:开发这个游戏除了耗费自己的时间和精力以外,不需要其他的资金问题,完成后放到网上开放下载,无需任何费用,有兴趣的人可以自己下载来玩。 需求分析 在游戏中需要实现的功能: (1)能够通过键盘自由控制坦克移动和发射子弹; (2)敌方坦克能够随机移动和随机发射子弹; (3)子弹和不同阵营坦克碰撞后会产生爆炸; (4)消灭敌方坦克后会有个计分板记录玩家得分 (5)游戏进行到一半时可以暂停退出,下次打开游戏时选继续游戏可以继续之前的游戏。 第三章系统总体设计 游戏总体流程设计 开始新游戏时,先进行初始化,然后调用敌方坦克类和我方坦克类,实现键盘监听功能,战场显示所有坦克的移动,发射子弹。判断子弹和敌方坦克的碰撞,调用爆炸类,调用记录类,修改玩家总得分。

java开发坦克大战

j a v a开发坦克大战 IMB standardization office【IMB 5AB- IMBK 08- IMB 2C】

坦克大战游戏演示为什么选择这个项目 1、好玩 2、涉及到java各个方面的技术 1、java面向对象编程; 2、界面编程; 3、绘图技术; 4、多线程; 5、文件i/o操作; 6、数据库 3、巩固旧知识,学习新知识 java绘图坐标体系 绘图坐标本系--介绍 坐标原点位于左上角,以像素为单位。像素是计算机屏幕上最小的显示单位。在java的坐标系中,第一个是X坐标,表示当前位置为水平方向,距离坐标原点X个像素;第二个是Y坐标,表示当前位置为垂直方向,距离坐标原点Y个像素。 坐标体系--像素 计算机在屏幕上显示的内容都是由屏幕上的每一个像素组成的。例如,计算机显示器的分辨率是800×600,表示计算机屏幕上的每一行由800个点组成,共有600行,整个计算机屏幕共有480000个像素。现在的计算机可以支持更高的分辨率,也就是说,屏幕上可以显示更多的像素。因此,像素是一个密度单位,而厘米是长度单位,两者无法比较。 绘图原理(1)[] Component类提供了两个和绘图相关最重要的方法: 1、paint(Graphicsg)绘制组件的外观 2、repaint()刷新组件的外观

当组件第一次在屏幕显示的时候,程序会自动的调用paint()方法来绘制组件 .*; .*; publicclassWindow013extendsJFrame{ ; 7、画字符串drawString(Stringstr,intx,inty); 8、设置画笔的字体setFont(Fontfont); 9、设置画笔的颜色setColor(Colorc); ; .*; publicclassWindow014extendsJFrame{ ; .*; publicclassWindow015extendsJFrame{ ; .*; import publicclassWindow016extendsJFrameimplementsActionListener{ quals("黑色")){ 点击了黑色按钮"); ; }elseif().equals("红色")){ 点击了红色按钮"); ; }else{ 不知道"); } } } classCatimplementsActionListener{ publicvoidactionPerformed(ActionEventarg0){ if().equals("黑色")){ 也知道你按下了黑色按钮");

java开发坦克大战

坦克大战游戏演示 为什么选择这个项目 1、好玩 2、涉及到java各个方面的技术 1、java面向对象编程; 2、界面编程; 3、绘图技术; 4、多线程; 5、文件i/o操作; 6、数据库 3、巩固旧知识,学习新知识 java绘图坐标体系 绘图坐标本系--介绍 坐标原点位于左上角,以像素为单位。像素是计算机屏幕上最小的显示单位。在java 的坐标系中,第一个是X坐标,表示当前位置为水平方向,距离坐标原点X个像素;第二个是Y坐标,表示当前位置为垂直方向,距离坐标原点Y个像素。 坐标体系--像素 计算机在屏幕上显示的内容都是由屏幕上的每一个像素组成的。例如,计算机显示器的分辨率是800×600,表示计算机屏幕上的每一行由800个点组成,共有600行,整个计算机屏幕共有480000个像素。现在的计算机可以支持更高的分辨率,也就是说,屏幕上可以显示更多的像素。因此,像素是一个密度单位,而厘米是长度单位,两者无法比较。 绘图原理(1)[Window013.java] Component类提供了两个和绘图相关最重要的方法: 1、paint(Graphics g)绘制组件的外观 2、repaint()刷新组件的外观 当组件第一次在屏幕显示的时候,程序会自动的调用paint()方法来绘制组件 import java.awt.*; import javax.swing.*; public class Window013 extends JFrame{ //定义组件 MyPanel mp=null; public static void main(String[] args) { Window013 th=new Window013();

坦克大战课程设计论文

坦克大战游戏设计 1.课程设计的目的 随着手机的日益普及,java功能在移动设备上的实现及java 应用程序产生的影响力,对丰富人们的生活内容,提供便捷的咨询起着不可忽视的作用。本项目介绍了坦克大战的基本构建方法、java的相关技术及本程序的结构分析和具体功能的实现。游戏是在Eclipse3.2环境下编程。本项目重点运用了图形化用户界面GUI,Thread多线程的有关知识,其中涉及了绘图工具的运用,事件处理操作以及图形的碰撞检测等知识点。通过此课程设计,使学生巩固所学知识、培养学生动手能力,了解Java的面向对象的体系结构。学生用Java语言设计一个完整的应用程序,综合应用所学知识完成软件的分析、设计、调试和总结,提高学生对Java语言的综合应用能力和解决问题的能力。 2.设计方案论证 2.1设计思路 本项目介绍了坦克大战的基本构建方法、java的相关技术及本程序的结构分析和具体功能的实现。游戏是在Eclipse3.2环境下编程。 一、游戏基本元素:坦克,炮管,子弹,墙壁,地雷 二、它的主要功能: (1)能够朝四个方向移动:上、下、左、右键。 (2) 按下鼠标左键发射普通子弹;按下鼠标右键发射散弹;子 弹爆炸的效果,普通子弹和炮弹的效果 (3)敌人能够移动

(4)能够模拟爆炸 (5)能够产生障碍 (6)能够增长生命 玩家控制主坦克(上方有血条的)的移动以及炮弹的发射。若玩家将敌方坦克全部打掉则玩家胜;若期间由玩家控制的主坦克被打掉则视为玩家失败。游戏中只有普通墙作为障碍物,玩家无法穿越它们并且普通子弹不能将墙打穿 ;但是玩家可以用炮弹将普通墙打掉。桃心可以将坦克的血加满。 2.2简要的设计流程: 键盘监听器 2.2设计方法 2.2.1构建游戏主类

java坦克大战毕业设计论文

基于J2SE的网络版坦克大战游戏设计 摘要 [摘要]:J2SE (Java 2 Standard Edition)就是Java2的标准版,主要用于桌面应用软件的编程,是伴随着计算机技术的飞速发展而诞生的一项新的开发技术。随着个人电脑的日益普及、Java 功能在个人电脑上的实现,Java应用程序产生的单机增值服务逐渐体现出其影响力,对丰富人们的生活内容、愉悦身心、开发智力等起着不可忽视的作用。该论文通过总结和分析JA V A 游戏的开发流程和代码框架的设计,开发了一款基于J2SE架构的游戏——坦克大战。本设计采用面向对象的设计模式,对游戏中的所有物体赋予对象的概念和属性。运行程序后允许用户选择执行选项菜单。在开始游戏后,启动服务器和客户端,对背景的所有物体进行绘图。在主程序运行的线程中,画面刷新将以一定的频率采用双缓冲技术对屏幕重绘,实时反映整个游戏的进行状态。用户控制的坦克运行在主线程中,随屏幕刷新的频率而移动。坦克将在游戏开始时进行初始化,然后将坦克绘制在地图的上层。本设计主要实现的功能是让坦克能向八个方向移动,并且打出炮弹,子弹击中敌人坦克,子弹和敌人坦克同时消失,产生爆炸,CPU坦克能智能的移动并且打出炮弹。能够支持网络对战和单机对战两种模式。 Java良好的跨平台特性在软件的开发中显示出了巨大的威力,“一次编写,随处运行”,java 系统可以运行在不同的操作系统和硬件上。随着linux的持续增长以及MacOSX完全支持java 技术,跨平台的特性变得越来越有分量。 由于免费、跨平台、java语言本身技术先进,在高校中,java已经成为许多学科研究、课程和计算的首选语言,用java做上机作业,一般都是鼓励的。据我所知,北大、清华许多院系的研究生入学考试都可以用java语言答题。实际上,用java来完成这些工作,大多数情况下要比用C或其他语言简洁得多,你可以把注意力集中在算法等核心部分,从而获得更高分数。 [关键词] 面向对象坦克大战游戏J2SE Socket

项目-坦克大战-设计报告

《JAVA程序开发课程设计》项目设计 项目名称:TankWar 软件 专业:软件工程班级:13软工1班姓名:毛晨光学号:1322120124 一、需求分析: 基本功能: 1.玩家控制的坦克能够四处移动并且打击敌方坦克; 2.敌方坦克能够随机四处移动并且打击玩家控制的坦克; 3.玩家控制的坦克拥有血量,而敌方坦克没有; 4.坦克受到攻击时血条会缩短; 5.敌方坦克被消灭完之后,提示游戏胜利; 6.用户方坦克被消灭后提示游戏结束; 特色功能: 1.坦克具有图片,不单单只是个圈圈。 2.增加了血包功能,地图上会随机出现一个血包,我方坦克开过会增加 血量。 二、系统设计: 1.TankMap类:实现游戏界面地图的初始化。 2.PainTread类:绘制和重绘功能。 3.DirectionHandler:监听用户的键盘输入。

4.Tank类:实现坦克的初始化,绘制,移动,发射等功能。 5.EnemyTank:实现敌方坦克的初始化,绘制,移动,发射等功能。 6.Shell类:实现炮弹的初始化,绘制,移动,攻击功能。 7.Explor类:实现爆炸的初始化。绘制功能,爆炸效果由绘制半径从小到 大再到小的圆实现。 8.Direction类:包含枚举。 9.Blood类:用于实现血包的功能。 三、功能实现。 一.绘制地图功能: public class TankMap extends Frame{ //定义地图的尺寸。 public static final int MAPWIDTH=800; public static final int MAPHEIGHT=600; //我方坦克 Tank t=null; //定义随机出现的血包 Random r=new Random(); Image bufferImage=null; public static java.util.Listshells=new ArrayList(); //地方坦克集合 public static java.util.List-> enemys=new ArrayList();

坦克大战java源代码

有些图片路径会出错要注意package com.tankgame; import java.util.Vector; //坦克类 class Tank { int x=0; int y=0; int color=0; int speed=1; int direct=0; boolean isLive=true; public Tank(int x,int y) { this.x=x; this.y=y; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } public int getDirect() { return direct; } public void setDirect(int direct) { this.direct = direct;

} public int getColor() { return color; } public void setColor(int color) { this.color = color; } } //我的坦克 class Hero extends Tank { Shot shot=null; Vector shotm=new V ector(); public Hero(int x,int y) { super(x,y); this.color=5; } //坦克具有一个打击敌人的方法 public void shotenemy(int x,int y,int direct) { switch(direct) { case 0: shot=new Shot(this.x+10,this.y,0); shotm.add(shot); break; case 1: shot=new Shot(this.x+30,this.y+10,1); shotm.add(shot); break; case 2: shot=new Shot(this.x+10,this.y+30,2); shotm.add(shot); break; case 3: shot=new Shot(this.x,this.y+10,3); shotm.add(shot);

坦克大战游戏程序课程设计

《程序设计应用基础》课程设计计划书

坦克大战游戏 1引言 学习了C语言程序设计之后,我们粗略的掌握了程序设计的基本思路和要求,为了更加熟练的掌握这门计算机语言,我们选择编译一个经典小游戏——坦克大战。通过课程设计提高我们的动手能力,把理论知识运用到实践当中。在课程设计中,C语言的语法和逻辑严谨,对于初学者而言,有时忘记一个逗号或者分号整个程序便运行不了,经过了反复的调试,修改,最终形成可执行的程序。在这个过程中,通过不断的练习,我们对C语言的掌握程度有明显的提高,同时,也锻炼了我们的头脑,使我们的思维更加科学严谨。 2设计方案 2.1设计思路 坦克大战游戏,一共两关。不同的关卡,游戏地图、敌方坦克出现的种类不一样。敌方坦克地图上最多存在4辆,击杀后会出现新坦克直至补足4个,当击杀坦克一定数值则敌方新坦克不会再增加。击杀完所有坦克则胜利过关。己方坦克也有复活次数,用完则失败。另地图正下方有己方老家,若被敌方坦克攻破则游戏失败。 3程序设计与实施 3.1程序的主要模块 整个程序分为里表两大部分。 里部分由41*41的int地图数组组成,每个元素代表了该以该数组元素行列下标为地图坐标y,x那个单元的情况,不同的地图障碍物在该数组有不同的值,坦克在地图上占3*3个单元,在地图数组内相应坐标的3*3个元素内也对应特殊的值。由地图数组值可以读出该坦克信息。 表部分则是根据里部分的地图数组通过gotoxy和printf函数在命令行界面打印出相应字符以构成游戏界面的。 程序中的每个函数操作都是通过里部分(地图数组)判定,然后对里部分(地图数组)操作,再由里部改变外部,由gotoxy和printf函数将可视化界面呈现给玩家。也就是游戏主体函数内里表部分是一起操作的,不分开。 对于函数分类,程序又可分为三大类。一类游戏辅助函数。一个子弹系统,一个坦克系统。子弹和坦克分别都是独立运作的系统,有少量信息交换。 3.2 主函数及其流程图 主函数包括打印地图,实现游戏内置调节游戏速度的功能,判断坦克类型,判断敌我坦克是否存活,判断游戏胜负。 3

毕业设计论文 基于J2ME的Java游戏--坦克大战的开发

目录 摘要 ................................................................................................................... - I - Abstract .................................................................................................................... - I - 引言 ...................................................................................................................... II 第一章绪论 .................................................................................................... - 1 - 1.1 手机软件现状.......................................................................................... - 1 - 1.2 游戏业务及J2ME概况............................................................................ - 1 - 1.3 任天堂(Nintendo)的8位FC机器和Battle City背景介绍............ - 3 - 1.4 本章小结.................................................................................................. - 3 - 第二章开发环境及相关技术的介绍 ................................................................ - 5 - 2.1 开发环境.................................................................................................. - 5 - 2.2 Java语言的特点..................................................................................... - 5 - 2.3 关于JBuilder9....................................................................................... - 5 - 2.4 关于Wireless Tool Kit....................................................................... - 6 - 2.5 Java Appication Manager.................................................................... - 6 - 2.6 本章小结.................................................................................................. - 6 - 第三章程序结构、思想和相关技术 ................................................................ - 7 - 3.1 本程序需解决的有关技术问题.............................................................. - 7 - 3.2 程序流程.................................................................................................. - 8 - 3.3 绘图与MIDP2.0新增的GameCanvas包.............................................. - 10 - 3.3.1 提供低级绘制的Canvas类....................................................... - 10 - 3.3.2 Graphics类................................................................................ - 10 - 3.3.3 PNG格式...................................................................................... - 10 - 3.3.4 Game包中的新功能.................................................................... - 11 - 3.3.5 有关绘图的一些技术................................................................. - 12 - 3.4 坦克的控制和敌方的智能运行............................................................ - 12 - 3.5 子弹的运行和控制................................................................................ - 13 - 3.6 RMS数据库系统..................................................................................... - 14 - 3.7 内存使用的最佳化................................................................................ - 15 - 3.8 混淆器(Obfuscator)的使用................................................................ - 16 - 3.9 模拟器的相关调试................................................................................ - 16 - 3.10 本章小结.............................................................................................. - 17 - 第四章程序分析和具体实现 .............................................................................. - 18 - 4.1 游戏进入前的选择................................................................................ - 18 - 4.2 主游戏逻辑及其涉及到的若干类........................................................ - 19 - 4.3 坦克的共同行为.................................................................................... - 21 - 4.4 玩家坦克的功能属性............................................................................ - 22 - 4.5 敌人坦克的功能属性............................................................................ - 22 - 4.6 子弹的运行和控制................................................................................ - 24 - 4.7 记分系统................................................................................................ - 25 -

java写的坦克大战简易版

MyTankGame2.java package test; import javax.swing.*; import java.awt.*; import java.awt.event.*; //import java.io.*; import java.util.*; class MyTankGame2 extends JFrame implements ActionListener { MyPanel mp=null; //定义一个开始的面板 MyStartPanel msp=null; //做出我需要的菜单 JMenuBar jmb=null; //开始游戏 JMenu jm1=null; JMenuItem jmi1=null; //退出系统 JMenuItem jmi2=null; //存盘退出 JMenuItem jmi3=null; JMenuItem jmi4=null; public static void main(String[] args) { //System.out.println("Hello World!"); MyTankGame2 mtg=new MyTankGame2(); } //构造方法 public MyTankGame2() { //创建菜单及菜单选项 jmb=new JMenuBar(); jm1=new JMenu("游戏(G)"); //设置助记符 jm1.setMnemonic('G'); jmi1=new JMenuItem("开始新游戏(N)"); jmi2=new JMenuItem("退出游戏(E)"); jmi3=new JMenuItem("存盘退出游戏"); jmi4=new JMenuItem("继续上局游戏"); jmi4.addActionListener(this);

程序设计实训坦克大战实验报告材料

程序设计实训报告 坦克大战 专业班级:装控1401 实习时间:2015年7月10日至7月14日实习地点:微401 成员 1:赵振华 成员 2:许晨欢 成员 3:蒋绪涛

一、作品概述 1.1 创新点: 1、自定义并命名树林和钢板精灵,设置树林属性为不接受碰撞可以自由穿梭,钢板为接受任何碰撞但不做任何处理(即子弹和坦克均不能摧毁钢板)。 2、添加坦克发炮、击中目标和坦克移动的特殊声效。 1.2 概述: 这款游戏是我们QWER小组以经典90版坦克大战为背景制作的坦克大战的改编款,玩家通过控制坦克摧毁敌方坦克来保卫主基地不被摧毁。当敌我双方坦克相碰或己方基地被子弹摧毁时游戏结束(敌我双方子弹均可摧毁基地),每隔3秒钟出现一辆敌方坦克,游戏最大时长为100秒。此款游戏与经典90版坦克大战较为相似,操作简单,能唤起我们对童年的回忆。 二、功能设计 玩家坦克与敌方坦克在街道中进行巷战,玩家坦克被击中或与敌方坦克相撞、玩家指挥部被击中或游戏时间到,一局游戏结束。 按下空格键后游戏开始,“空格开始”消失,载入地图,100秒倒计时开始,并把玩家坦克设置在指挥部左侧。 游戏时间到,玩家坦克被敌方坦克摧毁,与敌方坦克相撞,或者玩家指挥部被摧毁,一局游戏结束,游戏回到初始界面,并显示上一局的分数。 玩家用W、A、S、D键控制坦克上、下、左、右运行,按J键开炮。坦克行进过程中有特殊声效,坦克发射或击中目标都有相应的声效。玩家坦克碰到墙和钢板就停下来,需要调转方向才能继续前进。玩家坦克开炮,一炮就能摧毁一块墙或者一辆敌方坦克,但不能摧毁钢板,玩家可穿梭于树林中。玩家每摧毁一辆敌方坦克,加1分。 玩家指挥部被坦克或者炮弹(不管玩家还是敌方)碰上,都会被摧毁。 每隔3秒钟,就会产生一辆敌方坦克。敌方坦克每隔一段时间,就自动开炮。敌方坦克遇到墙就会停下来。停下来的坦克,前方的墙如果被摧毁了,又能继续前进。每隔几秒钟,敌方坦克就会顺时针变换一个方向前进。每局最大时长为100秒。

坦克大战系统《Java程序开发实训》综合实训报告

《Java程序开发实训》综合实训报告 题目:坦克大战系统 姓名:方庆 学号:2010203206 班级:10软件(2)班

一、系统实现的主要功能及运行结果截图 选择的语言的原因 游戏本身是一种娱乐方式,带给人无尽的乐趣,而且游戏行业的发展也将是带动周边行业的发展。同样对做出游戏的人的要求也会越来越高一满足游戏爱好者的要求。本次期末设计就是设计一种娱乐性较强的小游戏坦克大战,说到大战其实是不敢当的。但游戏基本拥有可玩性。java语言是一种跨平台,适合与分布计算环境的面向对象编程语言,java主要用在web开发,手机游戏及一些平台游戏的开发,他有很好的跨平台性。所以本次的设计坦克游戏选择的是java。 系统软件的软件环境 1.网络服务器操作系统:Window是 XP以上 2.开发工具:Eclipse 3运行环境:J2sdk 4.编程语言:java语言。 人机对战模式功能 1.能够发射子弹打击敌人 2.敌人能够移动 3.能够模拟爆炸 4.能够产生障碍 5能够增长生命6.能够使用超级子弹 坦克可以发射子弹

玩家坦克被击中血量减少。 被击中的坦克发生爆炸并且吃血块可以加血量。

玩家坦克可以从把方向发射超级子弹 自己的TankHealth为<=0时,。说明玩家坦克已死亡。游戏结束

本系统的坦克大战是基于java语言设计的开发,具有较高的人工智能和相对的图形处理。游戏可一人作战每次电脑方有10辆坦克, 此一举消灭全部的敌方坦克为目的。在这过程中坦克有机会得到血块来添加自己的生命值。从而变得强大。也利用wall来形成阻击敌人。 游戏拥有开挂的功能。可以穿过墙体来攻击敌方坦克。还给玩家坦克 置了超级炮弹。从八个方向同时射出炮弹来摧毁敌方坦克。主要功能 简单罗列如下: 1.屏幕左上方显示游戏的状态,当玩家方坦克全数为0是游戏结束 2.敌方坦克只在空地上行走,不可通过Wall 3.游戏打坏敌方坦克后,可随机位置随机出现血块奖励。坦克经过该 位置可获得相应的生命值加成。 4.玩家坦克的游戏资格和电脑坦克不同。 TankClient类设计流程 游戏系统类关联图

基于Java的网络版坦克大战游戏设计_毕业设计

伊犁师范学院 本科生毕业论文(设计) 论文题目:基于Java的网络版坦克大战游戏设计

基于Java的网络版坦克大战游戏设计 (伊犁师范学院计算机科学系06-2班,新疆伊宁市 835000) 摘要:本设计采用面向对象的设计模式,对游戏中的所有物体赋予对象的概念和属性。运行程序后允许用户选择执行选项菜单。在开始游戏后,启动服务器和客户端,对背景的所有物体进行绘图。在主程序运行的线程中,画面刷新将以一定的频率采用双缓冲技术对屏幕重绘,实时反映整个游戏的进行状态。用户控制的坦克运行在主线程中,随屏幕刷新的频率而移动。坦克将在游戏开始时进行初始化,然后将坦克绘制在地图的上层。本设计主要实现的功能是让坦克移动并能够智能的打出炮弹,躲避子弹,炸毁对方坦克。能够支持网络对战和单机对战两种模式。 关键词:面向对象;坦克大战;网络游戏;Java;Socket 类 中图分类号:TP311.1 目录

摘要 ......................................................................... 第1章前言.. (1) 1.1游戏设计的需求分析 (1) 1.1.1国内外电子网络游戏的现状 (1) 1.1.2本系统的现实意义 (1) 1.1.3本系统和其他开发游戏区别 (2) 1.2开发技术概述 (2) 1.2.1J AVA、C语言、C++三种主流编程技术比较 (2) 1.3本章小结 (2) 第2章相关技术理论 (3) 2.1系统运行环境 (3) 2.1.1系统运行的软件环境 (3) 2.1.2系统运行的硬件环境 (3) 2.2相关理论 (3) 2.2.1关于E CLIPSE的介绍 (3) 2.2.2J2SE框架 (3) 2.2.3联机通信机制 (4) 2.2.4J AVA图形编程 (5) 2.3本章小结 (5) 第3章系统设计 (5) 3.1系统可行性分析 (6) 3.1.1技术可行性 (6) 3.1.2经济可行性 (6) 3.1.3操作可行性 (6) 3.2系统需求分析 (6) 3.2.1在人机对战模式下实现的功能 (6) 3.2.2在网络对战模式下实现的功能 (6) 3.3系统功能设计 (6) 3.3.1坦克大战总体功能设计 (7)

相关主题
文本预览
相关文档 最新文档