系统简介
《飞机大战》是一款使用J2EE来开发的纵版射击类游戏。我们以计算机为工具,在Java平台上借助Eclipse软件开发设计,最后让游戏拥有良好的背景与音乐,和独特的纯鼠标控制界面,玩家可以通过移动鼠标,来完成游戏的操作。游戏含有三个关卡,每一个关卡都有独特的实力强劲的boss和独特的敌机出场方式,玩家们在享受游戏的同时需要利用系统给予玩家的一切资源击败每一个boss,才能完成游戏。
在设计中,我们借助了JFrame类构建我们的窗体,利用面板容器类JPanel嵌入窗体中,完成我们窗体界面的搭建,借助music类来完成我们背景音乐的嵌入,实现mouseListener接口来完善鼠标的监控,利用ArrayList集合来存放敌机。
引 言
在如今,计算机技术被利用在人们的生活方式和工作方式中,使得其发生了巨大的变革,更是在疫情的影响下,更让人们意识到了在这个世纪,计算机与网络才是这个时代的主体,随之而来的,还有新兴的娱乐方式,例如网络游戏等等。
由于科学技术的发展,电脑走进了万家千户,与人们的生活紧密的结合在了一起,随着科技的飞速发展,电子游戏已然变成了一种被世界认可的电子竞技运动,不再像从前一样,电子游戏是被遭到唾弃的存在,如当今爆火的,例如反恐精英,英雄联盟,守望先锋,绝地求生这些电子竞技,在世界范围内都有专属于他们的世界级比赛,在2018年的中国亚运会上,英雄联盟中国队的夺冠,才使得电脑游戏成为炙手可热的人们的焦点。
这是在中国电竞还未开化时的一款游戏,在很小的时候,游戏对我们来说,总是触不可及,家长总会认为玩游戏是毁坏下一代的缘由,所以只有在周末的时候,攒了一点点的零花钱,去游戏厅痛痛快快坐在那儿打了一下午的雷霆战机街机。
随着时代的发展,手机与电脑走进了千家万户,这不再是遥不可及的梦,他走进了人们的手机,走进了人们的电脑,它开始变得随手可及。但随之而来的,是更多的问题。飞机大战类似的游戏有许许多多,但很多飞机大战失去了它原本的初心,它开始发展的越来越复杂,里面充斥着各种广告,更多的充值入口,使得游戏失去了它原本的平衡性,只要氪金似乎就可以取得最后的胜利,这是否与最初的初衷有所违背,且那些游戏为了圈钱,使其游戏的色彩音效画质不能尽如人意。
飞机大战是一款童年理想中的游戏,玩家将扮演一架英雄所操纵的英雄飞机,通过简单的鼠标操作,鼠标随意移动的左右移动,便可自动地攻击敌人,上下移动亦可躲避敌机与子弹。在飞机上的左上角还有玩家的生命值,玩家需要保持着优异的血量击败boss才能够通关,由于后期的敌人太过强悍,我们会不定量不定时的为英雄机提供补给包,当然,补给包是随机投放的,玩家一定要吃到补给包才可触发补给哦,补给包可是分为三种的哦,有生命补给包,弹药补给包以及大招补给包,这些都会使玩家操纵的英雄机变得更加的强悍,让你火力全开。
同样的,为了秉持不忘初心的理念,我们的游戏随时可以开始,随时可以停止,让玩家们体验到随玩随停的便捷性与乐趣性,不会扰乱玩家们的正常生活,只当做闲余生活的调味剂,避免给玩家们带来生活负担。让玩家们有更好的游戏体验,不忘初心,方得始终!
1 相关技术
飞机大战小游戏开发环境是在操作系统 Microsoft Windows X64,程序语言Java,利用IDE Eclipse 4.14下J2EE技术开发的一款射击类游戏。
1.1 开发工具
1.1.1 计算机
计算机(Computer)全称:电子计算机。这是一种能够按照程序运行,自动、高速处理数据的现代化智能电子设备。计算机的应用已经渗透到社会的各个领域,正在改变着人们的工作、学习和生活的方式,推动着社会的发展。
1.1.2 计算机硬件
计算机硬件(Computer Hardware)是指计算机系统中由电子,机械和光电元件等组成的各种物理装置的总称。这些物理装置按照系统结构的要求构成一个有机整体为计算机软件运行提供物质基础。
计算机通常由鼠标、CPU、主机箱、硬盘、内存、显卡、键盘、电源、主板、显示器等多个部份组装而成。
1.1.3 计算机软件
计算机软件(Computer Software)是必不可少的东西在使用计算机的过程中,计算机软件按照其功能划分为系统软件与应用软件。
系统软件:DOS(Disk Operating System), Windows, Linux, Unix, Mac, Android, iOS等
应用软件:微信 百度网盘 英雄联盟 绝地求生 守望先锋 谷歌浏览器 腾讯会议 炉石传说等
1.2 开发环境
1.2.1 Java语言概述
詹姆斯·高斯林在转至Sun公司(Stanford university network)后,与Patrick,Naughton和Mike Sheridan等人合作“绿色计划”,后来发展一套语言叫做“Oak”,后改名为Java。
Java语言特点:简单性、高性能、编译性、解释性、面向对象、分布式处理、健壮性、安全性、开源与跨平台。那什么是跨平台呢?就是通过Java语言编写的应用程序在不同的系统平台上都可以运行。
只要在需要运行java应用程序的操作系统上,先安装一个Java虚拟机(JVM Java Virtual Machine)即可。由JVM来负责Java程序在该系统中的运行。
因为有了JVM,所以同一个Java程序在三个不同的操作系统中都可以执行。这样就实现了Java程序的跨平台性。也称为Java具有良好的可移植性。以下做一个的关系图以便理解,如图2.1JVM的理解图。
图2.1 JVM的理解图
1.2.2 JDK的概述
JDK是Java语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用程序。JDK是整个java开发的核心。
1.2.3 JDK JRE JVM的关系
如图2.2JDK JRE JVM关系图 。
图2.2 JDK JRE JVM关系图
1.2.4 Eclipse概述
Eclipse是一个基于Java的、开放源代码的可扩展开发平台。它只是一组服务和一个框架,用于通过插件组件构建来开发环境。Eclipse 还包括插件开发环境(Plug-in Development Environment,PDE),这个组件主要针对希望可以扩展 Eclipse 的软件开发人员,因为它允许他们构建与 Eclipse 环境无缝集成的开发工具。它构成了 IBM Java 开发工具系列的基础。
2 需求分析
2.1 问题描述
飞机大战类似的游戏有许许多多,但很多飞机大战失去了它原本的初心,它开始发展的越来越复杂,里面充斥着各种广告,更多的充值入口,使得游戏失去了它原本的平衡性,只要氪金似乎就可以取得最后的胜利,这是否与最初的初衷有所违背,且那些游戏为了圈钱,使其游戏的色彩音效画质不能尽如人意。
2.2 技术分析
这款游戏不需要任何的费用,不做为商用,只为了寻回小时候的初心,且免费对外开放源码,这款游戏可以在短时间内游戏,随玩随停,可以在短时间内完成,也可以暂停直到空闲时来完成,这款飞机大战是在雷霆战机的基础上进行些许的修改,所使用的思路也是延续了大多数的飞机大战,为编写代码打下来一定的基础。
2.3 设计功能分析
设计功能分析在整个项目之中有着不可或缺的地位,我们对整个项目进行分析,这将会决定这个游戏的完善性以及稳定性。在设计功能分析中,我们将实现整个游戏的构想。
2.4 游戏构想
飞机大战小游戏是为了仿制童年的游戏而开发出来的,顾名思义,游戏规则也是非常的显而易见。玩家通过操纵英雄机器来射击敌机来闯关,每关结束时都有一个大Boss,总共有三关,如果玩家能够全部通过则胜利,每击毁一架敌机敌机都会获得相应的分数,当玩家拥有足够的分数,则会出动boss机,boss机拥有着小敌机无可匹敌的力量与生命,当然击落boss机有着巨大的得分奖励,前提是你得活下来,当然,为了减轻游戏的难度,我们会派出一些血包,弹药包,以及大招包来帮助玩家度过难关。
根据此游戏设计的基本构想,主要涉及到的对象如下:
1、英雄机:通过鼠标的移动来控制英雄机的移动,子弹会自动发射,尽可能的消灭更多的敌人吧。
2、小敌机:本游戏中有三种小敌机,有不同的攻击模式,希望你能撑住很久喔。
3、Boss机:本游戏有三种boss机,随着玩家的分数越来越高,boss机会一一出现,一架更比一架强,最后有着极厚的血量以及频繁的攻击模式。
4、补血包:当玩家碰撞到此补血包时,会补充一定的生命值哦。
5、弹药包:当玩家碰撞到此弹药包时,会在一定的时间内获得双倍火力。
6、大招储备:当玩家碰撞到此包时,会触发大招,获得清屏的能力,但并不会清掉boss机,但会对其造成可观的伤害。
用户们驾驶的英雄机会固定在界面上,其他的游戏组件则是出了界面之外就会消失,boss机除外,只有击败boss机,才会结束游戏。
2.5 游戏流程分析
2.5.1游戏界面流程
当玩家进入游戏时,首先是进入的是开始状态,此页面提示点击鼠标左键开始游戏,当玩家点击左键时游戏开始,当游戏在运行状态的时候,点击鼠标右键,或者鼠标移出游戏界面,游戏会自动进入暂停状态,再次点击左键或者将鼠标移入界面,即可自动继续游戏,当玩家击败了所有的boss机时,则进入胜利界面,如若在游戏过程中,英雄机的血条消失,则英雄机坠毁,进入失败页面。
游戏界面流程如图2.1用户界面流程图。
图2.1 用户界面流程图
2.5.2游戏状态流程
讲述完了游戏界面的流程,接下来进入游戏状态的流程,这个环节非常的简单,此游戏分为三个关卡,每一个关卡小敌机的变化并不大,主要是boss机的改变,血量加厚,速度的些许改变。
接下来以流程图的方式讲解游戏状态的流程,见图2.2游戏状态流程图。
图2.2 游戏状态流程图
游戏状态的截图,因小敌机的模型与属性相差不大,便只取一张图,见图2.3小敌机截图,图2.4boss机1截图,图2.5boss2机截图,图2.6boss3机截图。
图2.3 小敌机截图
图2.4 boss机1截图
图2.5 boss2机截图
图2.6 boss3机截图
以在此游戏中找到最初的乐趣。
2.5.3游戏关卡流程
游戏关卡是如何判定的,用判断流程图来更清晰的展示,如图2.7游戏关卡流程图。
图2.7 游戏关卡流程图
2.6 素材准备与界面设计
在飞机大战游戏中,使用了大量的图片素材。图片的种类繁多,各有各的功能,以下将对其进行简单的介绍。
2.6.1界面设计
游戏中有许多的状态,在不同状态有不同的界面,这些界面都有各自的背景图片,如图2.8游戏暂停界面,图2.9 游戏开始界面,图2.10游戏胜利界面。
图2.8 游戏暂停界面
图2.9 游戏开始界面
图2.10 游戏胜利界面\
3 具体分析
3.1 构造设计
3.1.1 构造方法
PlanePanel(){
addMouseMotionListener(this);//将鼠标事件(this)与面板连接
addMouseListener(this);
}
这是本类PlanePanel类的无参构造。
鼠标的监听只有在物体都加载完成后才用监听鼠标,所以只需要在构造方法中使鼠标事件与面板连接即可。
3.1.2 静态代码块
在静态代码块中,我们需要加载游戏一开始就需要的对象,所以将他们放在静态代码块中第一时间执行,构成游戏的框架。需要预加载的对象如下:
创建开始画面图片对象
创建停止画面图片对象;
创建胜利画面图片对象;
创建胜利画面图片对象;
创建背景图片对象;
创建生命值图片对象;
创建得分图片对象;
创boss生命值图片对象。
3.2 变量设计
构想这个游戏中所有的物体所需要的变量,定义这些全局变量,并在后续的设计中使用他们。变量的声明如下:
声明类型为整型的开始,运行,暂停,胜利,结束画面状态的变量,且赋值为0;
声明类型为整型的分数的变量,且赋值为0;
定义血量宽度为200像素;
定义boss1血量宽度为300像素;
定义boss2血量宽度为400像素;
定义boss3血量宽度为500像素;
声明背景图片的横纵坐标的变量,且赋值为0;
声明start的横纵坐标的变量,且赋值为0;
声明stop的横纵坐标的变量,且赋值为0;
声明GameOver的横纵坐标的变量,且赋值为0;
声明胜利标志的横纵坐标的变量,且赋值为0;
声明生命标志的横纵坐标的变量,且赋值为0;
声明得分标志的横纵坐标的变量,且赋值为0;
声明boss生命的标志的横纵坐标变量,且赋值为0;
定义关卡的坐标变量,且赋值为0;
定义大招的变量,且赋值为0。
3.3 状态设计
本游戏一共分为5个状态,初始状态,运行状态,暂停状态,结束状态,胜利状态,分别用数字0,1,2,3,4来表示,下面开始具体结束,如何实现状态的画图。
3.3.1 初始状态
如果状态为等于0的时候,就是初始状态的时候:
g.drawImage(stImg,stx,sty,null);
画出start背景的图片。
Font f = new Font(“”,Font.BOLD,30);
g.setFont(f);//设置准备好的字符格式
g.setColor(Color.GREEN);//设置颜色
g.drawString(“点击鼠标左键开始”,300,200);//显示字符在什么位置
3.3.2 运行状态
如果状态为等于1的时候,就是运行状态的时候:
绘制背景图片,代码如下:
g.drawImage(bkImg,bx,by,null);
g.drawImage(bkImg,bx,by-9999,null);
画冲撞机1,画冲撞机2,画冲撞机3,画子弹,画奖励,画奖励2,画奖励3,
画生命标志,第一个参数是生命标志的图片,第二三个参数是图片横纵坐标,
画分数标志,设置字体颜色为白色,声明一个font类型的变量f,
Font f = new Font(“”,Font.BOLD,22);
设置准备好的字符格式,画分数,设置颜色,画生命绿条,
画boss1,画boss1的子弹,画boss2,画boss2的子弹,
画boss3,画boss3的子弹,画大招
画主战机。
3.3.3 暂停状态
如果状态为等于2的时候,就是暂停状态的时候:
g.drawImage(spImg,spx,spy,null);
drawImage()方法是画笔算法里的自带方法,需要本类去继承JPanel类才有的画笔算法。
3.3.4 结束状态
如果状态为等于3的时候,也就是结束状态的时候:
画出GameOver的图片,
设置已经自定义好的字体,
设置颜色为红色,
打印出GameOver的字符串在指定的位置。
调用GameOver的图片,确定横纵坐标,定义字体格式,用画笔g调用setFont,setColor,drawString这三个方法,分别意为设置已经定义的字体格式,设置颜色,画出字符在坐标上。
3.3.5 胜利状态
判断胜利状态的是boss3的血量是否是小于0 的,如果是,则进入状态4,也就是胜利状态,
当状态等于胜利状态的时候,
画出胜利界面在指定的位置上,
设置好已经定义好的字体格式,
设置字体的颜色,
打印出"You Are Winer!"在指定的位置。
如果boss机3的血量宽度小于0,则进入胜利状态,如果是胜利状态,则画出胜利界面,并以设置的字体格式打出字符串在自定的坐标位置。
3.4 操作设计
在游戏中用鼠标即可完成所有的操作,则只需在PlanePanel类中实现MouseMotionListener接口和MouseListener接口,重写其mouseMoved(),mouseClicked(),mouseEntered(),mouseExited()等方法。
3.4.1 鼠标的移动
定义一个鼠标移动的含参方法,参数则是鼠标,
得到鼠标的横纵坐标,
将鼠标的x坐标赋给英雄机,
将鼠标的y坐标赋给英雄机
这是控制出界的设置:
if(hero.x<-8){ hero.x = -8;}//控制左出界
if(hero.x+hero.heroImg.getWidth(null)>900){//控制右出界
hero.x = 900-hero.heroImg.getWidth(null);
}
if(hero.y<0){ hero.y = 0;}//控制上出界
if(hero.y+hero.heroImg.getHeight(null)>768){//控制下出界
hero.y = 768-hero.heroImg.getHeight(null);
}
定义鼠标移动的方法mouseMoved,通过java.awt.event包下的MouseEvent类创建鼠标对象e,这是jdk包中自带的,可以通过引用java.awt.event包可直接调用,定义类型为int类型的mx,my对象赋予其鼠标的横纵坐标,getX()方法,getY()依然是对象e自带包中的,可以通过导包直接引用,将得到的鼠标横坐标减去英雄机图片的宽度除以二,同时将其赋予英雄机的横坐标,便可达到将鼠标的x坐标赋给英雄机,将得到的鼠标纵坐标减去英雄机图片的高度除以二,同时将其赋予英雄机的纵坐标,便可达到将鼠标的y坐标赋给英雄机,同时需要控制英雄机不能移出界面,如果英雄机的横坐标加上英雄机图片的宽度大于我们定义的游戏边框的宽度,则判断其出界,则将英雄机的横坐标固定为游戏边框宽度减去英雄机图片的宽度,同理,控制上方出界,则使英雄机纵坐标为0,当英雄机的纵坐标加上英雄机图片的高度大于定义游戏边框的高度,则是下出界,将英雄机的纵坐标使其等于边框高度减去英雄机图片高度。
3.4.2 鼠标的点击
定义一个鼠标点击的方法,
获取鼠标的横纵坐标,
如果鼠标的点击事件是点击左键,
则进入状态1,也就是运行状态,
如果鼠标的点击事件是点击右键,
则进入状态2,也就是暂停状态。
定义鼠标的点击方法mouseClicked,依然是含参的,参数依然是java.awt.event包下的MouseEvent类创建鼠标对象e,e.BUTTON1,e.BUTTON2,e.BUTTON3都是指示鼠标按键,都由getButton()使用,经测试,BUTTON1是左键,BUTTON2是滚轮,BUTTON3是右键,e.getButton()方法是返回更改了状态的鼠标按键(如果有)。则代码的含义就为如果鼠标按键的状态是点击了左键,则将状态赋值1,如果鼠标按键的状态是点击了右键,则将状态赋值2,状态则在全局变量中声明过了,1则是开始,2是暂停。
3.4.3 鼠标的移入
定义一个鼠标移入的方法,
如果状态是暂停状态的话,鼠标移入,
则进入运行状态。
定义鼠标的移入方法,参数依然是java.awt.event包下的MouseEvent类创建鼠标对象e,当鼠标移入界面,如果状态为2暂停状态,则将状态赋值1为运行状态。
3.4.4 鼠标的移出
定义一个鼠标移出的方法,
如果状态是运行状态的话,鼠标移出,
则进入暂停状态。
定义鼠标的移出方法,参数依然是java.awt.event包下的MouseEvent类创建鼠标对象e,当鼠标移出界面,如果状态为1运行状态,则将状态赋值2为暂停状态。
上面的几个方法都是方法的重写。
上面的鼠标的点击,移动,移入移出方法则是本类同时实现了MouseMotionListener,MouseListener两个接口类而重写了其抽象方法而得出的。
3.5 算法设计
通过上面的介绍,可知道这个游戏有许多对象的产生,包括产生敌机,产生奖励包这些对象,生成他们的算法,以及他们的移动的算法。
3.5.1 随机生成敌机算法
我们利用随机函数Random()来控制小敌机出现的概率,且将出现的小敌机放入相应的ArrayList集合中,每一种小敌机都有相应的集合。当获取的分数达到一定的值后,则在屏幕上生成boss机。奖励包的机制与敌机一样。
创建存储子弹数组的集合,
创建存储奖励的集合,泛型是Award,
创建存储奖励2的集合,泛型是Award2,
创建存储奖励3的集合,泛型是Award3,
创建冲撞机1的集合,泛型是Crash1,
创建冲撞机2的集合,泛型是Crash2,
创建冲撞机3的集合,泛型是Crash3,
将boss机1,2,3的子弹数组存放进入一个集合。
这里的集合使用的是ArrayList集合,因为继承了Collection接口下的子接口List接口,用图4.1简单描述一下他的继承结构。如图4.1集合的继承结构。
图4.1 集合的继承结构
因为ArrayList继承了List接口,所有存储在ArrayList集合中的数据井然有序,并且可以重复,而且各个元素都有自己的索引,使得找到某个元素很方便,通过查看他的源码可以得知,他的底层是一个数组,他是封装了数组的操作,且数组的初始容量是10,如果不够的话会以1.5倍的容量增长,他虽然查询快,但是增删数据的效率就降低了许多。
3.5.2 敌机和奖励包的移动算法
奖励包和敌机的移动属于同一种形式,都是在随机生成后,按照往下的方向移动,通过变量speed来控制他们的飞行速度,变量x,y来控制横向以及纵向的移动,小敌机同样依赖Random()方法在屏幕上方随机横向产生,垂直下落,奖励包则设置xSpeed和ySpeed两个变量来控制奖励包在界面中的左右移动,且在移动时判断触碰边界的轨道。
if(x+awardImg.getWidth(null)>=900){
if(state0){state=1;}
}
//奖励碰到左边界的处理
if(x<=-21){
if(state1){state=0;}
这里代码用来处理碰到边界后的处理方式,将变量state定义为状态,如果奖励包触碰到左右边界,则改变状态,及向反方向运行。
3.5.3 碰撞检测算法
在此游戏中,碰撞是家常便饭,所有的碰撞检测及处理很重要,所有的对象都由图片构成,则图片为矩形,当图片的边角进入另一张图片的边角领域,则视为碰撞,如果发生碰撞,则直接调用ArrayList中的remove方法,直接使对象消失。
在此以其中某一个奖励包为例
定义边角像素点的位置变量,
判断图片是否发生碰撞,如果碰撞则移出集合。
如果是英雄机发生碰撞,则是掉一定的血量。如果碰撞过多,导致英雄机血量降低为0,则判断英雄机坠毁,游戏失败。
3.5.4 背景音乐算法
此游戏中背景音乐也是一大特色,相比经典的飞机大战所使用激情澎湃的背景音乐,这里显得别具一格,反其道而行之,选用舒适祥和的音乐,让人忘记烦恼,缓解疲惫。
先创建一个文件对象用来存储背景音乐的路径,然后直接调用Applet类中的newAudioClip()方法通过传参来调用背景音乐。
bg1 = Applet.newAudioClip(bgUrl_1);
再在启动类PlaneFrame中调用Music类中bg1属性的loop()方法来达到播放背景音乐的目的。
Music.bg1.loop();// 播放音乐
3.5.5 画笔算法
在Graphics类中将GUI看做了一张画纸,将其看做画笔,就能用其中的方法显示图像,在JVM中,会自动去为开发者创建一个Graphics对象,我们则可以通过传递对象来调用他的paintComponent(Graphics g)。我们则通过其drawImage方法来画出我们所需要的小敌机,英雄机,boss机以及奖励包。drawImage中包含多个参数,img表示画出的指定的图像,x代表横向的坐标,y代表纵向坐标,width代表在画面中的高度,height代表在画布上矩形的高度。因为画小敌机,英雄机,子弹,boss机,奖励包的画笔方法都一样,在此只选择一个代码块来展示。
算法伪码
定义boss生命的方法,
如果boss1不存在,
创建一个新的ImageIcon对象,将图片路径传进参数,用来获取图片,
mis1Img = new ImageIcon(“symbol/mission1.png”).getImage();
画关卡标志,
画boss的生命标志,
设置颜色为绿色,
画boss生命绿条在指定的位置,
画出boss1图片。
3.5.6 定时器算法
算法伪码
创建一个定时器Timer对象
调用定时器对象的计划方法,参数是一个计划任务对象,
在内部类中定义其任务运行的方法,
在这个定时器中,需要定时的有
英雄机图片的切换,
子弹的产生,
子弹的移动,
奖励1,2,3的产生,
奖励1,2,3的移动,
冲撞机1,2,3的产生,
冲撞机1,2,3的移动,
对子弹,敌机,奖励出界的处理,
对得分的处理,
吃奖励增加的生命,
减少的生命,
boss1,2,3的产生,
boss1,2,3的移动,
boss1,2,3子弹的生成
boss1,2,3子弹的移动
增加的火力,
触发的大招,
大招的产生,
重绘与刷新。
我们需要创建一个定时器在游戏启动的时候就要不停的创建敌人对象从上面掉下来,我们首先先创建定时器对象timer,并调用它的schedule()方法,其参数的意思是在等待delay毫秒后首次执行task,每隔period毫秒重复执行task。告诉定时器程序启动之后多久启动这个定时器,以及该定时器每隔多久重复执行一次定时任务,所以现在我们有三个未知因素:
1.程序运行之后多久启动这个定时器
2.定时器每隔多久执行一次定时任务
3.定时任务写哪里
我们设置程序运行0毫秒后直接启动定时器,每隔10毫秒执行一次定时任务,在TimerTask对象中重写它的运行方法,其方法是此计时器任务要执行的操作,所以将我们需要计时的任务写在里面即可完成这个计时器。
3.5.7 出界算法
算法伪码
//子弹,敌机,奖励出界的处理
定义出界的方法,
创建循环,循环大小为子弹数,
获取子弹数组中每一颗子弹,
如果现有子弹的纵坐标加上子弹图片的宽度小于等于0,
则移除子弹,
创建冲撞机循环,
获取每一个冲撞机数组中的冲撞机,
如果现在的冲撞机的纵坐标加上图片的高度大于界面的高度,
则移除冲撞机,
奖励也同样是如此,
//删除越界的Boss子弹,
同样,如果是子弹出界,则移除子弹。
当子弹,小敌机以及奖励包出界时,需要将这些物体删除,判断物体的纵坐标加上图片的宽度是否大于边界,如果是的话则调用ArrayList中的remove()方法将物体从数组中移除出去,在将其放入到循环中去,循环的限制是其物体数组的大小,这样就会不断的判断是否有物体出界,并将其做出界处理。这就是出界算法。
4 运行调试
在做整个项目中,我们需要很多次的运行调试,来测试我们程序的完整性以及复用性,接下来将我们在运行调试中出现的一些问题展示出来。
4.1 背景测试
在制作背景时,有时会出现画面不显示,画面重叠或者一些奇怪的问题,在运行调试时出现了如下图片的状况,如图4.1背景测试图。
图4.1 背景测试图
我们判断应该是图片的问题,于是我们在静态代码块中进行了一些调整与测试,调整如下:
static{
try{
stImg = new ImageIcon(“SSOVER/start.png”).getImage();
spImg = new ImageIcon(“SSOVER/stop.jpg”).getImage();
winImg = new ImageIcon(“SSOVER/winer.png”).getImage();
goImg = new ImageIcon(“SSOVER/winer.png”).getImage();
bkImg = new ImageIcon(“sources/background.png”).getImage();
lfImg = new ImageIcon(“symbol/life.png”).getImage();
scImg = new ImageIcon(“symbol/score.png”).getImage();
bosslifeImg = new ImageIcon(“symbol/bosslife.png”).getImage();
}catch(Exception e){
System.out.println(“看图片名称写错没,图片中没有空格”);
e.printStackTrace();
}
}
我们将图片的对象创建及路径引用写入try catch代码块中,如果出现了与图片相关的问题,则会在console中报出提示,使我们及时更正,否则这将不会在程序中报错,避免了许多不必要的麻烦。
4.2 物体测试
PlanePanel(){
hero = new Hero();
flyings = new FlyingObject[2];
flyings[0] = new Airplane();
flyings[1] = new Bee();
bullets = new Bullet[1];
bullets[0] = new Bullet(100,200);
}
这段代码只用在了测试中,我们需要知道物体能否很好的呈现在界面上,即使他们不会运动,我们在构造方法中将一些基础的物体呈现在界面上。
4.3 碰撞测试
在测试的时候有时候会遇见子弹从敌机中穿过去了,子弹击中了敌机却没有消失,或者奖励包对与英雄机发生不了碰撞反应,导致英雄机无法吃到奖励包,使得游戏的体验极其糟糕,无法获得补给包,不能够对敌机造成伤害,这些通过判断应该是英雄机,敌机,补给包这些物体的坐标问题,或者是碰撞的机制出现了问题,使得发生了穿模现象。我们将这段代码进行碰撞的测试。如图4.2碰撞测试图。
图4.2碰撞测试图。
/ * 判断敌人是否被子弹撞击
* 方法中的this表示敌人*/
public boolean shootBy(Bullet bullet){
int x = bullet.x;//子弹的x
int y = bullet.y;//子弹的y
int x1 = this.x;//敌人的x1
int x2 = this.x + this.width;//敌人的x2
int y1 = this.y;//敌人的y1
int y2 = this.y + this.height;//敌人的y2
return x >= x1 && x <= x2 && y >= y1 && y <= y2;
}
4.4 出界测试
当小敌机,子弹,奖励包这些物体明明已经达到了顶端或者底端,却仍然没有消失,使得界面看起来杂乱无章,物体又多,影响玩家的游戏体验,这绝不会出现在玩家的眼中,我们会在需要的类中加上越界判定,因为代码几乎相同,在这里只举出小敌机的代码测试。
public boolean outOfBounds() {
System.out.println(“小敌机是否越界”);
return this.y >= PlanePanel.HEIGHT;
}
这样就可以得知小敌机,子弹,奖励包是否越界。
总 结
从论文选题十一月开始,到如今已经过去了五个月,时间转瞬即逝,不知不觉我们的毕业论文已经接近了尾声,我从堪堪将论文的代码写完,到将整个项目完成,这接近五个月的敲写代码,让我受益匪浅,对Java语言有了更深入的了解。
我原本并不是飞机大战这份课题,后来与老师商量改成了飞机大战的开发与设计,这个课题与我在达内科技培训时做的项目有些许相似,正好我想给那个项目进行完善与修改功能,这正好老师给了我这个机会,让我对这个项目进行了完善,同时也完成了我的毕业设计,不然我的时间是必然不够的,同时也磨炼了我对Java语言的使用的熟练度,让我更深入的理解了Java面向对象的这个特性,真的是万物皆对象,虽然这句话从现在的我口中说出不太现实,但确定,我经历了这次项目,让我初窥了Java庞大的语言体系。这个项目充分运用了父子类的继承,为其降低耦合性,大量使用接口与实现类的实现以及抽象类。
经过了这五个月的努力,总算做出了一个像样的项目,本以为这几个月会很漫长,没想到因为疫情的缘故,一眨眼时间就过去了,也快到了毕业的时间,回首相望,仿佛初入校园还在昨日,一开始的时候还为选择了计算机行业所懊恼,我们专业不仅学了计算机也在同时学习数学,两种学科都不是轻而易举所能学会的。学习了四年,只是初学皮毛,远远没有踏进计算机语言的大门,属实令我有些心生退意,但在这五个月的钻研与探索下,我选择Java语言,深入钻研,似乎并没有我想象的那么枯燥,它再用自己独特的语言方式来为我展现代码的美丽,语言是美丽,尽管它不是人类的语言,它是计算机的语言,它让我感受到了什么叫人机交互,让我们读懂计算机的语言。开始的时候总是很枯燥,看见代码就头大,更别说去钻研源码了,都说会读源码就是很大的提升,我从一个一开始连helloworld都不会的小白,逐渐成长为能写出一个飞机大战的项目的程序员,尽管其中有许许多多的人的帮助与个鼓励,也依然使我成长。我会更加的努力成为一名合格的程序员。
之间我也遇到许多的挫折与瓶颈,没有明确的框架,没有完善的思路,总是缺东少西,对代码的完整性,完善性不够,到处出现bug,不断的断点测试,debug程序,找错误,删bug,在bug中做程序,一路走来,才勉勉强强算完成一个项目,之中也少不了很多人的帮助,才能一路坎坷走到这里。
这个游戏经过具体设计后拥有着新颖的界面,地图,特别的关卡与音效,让用户在一段时间内获取精神上的放松,多用于课余与休闲期间起到放松用户的作用,且刺激的关卡可以帮助用户保持一定的集中力,且越到后面的关卡,越能锻炼用户的反应力,集中力与手速,起到一定的锻炼作用,是放松兼锻炼及一体的功能性设计,这更像是我们的标志,也是我们的初心。
如果以后有时间的话,我会对这份项目再进行一些改良,理应将MVC的设计模式应用进去,使其降低耦合性,也可以使得代码更具有复用性,也可以将其整合进入SSM框架中,也就是spring,springmvc,mybatis框架中去,将这个项目包装成web项目,做好登录页面以及数据库,将其发展为一个线上游戏,从而来让玩家们感受到联机的快乐,也带给玩家更多的乐趣。
附 录
package 飞机大战;
import java.awt.Image;
import java.util.Random;
import javax.swing.ImageIcon;
public class Award {
static Image awardImg;
int x,y;
int xSpeed =1,ySpeed =2;
int state;
static{
awardImg = new ImageIcon("sources/gold.png").getImage();
}
Award(){
Random ran = new Random();
state = ran.nextInt(1);
x = ran.nextInt(900-awardImg.getWidth(null));
y = -awardImg.getHeight(null);
}
//奖励的移动
int awardIndex=0;
public void move(){
//奖励的移动
//奖励状态的判断
if(state==0){
x = x+xSpeed ;
y = y+ySpeed;
}
if(state==1){
x =x-xSpeed;
y =y+ySpeed;
}
//奖励碰到右边界的处理
if(x+awardImg.getWidth(null)>=900){
if(state==0){state=1;}
}
//奖励碰到左边界的处理
if(x<=-21){
if(state==1){state=0;}
}
}
}
package 飞机大战;
import java.awt.Image;
import java.util.Random;
import javax.swing.ImageIcon;
public class Award2 {
static Image award2Img;
int x,y;
int xSpeed =1,ySpeed =2;
int state;
static{
award2Img = new ImageIcon("sources/addfire1.png").getImage();
}
Award2(){
Random ran = new Random();
state = ran.nextInt(1);
x = ran.nextInt(900-award2Img.getWidth(null));
y = -award2Img.getHeight(null);
}
//奖励的移动
int awardIndex=0;
public void move(){
//奖励的移动
//奖励状态的判断
if(state==0){
x = x+xSpeed ;
y = y+ySpeed;
}
if(state==1){
x =x-xSpeed;
y =y+ySpeed;
}
//奖励碰到右边界的处理
if(x+award2Img.getWidth(null)>=900){
if(state==0){state=1;}
}
//奖励碰到左边界的处理
if(x<=-21){
if(state==1){state=0;}
}
}
}
package 飞机大战;
import java.awt.Image;
import java.util.Random;
import javax.swing.ImageIcon;
public class Award3 {
static Image award3Img;
int x,y;
int xSpeed =1,ySpeed =2;
int state;
static{
award3Img = new ImageIcon("sources/addfire2.png").getImage();
}
Award3(){
Random ran = new Random();
state = ran.nextInt(1);
x = ran.nextInt(900-award3Img.getWidth(null));
y = -award3Img.getHeight(null);
}
//奖励的移动
int awardIndex=0;
public void move(){
//奖励的移动
//奖励状态的判断
if(state==0){
x = x+xSpeed ;
y = y+ySpeed;
}
if(state==1){
x =x-xSpeed;
y =y+ySpeed;
}
//奖励碰到右边界的处理
if(x+award3Img.getWidth(null)>=900){
if(state==0){state=1;}
}
//奖励碰到左边界的处理
if(x<=-21){
if(state==1){state=0;}
}
}
}
package 飞机大战;
import java.awt.Image;
import java.util.Random;
import javax.swing.ImageIcon;
import 飞机大战.Boss1bullet;
public class Boss1 {
static Image Boss1Img;
int x,y;
int xSpeed=1;
int ySpeed=2;
static{
Boss1Img = new ImageIcon("boss/boss1.png").getImage();
}
//构造
Boss1(){
x = 50;
y = -200;
}
//boss1的运动
public void move(){
y+=ySpeed;
if(y>=100){
y=100;
x+=xSpeed;
}
//碰到了右边界
if(x+Boss1Img.getWidth(null)>=800){
xSpeed=-xSpeed;
}
//碰到了左边界
if(x<=0){
xSpeed=-xSpeed;
}
}
//Boss机产生子弹
public Boss1bullet[] shoot(){
//创建一个数组
Boss1bullet[] bb = new Boss1bullet[2];//数组个数为2
int width = Boss1Img.getWidth(null);
int height = Boss1Img.getHeight(null);
bb[0] = new Boss1bullet(x+width/4,y+height+5);//子弹的位置
bb[1] = new Boss1bullet(x+width*3/4,y+height+5);//子弹的位置
return bb;
}
}
package 飞机大战;
import java.awt.Image;
import javax.swing.ImageIcon;
public class Boss1bullet {
//一堆属性
public static Image bbImg;
public int x,y;
public int speed = 2;
public boolean isHit = false;
static{
bbImg = new ImageIcon("bullet/enemybullet01.png").getImage();
}
//构造,有参构造,两个整数类型的参数确定
//产生的子弹的位置
public Boss1bullet(int x,int y){
this.x=x;
this.y=y;
}
//子弹图片的切换以及子弹的运动
public void step(){
y+=speed;
}
}
package 飞机大战;
import java.awt.Image;
import javax.swing.ImageIcon;
public class Boss2 {
static Image Boss2Img;
int x,y;
int xSpeed=2;
int ySpeed=2;
static{
Boss2Img = new ImageIcon("boss/boss2.png").getImage();
}
//构造函数
Boss2(){
x = 500;
y = -200;
}
//boss2的运动
public void move(){
y+=ySpeed;
if(y>=100){
y=100;
x-=xSpeed;
}
//碰到了右边界
if(x+Boss2Img.getWidth(null)>=800){
xSpeed=-xSpeed;
}
//碰到了左边界
if(x<=0){
xSpeed=-xSpeed;
}
}
//Boss机产生子弹
public Boss2bullet[] shoot(){
//创建一个数组
Boss2bullet[] bb2 = new Boss2bullet[2];//数组个数为2
int width = Boss2Img.getWidth(null);
int height = Boss2Img.getHeight(null);
bb2[0] = new Boss2bullet(x+width/4,y+height+5);//子弹的位置
bb2[1] = new Boss2bullet(x+width*3/4,y+height+5);//子弹的位置
return bb2;
}
}
package 飞机大战;
import java.awt.Image;
import javax.swing.ImageIcon;
public class Boss2bullet {
//一堆属性
public static Image bbImg;
public int x,y;
public int speed = 2;
public boolean isHit = false;
static{
bbImg = new ImageIcon("bullet/enemybullet02.png").getImage();
}
//构造,有参构造,两个整数类型的参数确定
//产生的子弹的位置
public Boss2bullet(int x,int y){
this.x=x;
this.y=y;
}
//子弹图片的切换以及子弹的运动
public void step(){
y+=speed;
}
}
package 飞机大战;
import java.awt.Image;
import javax.swing.ImageIcon;
public class Boss3 {
static Image Boss3Img;
int x,y;
int xSpeed=1;
int ySpeed=1;
static{
Boss3Img = new ImageIcon("boss/boss3.png").getImage();
}
//构造函数
Boss3(){
x = 500;
y = -200;
}
//boss3的运动
public void move(){
y+=ySpeed;
if(y>=100){
y=100;
x-=xSpeed;
}
//碰到了右边界
if(x+Boss3Img.getWidth(null)>=800){
xSpeed=-xSpeed;
}
//碰到了左边界
if(x<=0){
xSpeed=-xSpeed;
}
}
//Boss机产生子弹
public Boss3bullet[] shoot(){
//创建一个数组
Boss3bullet[] bb3 = new Boss3bullet[2];//数组个数为2
int width = Boss3Img.getWidth(null);
int height = Boss3Img.getHeight(null);
bb3[0] = new Boss3bullet(x+width/4,y+height+5);//子弹的位置
bb3[1] = new Boss3bullet(x+width*3/4,y+height+5);//子弹的位置
return bb3;
}
}
package 飞机大战;
import java.awt.Image;
import javax.swing.ImageIcon;
public class Boss3bullet {
//一堆属性
public static Image bbImg;
public int x,y;
public int speed = 3;
public boolean isHit = false;
static{
bbImg = new ImageIcon("bullet/enemybullet03.png").getImage();
}
//构造,有参构造,两个整数类型的参数确定
//产生的子弹的位置
public Boss3bullet(int x,int y){
this.x=x;
this.y=y;
}
//子弹图片的切换以及子弹的运动
public void step(){
y+=speed;
}
}
package 飞机大战;
import java.awt.Image;
import javax.swing.ImageIcon;
public class Bullets {
//属性
static Image bulletImg;//图片的属性
int x,y;//子弹坐标
static{
bulletImg = new ImageIcon("sources/herobullet1.png").getImage();
}
//含参构造
Bullets(int x,int y){
this.x = x;
this.y = y;
}
//子弹的移动
public void move(){
y-=2;
}
}
package 飞机大战;
import java.awt.Image;
import java.util.Random;
import javax.swing.ImageIcon;
public class Crash1 {
static Image crash1Img;
int x,y;
Random random = new Random();
static{
crash1Img = new ImageIcon("crash/rash1.png").getImage();
}
//构造
Crash1(){
x = random.nextInt(900-crash1Img.getWidth(null));
y = -crash1Img.getHeight(null);
}
//冲撞机1的运动
public void move(){
//更改y坐标
y+=3;
}
}
package 飞机大战;
import java.awt.Image;
import java.util.Random;
import javax.swing.ImageIcon;
public class Crash2 {
static Image crash2Img;
int x,y;
Random random = new Random();
static{
crash2Img = new ImageIcon("crash/rash3.png").getImage();
}
//构造
Crash2(){
x = -crash2Img.getWidth(null);
y = random.nextInt(768-crash2Img.getHeight(null));
}
//冲撞机2的运动
public void move(){
//更改x坐标
x+=2;
}
}
package 飞机大战;
import java.awt.Image;
import javax.swing.ImageIcon;
public class Crash3 {
static Image crash3Img;
int x,y;
static{
crash3Img = new ImageIcon("crash/rash2.png").getImage();
}
//构造函数
Crash3(){
x =-crash3Img.getWidth(null);
y =70;
}
//冲撞机2的运动
public void move(){
//更改y坐标
x++;
if(x+crash3Img.getWidth(null)>=400){
x=400;
y+=6;
}
}
}
package 飞机大战;
import java.awt.Image;
import javax.swing.ImageIcon;
public class Dazhao {
static Image DazhaoImg;
int x,y;
static{//画大招
DazhaoImg = new ImageIcon("sources/dazhao.png").getImage();
}
Dazhao(){
x = 0;
y = 0;
}
}
package 飞机大战;
import java.awt.Image;
import java.util.Random;
import javax.swing.ImageIcon;
public class Enemy1 {
static Image enemyImg;
static Image[] enemyImgs = new Image[3];
int x,y;
Random random = new Random();
static{
enemyImg = new ImageIcon("sources/enemy00.png").getImage();
for(int i=0;i<enemyImgs.length;i++){
enemyImgs[i] = new ImageIcon("sources/enemy0"+i+".png").getImage();
}
}
//构造函数
Enemy1(){
x = random.nextInt(448-enemyImg.getWidth(null));
y = -enemyImg.getHeight(null);
}
//敌机图片切换的方法及运动
int enemyIndex = 0;
public void step1(){
//更改y坐标
y+=3;
//切换图标
if(enemyIndex==Integer.MAX_VALUE){
enemyIndex = 0;
}
int i = enemyIndex++/30%enemyImgs.length;
enemyImg = enemyImgs[i];
}
}
package 飞机大战;
import java.awt.Image;
import java.util.Random;
import javax.swing.ImageIcon;
public class Enemy2 {
static Image enemyImg;
static Image[] enemyImgs = new Image[3];
int x,y;
Random random = new Random();
static{
enemyImg = new ImageIcon("sources/enemy0.png").getImage();
for(int i=0;i<enemyImgs.length;i++){
enemyImgs[i] = new ImageIcon("sources/enemy"+i+".png").getImage();
}
}
//构造函数
Enemy2(){
x = random.nextInt(448-enemyImg.getWidth(null));
y = -enemyImg.getHeight(null);
}
//敌机图片切换的方法及运动
int enemyIndex = 0;
public void step2(){
//更改y坐标
y+=2;
//切换图标
if(enemyIndex==Integer.MAX_VALUE){
enemyIndex = 0;
}
int i = enemyIndex++/30%enemyImgs.length;
enemyImg = enemyImgs[i];
}
}
package 飞机大战;
import java.awt.Image;
import java.util.Random;
import javax.swing.ImageIcon;
public class Enemy3 {
static Image enemyImg;
static Image[] enemyImgs = new Image[3];
int x,y;
Random random = new Random();
static{
enemyImg = new ImageIcon("sources/enemy000.png").getImage();
for(int i=0;i<enemyImgs.length;i++){
enemyImgs[i] = new ImageIcon("sources/enemy00"+i+".png").getImage();
}
}
//构造函数
Enemy3(){
x = random.nextInt(448-enemyImg.getWidth(null));
y = -enemyImg.getHeight(null);
}
//敌机图片切换的方法及运动
int enemyIndex = 0;
public void step3(){
//更改y坐标
y+=1;
//切换图标
if(enemyIndex==Integer.MAX_VALUE){
enemyIndex = 0;
}
int i = enemyIndex++/30%enemyImgs.length;
enemyImg = enemyImgs[i];
}
}
package 飞机大战;
import java.awt.Image;
import javax.swing.ImageIcon;
import 飞机大战.Bullets;
public class Hero {
static Image heroImg;//默认要绘制的图片属性
static Image[] heroImgs = new Image[10];
int x,y;
static{//静态代码块
heroImg = new ImageIcon("sources/hero00.png").getImage();
for(int i=0;i<heroImgs.length;i++){
heroImgs[i] = new ImageIcon("sources/hero0"+i+".png").getImage();
}
}
//含参构造
public int doubleFire;//火力值
Hero(int x,int y){
doubleFire=0;
this.x = x;
this.y = y;
}
//图片切换的方法
int heroIndex = 0;
public void step(){
if(heroIndex==Integer.MAX_VALUE){
heroIndex = 0;
}
int i = heroIndex++/5%heroImgs.length;
heroImg = heroImgs[i];
}
//英雄机发射子弹的方法
public Bullets[] shoot(){
if(doubleFire>0){//返回双倍火力
//x1表示双倍火力时,左边那一个子弹的x坐标
//x2表示双倍火力时,右边那一个子弹的x坐标
int x1 = x+heroImg.getWidth(null)/3;
int x2 = x+heroImg.getWidth(null)*2/3;
int y = this.y-10;
Bullets bullet1 = new Bullets(x1,y);
Bullets bullet2 = new Bullets(x2,y);
Bullets[] bs = new Bullets[2];
bs[0] = bullet1;bs[1]=bullet2;
doubleFire--;
return bs;
}else{//返回单倍火力
int x = this.x+heroImg.getWidth(null)/2;
int y = this.y-10;
Bullets bullet = new Bullets(x,y);
Bullets[] bs = new Bullets[1];
bs[0] = bullet;
return bs;
}
}
}
package 飞机大战;
import java.applet.Applet;
import java.applet.AudioClip;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
/*
* 播放背景音乐的工具类
*/
public class Music {
// 属性
static URL bgUrl_1;
static AudioClip bg1;
static {
try {
bgUrl_1 = new File("music/what for?.wav").toURL();
} catch (MalformedURLException e) {
e.printStackTrace();
}
bg1 = Applet.newAudioClip(bgUrl_1);
}
}
package 飞机大战;
import javax.swing.JFrame;
public class PlaneFrame extends JFrame{
PlaneFrame(){
setTitle("雷霆战机");
setSize(900,768);
PlanePanel panel = new PlanePanel();
panel.startGame();
add(panel);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 播放音乐
Music.bg1.loop();
}
public static void main(String[] args){
new PlaneFrame();
}
}
package 飞机大战;
import javax.swing.*;
import java.awt.event.*;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Font;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import 飞机大战.Award;
import 飞机大战.Boss1;
import 飞机大战.Boss1bullet;
import 飞机大战.Boss2;
import 飞机大战.Bullets;
import 飞机大战.Crash1;
import 飞机大战.Crash2;
import 飞机大战.Crash3;
import 飞机大战.Enemy1;
import 飞机大战.Enemy2;
import 飞机大战.Hero;
public class PlanePanel extends JPanel
implements MouseMotionListener,MouseListener{
static Image stImg;
static Image spImg;
static Image goImg;
static Image winImg;
static Image bkImg;
static Image lfImg;
static Image scImg;
static Image bosslifeImg;
static Image mis1Img;
static Image mis2Img;
static Image mis3Img;
int state = 0;//开始,暂停,结束画面的
int score = 0;
int width = 200;
int widthb=300;//boss1的生命值宽度
int widthb2=400;//boss2的生命值宽度
int widthb3=500;//boss3的生命值宽度
int bx = 0,by = 0;//背景图片的坐标
int stx = 0,sty = 0;//绘制start的坐标
int spx = 0,spy = 0;//绘制stop的坐标
int gox = 0,goy = 0;//绘制GameOver的坐标
int wx = 0, wy = 0;
int lx = 0,ly =0;//生命标志的坐标
int sx = 0,sy =42;//得分标志的坐标
int box =500,boy =0;//boss生命的标志
int misx = 338,misy=0;//关卡的坐标
int DZ =0;
int Slimt=0;
Hero hero = new Hero(100, 200);//英雄机的属性
Bullets bullet = new Bullets(hero.x, hero.y);//子弹的属性
Boss1 boss1 = null;
Boss2 boss2 = null;
Boss3 boss3 = null;
Dazhao dazhao = null;
ArrayList<Bullets[]> bullets = new ArrayList<Bullets[]>();//存储子弹的集合
ArrayList<Award> awards = new ArrayList<Award>();//存储奖励的集合
ArrayList<Award2> awards2 = new ArrayList<Award2>();//存储奖励的集合
ArrayList<Award3> awards3 = new ArrayList<Award3>();//存储奖励的集合
ArrayList<Crash1> crash1 = new ArrayList<Crash1>();//冲撞机1的集合
ArrayList<Crash2> crash2 = new ArrayList<Crash2>();//冲撞机1的集合
ArrayList<Crash3> crash3 = new ArrayList<Crash3>();//冲撞机1的集合
ArrayList<Boss1bullet[]> bbs = new ArrayList<Boss1bullet[]>();
ArrayList<Boss2bullet[]> bbs2 = new ArrayList<Boss2bullet[]>();
ArrayList<Boss3bullet[]> bbs3 = new ArrayList<Boss3bullet[]>();
static{//静态代码块
stImg = new ImageIcon("SSOVER/start.png").getImage();
spImg = new ImageIcon("SSOVER/stop.jpg").getImage();
winImg = new ImageIcon("SSOVER/winer.png").getImage();
goImg = new ImageIcon("SSOVER/winer.png").getImage();
bkImg = new ImageIcon("sources/background.png").getImage();
lfImg = new ImageIcon("symbol/life.png").getImage();
scImg = new ImageIcon("symbol/score.png").getImage();
bosslifeImg = new ImageIcon("symbol/bosslife.png").getImage();
}
PlanePanel(){//构造函数
addMouseMotionListener(this);//将鼠标事件(this)与面板连接
addMouseListener(this);
}
public void paint(Graphics g){
super.paint(g);
//绘制开始图片
if(state==0){
g.drawImage(stImg,stx,sty,null);
Font f = new Font("",Font.BOLD,30);
g.setFont(f);
g.setColor(Color.GREEN);
g.drawString("点击鼠标左键开始",300,200);
}
if(state==1){
//绘制背景图片
g.drawImage(bkImg,bx,by,null);
g.drawImage(bkImg,bx,by-9999,null);//背景
paintCrash1(g);//画冲撞机1
paintCrash2(g);//画冲撞机2
paintCrash3(g);//画冲撞机2
paintBullet(g);//画子弹
paintAward(g);//画奖励
paintAward2(g);//画奖励2
paintAward3(g);//画奖励3
g.drawImage(lfImg,lx,ly,null);//画生命标志
g.drawImage(scImg,sx,sy,null);//画分数标志
g.setColor(Color.WHITE);
Font f = new Font("",Font.BOLD,22);
g.setFont(f);
g.drawString(" "+score, 22,66);//画分数
g.setColor(Color.GREEN);
g.fillRect(110, 4, width, 30);//画生命绿条
boss1lifePaint(g);//画boss1
paintBoss1bullet(g);//画boss1的子弹
boss2lifePaint(g);//画boss2
paintBoss2bullet(g);//画boss2的子弹
boss3lifePaint(g);//画boss3
paintBoss3bullet(g);//画boss3的子弹
DazhaoPaint(g);
g.drawImage(hero.heroImg,hero.x,hero.y,null);//画主战机
}
//绘制暂停界面
if(state==2){
g.drawImage(spImg,spx,spy,null);
}
//绘制结束界面
if(width<=0){
state=3;
}
if(state ==3){
g.drawImage(goImg,gox,goy,null);
Font f = new Font("",Font.BOLD,30);
g.setFont(f);
g.setColor(Color.RED);
g.drawString("GAME OVER",350,350);
}
//绘制胜利界面
if(widthb3<=0){
state=4;
}
if(state ==4){
g.drawImage(winImg,wx,wy,null);
Font f = new Font("",Font.BOLD,30);
g.setFont(f);
g.setColor(Color.BLUE);
g.drawString("You Are Winer!",350,350);
}
}
//游戏的开始
public void startGame(){
//游戏启动的时候就要不停的创建敌人对象从上面掉下来
//创建了一个定时器
Timer timer = new Timer();
/*
告诉定时器程序启动之后多久启动这个定时器,
以及该定时器每隔多久重复执行一次定时任务
3个未知因素
1.程序运行之后多久启动这个定时器
2.定时器每隔多久执行一次定时任务 1000
3.定时任务写哪里
*/
timer.schedule(new TimerTask(){
public void run(){
by++;
if(by==9999){by=0;}
hero.step();
bulletAction();//产生子弹
bulletMove();//移动子弹
awardAction();//产生奖励
awardStep();//移动奖励
award2Action();//产生奖励2
award2Step();//移动奖励2
award3Action();//产生奖励3
award3Step();//移动奖励3
crash1Action();//产生冲撞机1
crash1Move();//冲撞机1的移动
crash2Action();//产生冲撞机2
crash2Move();//冲撞机2的移动
crash3Action();//产生冲撞机3
crash3Move();//冲撞机3的移动
outOfBounds();//子弹,敌机,奖励出界的处理
Score();//得分的处理
addLife();//吃奖励增加生命
LoseLife();//减少生命
boss1Action();//boss1的产生
Boss1Move();//boss1的移动
boss2Action();//boss2的产生
Boss2Move();//boss2的移动
boss3Action();//boss3的产生
Boss3Move();//boss3的移动
boss1bulletAction();//boss1子弹的生成
moveBoss1bullet();//boss1子弹的移动
boss2bulletAction();//boss2子弹的生成
moveBoss2bullet();//boss2子弹的移动
boss3bulletAction();//boss3子弹的生成
moveBoss3bullet();//boss3子弹的移动
addFire();//增加火力
maxFire();//触发大招
DazhaoAction();
repaint();//重绘,刷新
}
}, 0, 10);
}
//触发大招
public void maxFire(){
int x1,x2,x3,y1,y2,y3;
for(int i=0;i<awards3.size();i++){
Award3 award3 = awards3.get(i);
x1 = award3.x; y1=award3.y;
x2 = x1+award3.award3Img.getWidth(null);
y2 = y1+award3.award3Img.getHeight(null);
x3 = hero.x+hero.heroImg.getWidth(null)/2;
y3 = hero.y+hero.heroImg.getHeight(null)/2;
if(x1<x3&&y1<y3&&x3<x2&&y3<y2){
awards3.remove(award3);
score+=100;//大招出现一次score加100
DZ+=50;//大招延时的时间
}
}
}
//大招的产生
public void DazhaoAction(){
if(dazhao==null){
dazhao = new Dazhao();
}
}
//大招的绘制
public void DazhaoPaint(Graphics g){
if(dazhao !=null && DZ>=1){//产生大招的条件
g.drawImage(dazhao.DazhaoImg,dazhao.x,dazhao.y,null);
DZ--;//大招延时
//大招使冲撞机1消失
if(dazhao != null){
int dx1 =0;
int dy1 =0;
for(int i=0;i<crash1.size();i++){
Crash1 c = crash1.get(i);
int cx1 = c.x;
if(cx1>dx1){
crash1.remove(i);
}
}
}
//大招使冲撞机2消失
if(dazhao != null){
int dx1 =0;
int dy1 =0;
for(int i=0;i<crash2.size();i++){
Crash2 c = crash2.get(i);
int cx1 = c.x;
if(cx1>dx1){
crash2.remove(i);
}
}
}
//大招使冲撞机3消失
if(dazhao != null){
int dx1 =0;
int dy1 =0;
for(int i=0;i<crash3.size();i++){
Crash3 c = crash3.get(i);
int cx1 = c.x;
if(cx1>dx1){
crash3.remove(i);
}
}
}
//大招使boss1失血
if(dazhao != null && boss1 !=null){
widthb-=1;
if(widthb<=0){
boss1 =null;
}
}
//大招使boss2失血
if(dazhao != null && boss2 !=null){
widthb2-=1;
if(widthb2<=0){
boss2 =null;
}
}
//大招使boss3失血
if(dazhao != null && boss3 !=null){
widthb3-=1;
if(widthb3<=0){
boss3 =null;
}
}
}
}
//boss1产生
public void boss1Action()
{
if(score>=1000&&score<=1100&&boss1==null){
boss1 = new Boss1();
}
}
//boss1的移动
public void Boss1Move(){
if(boss1!=null){
boss1.move();
}
}
//boss血条的出现,boss1的绘制
public void boss1lifePaint(Graphics g){
if(boss1!=null){
mis1Img = new ImageIcon("symbol/mission1.png").getImage();
g.drawImage(mis1Img,misx,misy,null);//画关卡标志
g.drawImage(bosslifeImg,box,boy,null);//画boss生命标志
g.setColor(Color.GREEN);
g.fillRect(550, 4, widthb, 30);//画boss生命绿条
g.drawImage(boss1.Boss1Img,boss1.x,boss1.y,null);
}
}
//boss2产生
public void boss2Action()
{
if(score==Slimt+1000 && boss2==null && boss1==null){
boss2 = new Boss2();
}
}
//boss2的移动
public void Boss2Move(){
if(boss2!=null){
boss2.move();
}
}
//boss血条的出现,boss2的绘制
public void boss2lifePaint(Graphics g){
if(boss2!=null){
mis2Img = new ImageIcon("symbol/mission2.png").getImage();
g.drawImage(mis2Img,misx,misy,null);//画关卡标志
g.drawImage(bosslifeImg,box,boy,null);//画boss生命标志
g.setColor(Color.GREEN);
g.fillRect(550, 4, widthb2, 30);//画boss生命绿条
g.drawImage(boss2.Boss2Img,boss2.x,boss2.y,null);
}
}
//boss3产生
public void boss3Action()
{
if(score>=6000 && score<=8000 && boss2==null && boss1==null && boss3==null){
boss3 = new Boss3();
}
}
//boss3的移动
public void Boss3Move(){
if(boss3!=null){
boss3.move();
}
}
//boss血条的出现,boss3的绘制
public void boss3lifePaint(Graphics g){
if(boss3!=null){
mis3Img = new ImageIcon("symbol/mission3.png").getImage();
g.drawImage(mis3Img,misx,misy,null);//画关卡标志
g.drawImage(bosslifeImg,box,boy,null);//画boss生命标志
g.setColor(Color.RED);
g.fillRect(550, 4, widthb3, 30);//画boss生命绿条
g.drawImage(boss3.Boss3Img,boss3.x,boss3.y,null);
}
}
//生成boss1的子弹
int bbIndex=0;
public void boss1bulletAction(){
bbIndex++;
if(bbIndex==Integer.MAX_VALUE){
bbIndex=0;
}
if(bbIndex%80==0&&boss1!=null){
Boss1bullet[] bb = boss1.shoot();
bbs.add(bb);
}
}
//移动boss1的子弹
public void moveBoss1bullet(){
for (int i = 0; i < bbs.size(); i++) {
Boss1bullet[] bb = bbs.get(i);
for (int j = 0; j < bb.length; j++) {
bb[j].step();
}
}
}
//绘制boss1的子弹
public void paintBoss1bullet(Graphics g){
for(int i=0;i<bbs.size();i++){
Boss1bullet[] bb = bbs.get(i);
for(int j=0;j<bb.length;j++){
if(bb[j].isHit==false){
g.drawImage(bb[j].bbImg,bb[j].x,bb[j].y,null);
}
}
}
}
//生成boss2的子弹
int bb2Index=0;
public void boss2bulletAction(){
bb2Index++;
if(bb2Index==Integer.MAX_VALUE){
bb2Index=0;
}
if(bb2Index%30==0&&boss2!=null){
Boss2bullet[] bb = boss2.shoot();
bbs2.add(bb);
}
}
//移动boss2的子弹
public void moveBoss2bullet(){
for (int i = 0; i < bbs2.size(); i++) {
Boss2bullet[] bb = bbs2.get(i);
for (int j = 0; j < bb.length; j++) {
bb[j].step();
}
}
}
//绘制boss2的子弹
public void paintBoss2bullet(Graphics g){
for(int i=0;i<bbs2.size();i++){
Boss2bullet[] bb = bbs2.get(i);
for(int j=0;j<bb.length;j++){
if(bb[j].isHit==false){
g.drawImage(bb[j].bbImg,bb[j].x,bb[j].y,null);
}
}
}
}
//生成boss3的子弹
int bb3Index=0;
public void boss3bulletAction(){
bb3Index++;
if(bb3Index==Integer.MAX_VALUE){
bb3Index=0;
}
if(bb3Index%30==0&&boss3!=null){
Boss3bullet[] bb = boss3.shoot();
bbs3.add(bb);
}
}
//移动boss3的子弹
public void moveBoss3bullet(){
for (int i = 0; i < bbs3.size(); i++) {
Boss3bullet[] bb = bbs3.get(i);
for (int j = 0; j < bb.length; j++) {
bb[j].step();
}
}
}
//绘制boss3的子弹
public void paintBoss3bullet(Graphics g){
for(int i=0;i<bbs3.size();i++){
Boss3bullet[] bb = bbs3.get(i);
for(int j=0;j<bb.length;j++){
if(bb[j].isHit==false){
g.drawImage(bb[j].bbImg,bb[j].x,bb[j].y,null);
}
}
}
}
//产生冲撞机1
int crash1Idex=0;
public void crash1Action(){
crash1Idex++;
if(crash1Idex == Integer.MAX_VALUE){//判断bulletIdex不要太大,防止内存溢出
crash1Idex = 0;
}
if(crash1Idex%80 ==0){
Crash1 c = new Crash1();//产生冲撞机1
crash1.add(c);//产生一个冲撞机1,然后把冲撞机1放入集合
}
}
//移动冲撞机1
public void crash1Move(){//循环遍历集合,得到每一个敌机,然后调用敌机的移动
for(int i=0;i<crash1.size();i++){
Crash1 c = crash1.get(i);
c.move();
}
}
//画冲撞机1
public void paintCrash1(Graphics g){
for(int i =0;i<crash1.size();i++){
Crash1 c =crash1.get(i);
g.drawImage(c.crash1Img,c.x,c.y,null);
}
}
//产生冲撞机2
int crash2Idex=0;
public void crash2Action(){
crash2Idex++;
if(crash2Idex == Integer.MAX_VALUE){//判断bulletIdex不要太大,防止内存溢出
crash2Idex = 0;
}
if(crash2Idex%200 ==0){
Crash2 c = new Crash2();//产生冲撞机2
if(score>=2000&& boss2 == null){
crash2.add(c);//产生一个冲撞机2,然后把冲撞机2放入集合
}
}
}
//移动冲撞机2
public void crash2Move(){//循环遍历集合,得到每一个敌机,然后调用敌机的移动
for(int i=0;i<crash2.size();i++){
Crash2 c = crash2.get(i);
c.move();
}
}
//画冲撞机2
public void paintCrash2(Graphics g){
for(int i =0;i<crash2.size();i++){
Crash2 c =crash2.get(i);
g.drawImage(c.crash2Img,c.x,c.y,null);
}
}
//产生冲撞机3
int crash3Idex=0;
public void crash3Action(){
crash3Idex++;
if(crash3Idex == Integer.MAX_VALUE){//判断bulletIdex不要太大,防止内存溢出
crash3Idex = 0;
}
if(crash3Idex%100 ==0){
Crash3 c = new Crash3();//产生冲撞机3
if(score>=3000 && boss1==null){
crash3.add(c);//产生一个冲撞机3,然后把冲撞机3放入集合
}
}
}
//移动冲撞机3
public void crash3Move(){//循环遍历集合,得到每一个敌机,然后调用敌机的移动
for(int i=0;i<crash3.size();i++){
Crash3 c = crash3.get(i);
c.move();
}
}
//画冲撞机3
public void paintCrash3(Graphics g){
for(int i =0;i<crash3.size();i++){
Crash3 c =crash3.get(i);
g.drawImage(c.crash3Img,c.x,c.y,null);
}
}
//主战机子弹的方法
//产生子弹的方法
int bulletIdex=0;
public void bulletAction(){
bulletIdex++;
if(bulletIdex == Integer.MAX_VALUE){//判断bulletIdex不要太大,防止内存溢出
bulletIdex = 0;
}
if(bulletIdex%30 ==0){
Bullets[] bs = hero.shoot();//产生子弹
bullets.add(bs);//产生一个子弹,然后把子弹放入集合
}
}
//移动子弹的方法
public void bulletMove(){//循环遍历集合,得到每一个子弹,然后调用子弹的移动
for(int i=0;i<bullets.size();i++){
Bullets[] bs = bullets.get(i);
for(int j=0;j<bs.length;j++){
Bullets bullet = bs[j];
bullet.move();
}
}
}
//绘制子弹的方法
public void paintBullet(Graphics g){//循环得到每一个子弹,然后把这个子弹画出来
for(int i=0;i<bullets.size();i++){//循环这个集合
Bullets[] bs = bullets.get(i);
for(int j=0;j<bs.length;j++){
Bullets bullet = bs[j];
g.drawImage(bullet.bulletImg,bullet.x,
bullet.y,null);
}
}
}
// 奖励的方法
//产生奖励1的方法
int awardIdex = 0;
public void awardAction(){
awardIdex++;
if(awardIdex == Integer.MAX_VALUE){
awardIdex = 0;
}
if(awardIdex%500 ==0){
Award a = new Award();//
awards.add(a);
}
}
//移动奖励1的方法
public void awardStep(){
for(int i=0;i<awards.size();i++){
Award a = awards.get(i);
a.move();
}
}
//画奖励1的方法
public void paintAward(Graphics g){
for(int i =0;i<awards.size();i++){
Award a=awards.get(i);
g.drawImage(a.awardImg,a.x,a.y,null);
}
}
//产生奖励2的方法
int award2Idex = 0;
public void award2Action(){
award2Idex++;
if(award2Idex == Integer.MAX_VALUE){
award2Idex = 0;
}
if(award2Idex%800 ==0){
Award2 a = new Award2();
awards2.add(a);
}
}
//移动奖励2的方法
public void award2Step(){
for(int i=0;i<awards2.size();i++){
Award2 a = awards2.get(i);
a.move();
}
}
//画奖励2的方法
public void paintAward2(Graphics g){
for(int i =0;i<awards2.size();i++){
Award2 a=awards2.get(i);
g.drawImage(a.award2Img,a.x,a.y,null);
}
}
//产生奖励3的方法
int award3Idex = 0;
public void award3Action(){
award3Idex++;
if(award3Idex == Integer.MAX_VALUE){
award3Idex = 0;
}
if(award3Idex%1000 ==0 && score>=1500){
Award3 a = new Award3();
awards3.add(a);
}
}
//移动奖励3的方法
public void award3Step(){
for(int i=0;i<awards3.size();i++){
Award3 a = awards3.get(i);
a.move();
}
}
//画奖励3的方法
public void paintAward3(Graphics g){
for(int i =0;i<awards3.size();i++){
Award3 a=awards3.get(i);
g.drawImage(a.award3Img,a.x,a.y,null);
}
}
//子弹,敌机,奖励出界的处理
public void outOfBounds(){
for(int i = 0;i<bullets.size();i++){
Bullets[] b = bullets.get(i);
if(b[0].y+Bullets.bulletImg.getWidth(null) <=0){bullets.remove(i);}
}
for(int i = 0;i<crash1.size();i++){
Crash1 e = crash1.get(i);
if(e.y+e.crash1Img.getWidth(null) >=768){crash1.remove(i);}
}
for(int i = 0;i<crash2.size();i++){
Crash2 e = crash2.get(i);
if(e.y+e.crash2Img.getWidth(null) <=0){crash2.remove(i);}
}
for(int i = 0;i<crash3.size();i++){
Crash3 e = crash3.get(i);
if(e.y+e.crash3Img.getWidth(null) >=768){crash3.remove(i);}
}
for(int i = 0;i<awards.size();i++){
Award a = awards.get(i);
if(a.y+a.awardImg.getWidth(null) >=768){awards.remove(i);}
}
//删除越界的Boss子弹
for(int i=0;i<bbs.size();i++){
Boss1bullet[] bb = bbs.get(i);
if(bb[0].y>=768){
bbs.remove(bb);
}
}
}
//子弹得分
public void Score(){
//打敌机1,敌机1消失
for (int i = 0; i < crash1.size(); i++)
{
Crash1 c = crash1.get(i);
int cx1 = c.x,cy1 =c.y ;
int cx2 =c.x+ c.crash1Img.getWidth(null),cy2 =c.y+c.crash1Img.getHeight(null);
for (int j = 0; j < bullets.size(); j++) {
Bullets[] bs = bullets.get(j);
for(int k =0;k<bs.length;k++){
Bullets b =bs[k];
int bx1 =b.x ,by1 =b.y ;
int bx2 =b.x+b.bulletImg.getWidth(null) ,by2 =b.y+b.bulletImg.getHeight(null) ;
if(bx1 >=cx1 && bx2<=cx2 && by1>=cy1 &&by2<=cy2){
score+=100;
crash1.remove(c);
bullets.remove(b);
break;
}
}
}
}
//打敌机2,敌机2消失
for (int i = 0; i < crash2.size(); i++)
{
Crash2 c = crash2.get(i);
int cx1 = c.x,cy1 =c.y ;
int cx2 =c.x+ c.crash2Img.getWidth(null),cy2 =c.y+c.crash2Img.getHeight(null);
for (int j = 0; j < bullets.size(); j++) {
Bullets[] bs = bullets.get(j);
for(int k =0;k<bs.length;k++){
Bullets b =bs[k];
int bx1 =b.x ,by1 =b.y ;
int bx2 =b.x+b.bulletImg.getWidth(null)/2 ,by2 =b.y+b.bulletImg.getHeight(null)/2 ;
if(bx2>cx1&&bx2<cx2&&by2>cy1&&by2<cy2){
score+=100;
crash2.remove(c);
bullets.remove(b);
break;
}
}
}
}
//打敌机3,让敌机3消失
for (int i = 0; i < crash3.size(); i++)
{
Crash3 c = crash3.get(i);
int cx1 = c.x,cy1 =c.y ;
int cx2 =c.x+ c.crash3Img.getWidth(null),cy2 =c.y+c.crash3Img.getHeight(null);
for (int j = 0; j < bullets.size(); j++) {
Bullets[] bs = bullets.get(j);
for(int k =0;k<bs.length;k++){
Bullets b =bs[k];
int bx1 =b.x ,by1 =b.y ;
int bx2 =b.x+b.bulletImg.getWidth(null) ,by2 =b.y+b.bulletImg.getHeight(null) ;
if(bx1 >=cx1 && bx2<=cx2 && by1>=cy1 &&by2<=cy2){
score+=100;
crash3.remove(c);
bullets.remove(b);
break;
}
}
}
}
//打中小Boss,子弹消失,血量减少
if(boss1!=null){
int cx1 = boss1.x,cy1 =boss1.y ;
int cx2 =boss1.x+ boss1.Boss1Img.getWidth(null),cy2 =boss1.y+boss1.Boss1Img.getHeight(null);
for(int i=0;i<bullets.size();i++){
Bullets[] b = bullets.get(i);
for (int j = 0; j < b.length; j++) {
if(b[j].x>cx1&&b[j].x<cx2
&&b[j].y>cy1&&b[j].y<cy2){
widthb-=10;
if(widthb<=0){
widthb=0;
score+=300;
boss1=null;
}
bullets.remove(b);
Slimt =score;
break;
}
}
}
}
//打中小boss2
if(boss2!=null){
int cx1 = boss2.x,cy1 =boss2.y ;
int cx2 =boss2.x+ boss2.Boss2Img.getWidth(null),cy2 =boss2.y+boss2.Boss2Img.getHeight(null);
for(int i=0;i<bullets.size();i++){
Bullets[] b = bullets.get(i);
for (int j = 0; j < b.length; j++) {
if(b[j].x>cx1&&b[j].x<cx2 &&b[j].y>cy1&&b[j].y<cy2){
widthb2-=5;
if(widthb2<=0){
widthb2=0;
score+=300;
boss2=null;
}
bullets.remove(b);
break;
}
}
}
}
//打中小Boss,子弹消失,血量减少
if(boss3!=null){
int cx1 = boss3.x,cy1 =boss3.y ;
int cx2 =boss3.x+ boss3.Boss3Img.getWidth(null),cy2 =boss3.y+boss3.Boss3Img.getHeight(null);
for(int i=0;i<bullets.size();i++){
Bullets[] b = bullets.get(i);
for (int j = 0; j < b.length; j++) {
if(b[j].x>cx1&&b[j].x<cx2
&&b[j].y>cy1&&b[j].y<cy2){
widthb-=10;
if(widthb3<=0){
widthb3=0;
score+=300;
boss3=null;
}
bullets.remove(b);
break;
}
}
}
}
}
//增加生命
public void addLife(){
for(int i =0;i<awards.size();i++){
Award a = awards.get(i);
int ax1,ay1,ax2,ay2;
int hx1,hy1,hx2,hy2 ;
ax1 = a.x;
ay1 = a.y;
ax2 = ax1 +a.awardImg.getWidth(null);
ay2 = ay1 +a.awardImg.getHeight(null);
hx1 = hero.x;
hy1 = hero.y;
hx2 = hx1 +hero.heroImg.getWidth(null);
hy2 = hy1 +hero.heroImg.getHeight(null);
if(ax1 >=hx1 && ax2 <=hx2 && ay1>=hy1 && ay2 <=hy2){
awards.remove(i);
width+=50;//生命增加
if(width>=200){
width=200;
}
}
}
}
//增加火力
public void addFire(){
/*判断是不是碰撞到了奖励
*如果碰撞到了,就移除奖励,并增加火力
*/
int x1,x2,x3,y1,y2,y3;
for(int i=0;i<awards2.size();i++){
Award2 award2 = awards2.get(i);
x1 = award2.x; y1=award2.y;
x2 = x1+award2.award2Img.getWidth(null);
y2 = y1+award2.award2Img.getHeight(null);
x3 = hero.x+hero.heroImg.getWidth(null)/2;
y3 = hero.y+hero.heroImg.getHeight(null)/2;
if(x1<x3&&y1<y3&&x3<x2&&y3<y2){
awards2.remove(award2);
hero.doubleFire+=10;
}
}
}
//敌机撞击损失生命
public void LoseLife(){
//冲撞机1撞击
for(int i =0;i<crash1.size();i++){
Crash1 c = crash1.get(i);
int cx1,cy1,cx2,cy2;
int hx1,hy1,hx2,hy2 ;
cx1 = c.x;
cy1 = c.y;
cx2 = cx1 +c.crash1Img.getWidth(null)/2;
cy2 = cy1 +c.crash1Img.getHeight(null)/2;
hx1 = hero.x;
hy1 = hero.y;
hx2 = hx1 +hero.heroImg.getWidth(null);
hy2 = hy1 +hero.heroImg.getHeight(null);
if(cx2>hx1&&cx2<hx2&&cy2<hy2&&cy2>hy1 ){
crash1.remove(i);
width-=50;//生命减少
if(width<=0){
width =0;
}
}
}
//冲撞机2撞击
for(int i =0;i<crash2.size();i++){
Crash2 c = crash2.get(i);
int cx1,cy1,cx2,cy2;
int hx1,hy1,hx2,hy2 ;
cx1 = c.x;
cy1 = c.y;
cx2 = cx1 +c.crash2Img.getWidth(null)/2;
cy2 = cy1 +c.crash2Img.getHeight(null)/2;
hx1 = hero.x;
hy1 = hero.y;
hx2 = hx1 +hero.heroImg.getWidth(null);
hy2 = hy1 +hero.heroImg.getHeight(null);
if(cx2>hx1&&cx2<hx2&&cy2<hy2&&cy2>hy1 ){
crash2.remove(i);
width-=50;//生命减少
if(width<=0){
width =0;
}
}
}
//冲撞机3撞击
for(int i =0;i<crash3.size();i++){
Crash3 c = crash3.get(i);
int cx1,cy1,cx2,cy2;
int hx1,hy1,hx2,hy2 ;
cx1 = c.x;
cy1 = c.y;
cx2 = cx1 +c.crash3Img.getWidth(null)/2;
cy2 = cy1 +c.crash3Img.getHeight(null)/2;
hx1 = hero.x;
hy1 = hero.y;
hx2 = hx1 +hero.heroImg.getWidth(null);
hy2 = hy1 +hero.heroImg.getHeight(null);
if(cx2>hx1&&cx2<hx2&&cy2<hy2&&cy2>hy1 ){
crash3.remove(i);
width-=50;//生命减少
if(width<=0){
width =0;
}
}
}
//boss1的子弹打中主战机
for (int i = 0; i < bbs.size(); i++) {
int x1,x2,y1,y2,x3,y3;
x1=hero.x;y1=hero.y;
x2=x1+hero.heroImg.getWidth(null);
y2=y1+hero.heroImg.getHeight(null);
Boss1bullet[] bb = bbs.get(i);
for (int j = 0; j < bb.length; j++) {
x3=bb[j].x;y3=bb[j].y;
if(x3>x1&&x3<x2&&y3>y1&&y3<y2){
width--;
if(width<=0){
width=0;
}
bb[j].isHit=true;
break;
}
}
}
//boss2的子弹打中主战机
for (int i = 0; i < bbs2.size(); i++) {
int x1,x2,y1,y2,x3,y3;
x1=hero.x;y1=hero.y;
x2=x1+hero.heroImg.getWidth(null);
y2=y1+hero.heroImg.getHeight(null);
Boss2bullet[] bb = bbs2.get(i);
for (int j = 0; j < bb.length; j++) {
x3=bb[j].x;y3=bb[j].y;
if(x3>x1&&x3<x2&&y3>y1&&y3<y2){
width--;
if(width<=0){
width=0;
}
bb[j].isHit=true;
break;
}
}
}
//boss1的子弹打中主战机
for (int i = 0; i < bbs.size(); i++) {
int x1,x2,y1,y2,x3,y3;
x1=hero.x;y1=hero.y;
x2=x1+hero.heroImg.getWidth(null);
y2=y1+hero.heroImg.getHeight(null);
Boss1bullet[] bb = bbs.get(i);
for (int j = 0; j < bb.length; j++) {
x3=bb[j].x;y3=bb[j].y;
if(x3>x1&&x3<x2&&y3>y1&&y3<y2){
width--;
if(width<=0){
width=0;
}
bb[j].isHit=true;
break;
}
}
}
}
//鼠标的方法
public void mouseDragged(MouseEvent arg0) {
}
public void mouseMoved(MouseEvent e) {
int mx = e.getX();//得到鼠标的坐标
int my = e.getY();
hero.x = mx-hero.heroImg.getWidth(null)/2;//鼠标的x坐标赋给英雄机
hero.y = my-hero.heroImg.getHeight(null)/2;//鼠标的y坐标赋给英雄机
//控制出界的设置
if(hero.x<-8){ hero.x = -8;}//控制左出界
if(hero.x+hero.heroImg.getWidth(null)>900)//控制右出界
{
hero.x = 900-hero.heroImg.getWidth(null);
}
if(hero.y<0){ hero.y = 0;}//控制上出界
if(hero.y+hero.heroImg.getHeight(null)>768)//控制下出界
{
hero.y = 768-hero.heroImg.getHeight(null);
}
}
@Override
public void mouseClicked(MouseEvent e) {