Java小游戏飞机大战(Java期末大作业)
前言
这学期的Java期末大作业是让做一个飞机大战或者坦克大战,我选择了飞机大战,但是之前没有学过JavaGui的知识,我觉得JavaSwing对于现在的Java来说都已经有些过时了,但是没办法,课本上还是在教这些东西,自己虽然已经学了很久的Java,但是对于JavaGui是属于一个门外汉的状态,为了这次的期末大作业也是去学了一下JavaGui,在b站上找了些视频看了看,总体感觉还行,不算很难。
开发过程
在刚开始学的时候,自己就只看了看课本,看完就两个字,无语,特别的无语,课本上那点知识也就只够写个图形化的计算器的(上周的作业),然后自己就想着找一些文档来看,但网上关于JavaGui的教程太少了,没有找到合适的文档,就只能在b站上找视频看了。对于刚开始,自己对于如何写这个游戏还是有些迷惑的,如何实现子弹撞击等等,看了几集之后觉得有思路了,把每个飞机都看作一个图片,然后当两个图片位置相同时就相当于撞击了,有了思路之后,去找了一下尚学堂的素材,看了几集,后面就是几乎一模一样的代码了,给各种飞机添加子弹碰撞等等。
项目结构
大致分为三个包,最主要的还是obj包,里面包含了各种素材的实例对象,其中GameObj是一个父类,其他类均继承至此类。GameUnit则包含了各种所需要用到的图片对象,集合对象等等。而startwin则就是游戏的绘制了,调用各种对象来实现这个游戏。
具体实现
1.GameObj父类
package obj;
import planewar.StartWin;
import java.awt.*;
public class GameObj {
Image img;
int width;
int height;
int x;
int y;
double speed;
public Image getImg() {
return img;
}
public void setImg(Image img) {
this.img = img;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
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 double getSpeed() {
return speed;
}
public void setSpeed(double speed) {
this.speed = speed;
}
public StartWin getFrame() {
return frame;
}
public void setFrame(StartWin frame) {
this.frame = frame;
}
StartWin frame;
public GameObj() {
}
public GameObj(Image img, int width, int height, int x, int y, double speed, StartWin frame) {
this.img = img;
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.speed = speed;
this.frame = frame;
}
public GameObj(Image img, int x, int y, double speed) {
this.img = img;
this.x = x;
this.y = y;
this.speed = speed;
}
public GameObj(int x, int y) {
this.x = x;
this.y = y;
}
//控制元素自身的方法
public void paintSelf(Graphics g){
g.drawImage(img,x,y,null);
}
//选取自身矩形的方法,用来碰撞检测
public Rectangle getRec(){
return new Rectangle(x,y,width,height);
}
}
这个类中,定义了以后的子类中各种可能会使用到的方法,如设立获取对象的宽高,对象的位置,对象显示的窗口,绘制对象的方法,碰撞检测的方法等等。
2.我方飞机类
package obj;
import planewar.StartWin;
import unit.GameUnit;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class PlaneObj extends GameObj{
public static int times = 2;
LittleBoss1 littleBoss1 = new LittleBoss1();
LittleBoss2 littleBoss2 = new LittleBoss2();
public PlaneObj() {
super();
}
public PlaneObj(Image img, int width, int height, int x, int y, double speed, StartWin frame) {
super(img, width, height, x, y, speed, frame);
//添加鼠标的移动事件
this.frame.addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
PlaneObj.super.x = e.getX()-19;
PlaneObj.super.y = e.getY()-20;
}
});
}
public PlaneObj(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
@Override
public void paintSelf(Graphics g) {
super.paintSelf(g);
//敌方小飞机与我方飞机相撞后,敌方小飞机消失,我方飞机消失
for (Enemy1Obj enemy1Obj: GameUnit.enemy1ObjList){
if(this.getRec().intersects(enemy1Obj.getRec())) {
//绘制爆炸效果
ExplodeObj explodeObj = new ExplodeObj(x,y);
//添加到爆炸集合中,方便后续绘制
GameUnit.explodeObjList.add(explodeObj);
//爆炸后移除图片,以达到预期效果
GameUnit.removeList.add(explodeObj);
//爆炸后把飞机移动到窗口外
enemy1Obj.setX(-100);
enemy1Obj.setY(-100);
//我放飞机移动出去
this.x = -200;
this.y = -200;
//在移除的集合中添加这两个对象
GameUnit.removeList.add(enemy1Obj);
GameUnit.removeList.add(this);
//把游戏状态设置为状态三
StartWin.state = 3;
}
}
//敌方打飞机与我方飞机相撞后,敌方大飞机消失,我方飞机消失。
for (Enemy2Obj enemy2Obj: GameUnit.enemy2ObjList){
if(this.getRec().intersects(enemy2Obj.getRec())) {
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
enemy2Obj.setX(-100);
enemy2Obj.setY(-100);
this.x = -200;
this.y = -200;
GameUnit.removeList.add(enemy2Obj);
GameUnit.removeList.add(this);
StartWin.state = 3;
}
}
//敌方子弹与我方飞机相撞后,敌方子弹消失,我方飞机消失
for (Enemy2BulletObj enemy2BulletObj: GameUnit.enemy2BulletObjList){
if(this.getRec().intersects(enemy2BulletObj.getRec())) {
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
enemy2BulletObj.setX(-100);
enemy2BulletObj.setY(-100);
this.x = -200;
this.y = -200;
GameUnit.removeList.add(enemy2BulletObj);
GameUnit.removeList.add(this);
StartWin.state = 3;
}
}
//boss1碰撞后我方消失,敌方存在
if(this.getRec().intersects(littleBoss1.getRec())){
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
this.x = -200;
this.y = -200;
GameUnit.removeList.add(this);
StartWin.state = 3;
}
//boss2碰撞后我方消失,敌方存在
if(this.getRec().intersects(littleBoss2.getRec())){
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
this.x = -200;
this.y = -200;
GameUnit.removeList.add(this);
StartWin.state = 3;
}
//当我放飞机和敌方1号boss子弹碰撞后都消失
for(LittleBoss1Bullet littleBoss1Bullet : GameUnit.littleBoss1BulletList){
if(this.getRec().intersects(littleBoss1Bullet.getRec())){
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
littleBoss1Bullet.setX(-100);
littleBoss1Bullet.setY(-100);
GameUnit.removeList.add(littleBoss1Bullet);
this.x = -200;
this.y = -200;
GameUnit.removeList.add(this);
StartWin.state = 3;
}
}
//敌方飞机2boss子弹撞击
for(LittleBoss2Bullet littleBoss2Bullet : GameUnit.littleBoss2BulletList){
if(this.getRec().intersects(littleBoss2Bullet.getRec())){
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
littleBoss2Bullet.setX(-100);
littleBoss2Bullet.setY(-100);
GameUnit.removeList.add(littleBoss2Bullet);
this.x = -200;
this.y = -200;
GameUnit.removeList.add(this);
StartWin.state = 3;
}
}
//飞机与补给品碰撞
for(GiftObj giftObj:GameUnit.giftObjList){
if(this.getRec().intersects(giftObj.getRec())){
giftObj.setX(-100);
giftObj.setY(-100);
GameUnit.removeList.add(giftObj);
times++;
}
}
//飞机与boss子弹碰撞
for(BossBullet bossBullet:GameUnit.bossBulletList){
if(this.getRec().intersects(bossBullet.getRec())){
//绘制爆炸
ExplodeObj explodeObj=new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
bossBullet.setX(-100);
bossBullet.setY(-100);
this.x=-200;
this.y=-200;
GameUnit.removeList.add(bossBullet);
GameUnit.removeList.add(this);
StartWin.state = 3;
}
}
}
//碰撞检测的方法
@Override
public Rectangle getRec() {
return super.getRec();
}
}
在这个游戏中,我们主要是用鼠标来操控飞机的移动,所以对飞机对象添加了一个鼠标的监听事件,而在这个类中还包括了飞机与敌方各种飞机与各种子弹的碰撞方法,在碰撞之后,会有一个爆炸的效果,代码看起来很多,但其实都是相同的代码,只不过换了对象,对于代码的解释,在代码的注释中写有,在这里就不再赘述。对于我放飞机的碰撞有一个补给品,在我们的设计中,游戏过程中有两个小boss,击败小boss之后,会出现一个补给品,碰撞之后,飞机的子弹会升级,伤害会更高。
3.各种敌方飞机类
在消灭飞机时,我们会进行加分,而不同的飞机所加的分数也不同,对于飞机的不同,他们的血量与发射的子弹也不相同,以下是具体实现。
1.敌方小飞机
package obj;
import planewar.StartWin;
import unit.GameUnit;
import java.awt.*;
public class Enemy1Obj extends GameObj{
public Enemy1Obj() {
super();
}
public Enemy1Obj(Image img, int width, int height, int x, int y, double speed, StartWin frame) {
super(img, width, height, x, y, speed, frame);
}
public Enemy1Obj(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
@Override
public void paintSelf(Graphics g) {
super.paintSelf(g);
y+=speed;
//我方子弹和小飞机碰撞
for(ShellObj shellObj: GameUnit.shellObjList){
if(this.getRec().intersects(shellObj.getRec())){
//碰撞之后的碰撞动画
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
shellObj.setX(-100);
shellObj.setY(-100);
this.setX(-100);
this.setY(-100);
GameUnit.removeList.add(shellObj);
GameUnit.removeList.add(this);
StartWin.score+=1;
}
}
//二级子弹
for(DoubleShellObj doubleshellObj: GameUnit.doubleShellObjList){
if(this.getRec().intersects(doubleshellObj.getRec())){
//碰撞之后的碰撞动画
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
doubleshellObj.setX(-100);
doubleshellObj.setY(-100);
this.setX(-100);
this.setY(-100);
GameUnit.removeList.add(doubleshellObj);
GameUnit.removeList.add(this);
StartWin.score+=1;
}
}
//三级子弹
for(TripleShellObj tripleshellObj: GameUnit.tripleShellObjList){
if(this.getRec().intersects(tripleshellObj.getRec())){
//碰撞之后的碰撞动画
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
tripleshellObj.setX(-100);
tripleshellObj.setY(-100);
this.setX(-100);
this.setY(-100);
GameUnit.removeList.add(tripleshellObj);
GameUnit.removeList.add(this);
StartWin.score+=1;
}
}
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
对于敌方小飞机,我们的设计是小飞机不发射子弹,而对于我方飞机,我方飞机是有三种子弹,所以对三种子弹都进行一个碰撞检测。
2.敌方大飞机
package obj;
import planewar.StartWin;
import unit.GameUnit;
import java.awt.*;
public class Enemy2Obj extends GameObj{
//设置大飞机的血量
int red = 3;
public Enemy2Obj() {
super();
}
public Enemy2Obj(Image img, int width, int height, int x, int y, double speed, StartWin frame) {
super(img, width, height, x, y, speed, frame);
}
public Enemy2Obj(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
@Override
public void paintSelf(Graphics g) {
super.paintSelf(g);
y += speed;
//一级子弹
for (ShellObj shellObj : GameUnit.shellObjList) {
if (this.getRec().intersects(shellObj.getRec())&&red>0) {
shellObj.setX(-100);
shellObj.setY(-100);
GameUnit.removeList.add(shellObj);
red--;
}
else if(this.getRec().intersects(shellObj.getRec())&&red<=0){
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
shellObj.setX(-100);
shellObj.setY(-100);
GameUnit.removeList.add(shellObj);
this.setX(-100);
this.setY(-100);
GameUnit.removeList.add(this);
StartWin.score+=2;
}
}
//二级子弹
for (DoubleShellObj doubleshellObj : GameUnit.doubleShellObjList) {
if (this.getRec().intersects(doubleshellObj.getRec())&&red>0) {
doubleshellObj.setX(-100);
doubleshellObj.setY(-100);
GameUnit.removeList.add(doubleshellObj);
red-=3;
}
else if(this.getRec().intersects(doubleshellObj.getRec())&&red<=0){
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
doubleshellObj.setX(-100);
doubleshellObj.setY(-100);
GameUnit.removeList.add(doubleshellObj);
this.setX(-100);
this.setY(-100);
GameUnit.removeList.add(this);
StartWin.score+=2;
}
}
//三级子弹
for (TripleShellObj tripshellObj : GameUnit.tripleShellObjList) {
if (this.getRec().intersects(tripshellObj.getRec())&&red>0) {
tripshellObj.setX(-100);
tripshellObj.setY(-100);
GameUnit.removeList.add(tripshellObj);
red-=5;
}
else if(this.getRec().intersects(tripshellObj.getRec())&&red<=0){
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
tripshellObj.setX(-100);
tripshellObj.setY(-100);
GameUnit.removeList.add(tripshellObj);
this.setX(-100);
this.setY(-100);
GameUnit.removeList.add(this);
StartWin.score+=2;
}
}
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
对于大飞机,是要发射子弹的,但是子弹类是另外写了一个,对于大飞机,血量为3,因此在进行碰撞时要进行一个检测,子弹撞击后,大飞机的血量是否为0,三种子弹的威力不同,消灭飞机所需要的子弹数也不同。
3.敌方一号小boss
package obj;
import planewar.StartWin;
import unit.GameUnit;
import java.awt.*;
public class LittleBoss1 extends GameObj{
int red = 10;
public LittleBoss1() {
super();
}
public LittleBoss1(Image img, int width, int height, int x, int y, double speed, StartWin frame) {
super(img, width, height, x, y, speed, frame);
}
public LittleBoss1(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
public LittleBoss1(int x, int y) {
super(x, y);
}
@Override
public void paintSelf(Graphics g) {
super.paintSelf(g);
x+=speed;
//当飞机移动到最右边之后,往左边进行移动
if(x>400){
speed = -1;
}
for (ShellObj shellObj: GameUnit.shellObjList){
if(this.getRec().intersects(shellObj.getRec())&&red>0){
shellObj.setX(-100);
shellObj.setY(-100);
GameUnit.removeList.add(shellObj);
red--;
}else if(this.getRec().intersects(shellObj.getRec())&&red<=0){
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
//补给
GiftObj giftObj = new GiftObj(this.x,this.y);
GameUnit.giftObjList.add(giftObj);
GameUnit.gameUnitList.addAll(GameUnit.giftObjList);
shellObj.setX(-100);
shellObj.setY(-100);
GameUnit.removeList.add(shellObj);
this.x=-200;
this.y=-200;
GameUnit.removeList.add(this);
StartWin.score+=5;
}
}
for (DoubleShellObj doubleshellObj : GameUnit.doubleShellObjList) {
if (this.getRec().intersects(doubleshellObj.getRec())&&red>0) {
doubleshellObj.setX(-100);
doubleshellObj.setY(-100);
GameUnit.removeList.add(doubleshellObj);
red-=3;
}
else if(this.getRec().intersects(doubleshellObj.getRec())&&red<=0){
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
//补给
GiftObj giftObj = new GiftObj(this.x,this.y);
GameUnit.giftObjList.add(giftObj);
GameUnit.gameUnitList.addAll(GameUnit.giftObjList);
doubleshellObj.setX(-100);
doubleshellObj.setY(-100);
GameUnit.removeList.add(doubleshellObj);
this.setX(-100);
this.setY(-100);
GameUnit.removeList.add(this);
StartWin.score+=5;
}
}
for (TripleShellObj tripshellObj : GameUnit.tripleShellObjList) {
if (this.getRec().intersects(tripshellObj.getRec())&&red>0) {
tripshellObj.setX(-100);
tripshellObj.setY(-100);
GameUnit.removeList.add(tripshellObj);
red-=5;
}
else if(this.getRec().intersects(tripshellObj.getRec())&&red<=0){
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
//补给
GiftObj giftObj = new GiftObj(this.x,this.y);
GameUnit.giftObjList.add(giftObj);
GameUnit.gameUnitList.addAll(GameUnit.giftObjList);
tripshellObj.setX(-100);
tripshellObj.setY(-100);
GameUnit.removeList.add(tripshellObj);
this.setX(-100);
this.setY(-100);
GameUnit.removeList.add(this);
StartWin.score+=5;
}
}
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
对于一号小boss,我们的设定是会在游戏屏幕中间出现,会在整个横轴移动,所以对于绘制的代码有些不同。而且消灭了一号小boss之后,会产生一个补给品,所以在碰撞代码中也多了一段添加补给的代码。
4.敌方二号小boss
package obj;
import planewar.StartWin;
import unit.GameUnit;
import java.awt.*;
public class LittleBoss2 extends GameObj{
int red =10;
public LittleBoss2() {
super();
}
public LittleBoss2(Image img, int width, int height, int x, int y, double speed, StartWin frame) {
super(img, width, height, x, y, speed, frame);
}
public LittleBoss2(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
public LittleBoss2(int x, int y) {
super(x, y);
}
@Override
public void paintSelf(Graphics g) {
super.paintSelf(g);
//从屏幕顶端出现
if(y<150){
y+=2;
}else{
//移动到一个固定位置后,开始左右移动
x+=speed;
if(x>400||x<10){
speed=-speed;
}
}
for (ShellObj shellObj: GameUnit.shellObjList){
if(this.getRec().intersects(shellObj.getRec())&&red>0){
shellObj.setX(-100);
shellObj.setY(-100);
GameUnit.removeList.add(shellObj);
red--;
}else if(this.getRec().intersects(shellObj.getRec())&&red<=0){
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
GiftObj giftObj = new GiftObj(this.x,this.y);
GameUnit.giftObjList.add(giftObj);
GameUnit.gameUnitList.addAll(GameUnit.giftObjList);
shellObj.setX(-100);
shellObj.setY(-100);
GameUnit.removeList.add(shellObj);
this.x=-200;
this.y=-200;
GameUnit.removeList.add(this);
StartWin.score+=5;
}
}
for (DoubleShellObj doubleshellObj : GameUnit.doubleShellObjList) {
if (this.getRec().intersects(doubleshellObj.getRec())&&red>0) {
doubleshellObj.setX(-100);
doubleshellObj.setY(-100);
GameUnit.removeList.add(doubleshellObj);
red-=3;
}
else if(this.getRec().intersects(doubleshellObj.getRec())&&red<=0){
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
//补给
GiftObj giftObj = new GiftObj(this.x,this.y);
GameUnit.giftObjList.add(giftObj);
GameUnit.gameUnitList.addAll(GameUnit.giftObjList);
doubleshellObj.setX(-100);
doubleshellObj.setY(-100);
GameUnit.removeList.add(doubleshellObj);
this.setX(-100);
this.setY(-100);
GameUnit.removeList.add(this);
StartWin.score+=5;
}
}
for (TripleShellObj tripshellObj : GameUnit.tripleShellObjList) {
if (this.getRec().intersects(tripshellObj.getRec())&&red>0) {
tripshellObj.setX(-100);
tripshellObj.setY(-100);
GameUnit.removeList.add(tripshellObj);
red-=5;
}
else if(this.getRec().intersects(tripshellObj.getRec())&&red<=0){
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
//补给
GiftObj giftObj = new GiftObj(this.x,this.y);
GameUnit.giftObjList.add(giftObj);
GameUnit.gameUnitList.addAll(GameUnit.giftObjList);
tripshellObj.setX(-100);
tripshellObj.setY(-100);
GameUnit.removeList.add(tripshellObj);
this.setX(-100);
this.setY(-100);
GameUnit.removeList.add(this);
StartWin.score+=5;
}
}
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
2号和1号的代码几乎一模一样,只是出现位置不同,所以在绘制的代码上有所不同。
5.敌方大boss
package obj;
import planewar.StartWin;
import unit.GameUnit;
import java.awt.*;
public class BossObj extends GameObj{
int health = 30;
public BossObj() {
super();
}
public BossObj(Image img, int width, int height, int x, int y, double speed, StartWin frame) {
super(img, width, height, x, y, speed, frame);
}
public BossObj(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
public BossObj(int x, int y) {
super(x, y);
}
@Override
public void paintSelf(Graphics g) {
super.paintSelf(g);
if(y<40){
y+=speed;
}else{
x+=speed;
if(x<0||x>360){
speed=-speed;
}
}
//首先是我方一级子弹和boss进行碰撞检测
for(ShellObj shellObj: GameUnit.shellObjList){
if(this.getRec().intersects(shellObj.getRec())&&health>0){
shellObj.setX(-100);
shellObj.setY(-100);
GameUnit.removeList.add(shellObj);
health--;
} else if (this.getRec().intersects(shellObj.getRec())&&health<=0) {
//绘制爆炸
ExplodeObj explodeObj=new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
shellObj.setX(-100);
shellObj.setY(-100);
GameUnit.removeList.add(shellObj);
this.x=-200;
this.y=-200;
GameUnit.removeList.add(this);
StartWin.state = 4;
StartWin.score+=20;
}
}
//首先是我方二级子弹和boss进行碰撞检测
for(DoubleShellObj doubleshellObj: GameUnit.doubleShellObjList){
if(this.getRec().intersects(doubleshellObj.getRec())&&health>0){
doubleshellObj.setX(-100);
doubleshellObj.setY(-100);
GameUnit.removeList.add(doubleshellObj);
health-=3;
} else if (this.getRec().intersects(doubleshellObj.getRec())&&health<=0) {
//绘制爆炸
ExplodeObj explodeObj=new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
doubleshellObj.setX(-100);
doubleshellObj.setY(-100);
GameUnit.removeList.add(doubleshellObj);
this.x=-200;
this.y=-200;
GameUnit.removeList.add(this);
StartWin.state = 4;
StartWin.score+=20;
}
}
//首先是我方三级子弹和boss进行碰撞检测
for(TripleShellObj tripleshellObj: GameUnit.tripleShellObjList){
if(this.getRec().intersects(tripleshellObj.getRec())&&health>0){
tripleshellObj.setX(-100);
tripleshellObj.setY(-100);
GameUnit.removeList.add(tripleshellObj);
health-=5;
} else if (this.getRec().intersects(tripleshellObj.getRec())&&health<=0) {
//绘制爆炸
ExplodeObj explodeObj=new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
tripleshellObj.setX(-100);
tripleshellObj.setY(-100);
GameUnit.removeList.add(tripleshellObj);
this.x=-200;
this.y=-200;
GameUnit.removeList.add(this);
StartWin.state = 4;
StartWin.score+=20;
}
}
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
对于大boss,和二号小boss有些类似,都是从屏幕顶端出现,然后左右移动。
4.各种子弹类
1.我方一级子弹
package obj;
import planewar.StartWin;
import java.awt.*;
public class ShellObj extends GameObj{
@Override
public Image getImg() {
return super.getImg();
}
public ShellObj() {
super();
}
public ShellObj(Image img, int width, int height, int x, int y, double speed, StartWin frame) {
super(img, width, height, x, y, speed, frame);
}
public ShellObj(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
@Override
public void paintSelf(Graphics g) {
super.paintSelf(g);
y -= speed;
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
代码比较简单,重写父类的方法就可以了,然后在绘制的方法中加入移动的代码,注意是从下往上进行移动,所以是y -= speed;
2.我方二级子弹
package obj;
import planewar.StartWin;
import java.awt.*;
public class DoubleShellObj extends GameObj{
public DoubleShellObj() {
super();
}
public DoubleShellObj(Image img, int width, int height, int x, int y, double speed, StartWin frame) {
super(img, width, height, x, y, speed, frame);
}
public DoubleShellObj(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
public DoubleShellObj(int x, int y) {
super(x, y);
}
@Override
public void paintSelf(Graphics g) {
super.paintSelf(g);
y-=speed;
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
代码一模一样,重写,再加上移动代码。
3.我方三级子弹
package obj;
import planewar.StartWin;
import java.awt.*;
public class TripleShellObj extends GameObj{
public TripleShellObj() {
super();
}
public TripleShellObj(Image img, int width, int height, int x, int y, double speed, StartWin frame) {
super(img, width, height, x, y, speed, frame);
}
public TripleShellObj(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
public TripleShellObj(int x, int y) {
super(x, y);
}
@Override
public void paintSelf(Graphics g) {
super.paintSelf(g);
y-=speed;
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
一模一样。
4.敌方大飞机子弹
package obj;
import planewar.StartWin;
import java.awt.*;
public class Enemy2BulletObj extends GameObj{
public Enemy2BulletObj() {
super();
}
public Enemy2BulletObj(Image img, int width, int height, int x, int y, double speed, StartWin frame) {
super(img, width, height, x, y, speed, frame);
}
public Enemy2BulletObj(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
@Override
public void paintSelf(Graphics g) {
super.paintSelf(g);
y+=speed;
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
代码也是几乎一样,只不过是从上往下发射子弹。
5.敌方1号boss子弹
package obj;
import planewar.StartWin;
import java.awt.*;
public class LittleBoss1Bullet extends GameObj{
public LittleBoss1Bullet() {
super();
}
public LittleBoss1Bullet(Image img, int width, int height, int x, int y, double speed, StartWin frame) {
super(img, width, height, x, y, speed, frame);
}
public LittleBoss1Bullet(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
public LittleBoss1Bullet(int x, int y) {
super(x, y);
}
@Override
public void paintSelf(Graphics g) {
super.paintSelf(g);
y+=speed;
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
6.敌方2号boss子弹
package obj;
import planewar.StartWin;
import unit.GameUnit;
import java.awt.*;
public class LittleBoss2Bullet extends GameObj{
int red = 2;
public LittleBoss2Bullet() {
super();
}
public LittleBoss2Bullet(Image img, int width, int height, int x, int y, double speed, StartWin frame) {
super(img, width, height, x, y, speed, frame);
}
public LittleBoss2Bullet(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
public LittleBoss2Bullet(int x, int y) {
super(x, y);
}
@Override
public void paintSelf(Graphics g) {
super.paintSelf(g);
this.y+=speed;
this.x -=(this.x- GameUnit.gameUnitList.get(StartWin.planeindex).getX())/30;
for (ShellObj shellObj: GameUnit.shellObjList){
if(this.getRec().intersects(shellObj.getRec())&&red>0){
shellObj.setX(-100);
shellObj.setY(-100);
GameUnit.removeList.add(shellObj);
red--;
}else if(this.getRec().intersects(shellObj.getRec())&&red<=0){
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
shellObj.setX(-100);
shellObj.setY(-100);
GameUnit.removeList.add(shellObj);
this.x=-200;
this.y=-200;
GameUnit.removeList.add(this);
StartWin.score+=3;
}
}
for (DoubleShellObj doubleshellObj : GameUnit.doubleShellObjList) {
if (this.getRec().intersects(doubleshellObj.getRec())&&red>0) {
doubleshellObj.setX(-100);
doubleshellObj.setY(-100);
GameUnit.removeList.add(doubleshellObj);
red-=3;
}
else if(this.getRec().intersects(doubleshellObj.getRec())&&red<=0){
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
doubleshellObj.setX(-100);
doubleshellObj.setY(-100);
GameUnit.removeList.add(doubleshellObj);
this.setX(-100);
this.setY(-100);
GameUnit.removeList.add(this);
StartWin.score+=3;
}
}
for (TripleShellObj tripshellObj : GameUnit.tripleShellObjList) {
if (this.getRec().intersects(tripshellObj.getRec())&&red>0) {
tripshellObj.setX(-100);
tripshellObj.setY(-100);
GameUnit.removeList.add(tripshellObj);
red-=5;
}
else if(this.getRec().intersects(tripshellObj.getRec())&&red<=0){
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUnit.explodeObjList.add(explodeObj);
GameUnit.removeList.add(explodeObj);
tripshellObj.setX(-100);
tripshellObj.setY(-100);
GameUnit.removeList.add(tripshellObj);
this.setX(-100);
this.setY(-100);
GameUnit.removeList.add(this);
StartWin.score+=3;
}
}
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
对于二号boss的子弹,这里有些不同,二号boss的子弹是追踪的,所以我们设定它可以被击毁,所以加了一个碰撞监测。
7.敌方boss子弹
package obj;
import planewar.StartWin;
import java.awt.*;
public class BossBullet extends GameObj{
public BossBullet() {
super();
}
public BossBullet(Image img, int width, int height, int x, int y, double speed, StartWin frame) {
super(img, width, height, x, y, speed, frame);
}
public BossBullet(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
public BossBullet(int x, int y) {
super(x, y);
}
@Override
public void paintSelf(Graphics g) {
super.paintSelf(g);
y+=speed;
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
5.其他类
1.背景类
package obj;
import planewar.StartWin;
import java.awt.*;
public class BgObj extends GameObj {
public BgObj() {
super();
}
public BgObj(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
public BgObj(Image img, int width, int height, int x, int y, double speed, StartWin frame) {
super(img, width, height, x, y, speed, frame);
}
@Override
public void paintSelf(Graphics g) {
super.paintSelf(g);
y+=speed;
if(y>=0){
y=-1800;
}
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
2.补给类
package obj;
import planewar.StartWin;
import unit.GameUnit;
import java.awt.*;
public class GiftObj extends GameObj{
public GiftObj() {
super();
}
public GiftObj(Image img, int width, int height, int x, int y, double speed, StartWin frame) {
super(img, width, height, x, y, speed, frame);
}
public GiftObj(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
public GiftObj(int x, int y) {
super(x, y);
}
@Override
public void paintSelf(Graphics g) {
super.img = GameUnit.giftImg;
super.width=64;
super.height=62;
super.paintSelf(g);
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
3.警告类
package obj;
import planewar.StartWin;
import java.awt.*;
public class WaringObj extends GameObj{
public WaringObj() {
super();
}
public WaringObj(Image img, int width, int height, int x, int y, double speed, StartWin frame) {
super(img, width, height, x, y, speed, frame);
}
public WaringObj(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
public WaringObj(int x, int y) {
super(x, y);
}
@Override
public void paintSelf(Graphics g) {
super.paintSelf(g);
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
4.爆炸类
package obj;
import java.awt.*;
public class ExplodeObj extends GameObj{
//定义一个image类型的静态数组,存放一串爆炸图
static Image[] explodePic = new Image[16];
//定义变量来记录爆炸图的次数
int explodeCount = 0;
//定义一个静态代码块来将爆炸图片放到数组当中
static{
for (int i = 0; i < explodePic.length; i++) {
explodePic[i] = Toolkit.getDefaultToolkit().getImage("img/explode/"+"e"+(i+1)+".gif");
}
}
public ExplodeObj(int x, int y) {
super(x, y);
}
@Override
public void paintSelf(Graphics g) {
if(explodeCount<16){
super.img = explodePic[explodeCount];
super.paintSelf(g);
explodeCount++;
}
}
}
6.游戏界面类
最后就是重头戏了,最重要的中枢,直接上代码。
package planewar;
import obj.*;
import unit.GameUnit;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class StartWin extends JFrame {
//记录游戏状态的变量
//未开始0 游戏中 1暂停2 失败3 通关4
public static int state = 0;
public static int score = 0;
BgObj bgObj = new BgObj(GameUnit.bdImg,0,-1800,2);
//定义图片变量
Image offScreenImage = null;
//引入我方飞机对象
PlaneObj planeObj = new PlaneObj(GameUnit.planeImg,37,41,290,550,0,this);
//引入子弹对象
//ShellObj shellObj = new ShellObj(GameUnit.shellImg,14,29,planeObj.getX(),planeObj.getY(),5,this);
//定义游戏绘制的次数
int count=1;
//创建一号boss的对象
LittleBoss1 littleBoss1 = new LittleBoss1(GameUnit.littleBoss1Img,172,112,-200,350,3,this);
//创建二号boss的对象
LittleBoss2 littleBoss2 = new LittleBoss2(GameUnit.littleBoss2Img,172,112,300,-150,2,this);
//创建boss对象
BossObj bossObj = new BossObj(GameUnit.bossImg,240,174,180,-180,3,this);
//记录我方飞机的索引
public static int planeindex = 0;
WaringObj waringObj=new WaringObj(GameUnit.warningImg,599,90,0,350,0,this);
public void launch(){
this.setVisible(true);
this.setSize(600,800);
this.setLocationRelativeTo(null);
this.setTitle("飞机大战");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//背景对象
GameUnit.gameUnitList.add(bgObj);
//飞机对象
GameUnit.gameUnitList.add(planeObj);
planeindex = GameUnit.gameUnitList.indexOf(planeObj);
//鼠标点击事件
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if(e.getButton()==1&&state==0){
state=1;//游戏开始状态
repaint();
}
}
});
this.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==32){
if(state==1){
state=2;
} else if (state==2) {
state=1;
}
}
}
});
while(true){
creatObj();
repaint();
try {
Thread.sleep(25);
}catch(Exception e){
e.printStackTrace();
}
}
}
@Override
public void paint(Graphics g) {
//初始化双缓存图片对象
if(offScreenImage==null){
offScreenImage=createImage(600,800);
}
//获取双缓存图片对象的画笔
Graphics gImage = offScreenImage.getGraphics();
gImage.fillRect(0,0,600,800);
if(state==0) {
gImage.drawImage(GameUnit.bdImg, 0, 0, null);
gImage.drawImage(GameUnit.bossImg, 190, 70, null);
gImage.drawImage(GameUnit.explodeImg, 270, 350, null);
gImage.drawImage(GameUnit.planeImg, 280, 470, null);
gImage.setColor(Color.blue);
gImage.setFont(new Font("仿宋", Font.BOLD, 30));
gImage.drawString("鼠标左键开始游戏", 180, 300);
}
if(state==1){
// bgObj.paintSelf(gImage);
// planeObj.paintSelf(gImage);
// shellObj.paintSelf(gImage);
GameUnit.gameUnitList.addAll(GameUnit.explodeObjList);
//不在单独绘制某个游戏元素,因为所有游戏元素都放入了所有元素集合当中,这里只需要将集合中的元素遍历出来,然后绘制相对应的图片
for (int i = 0; i < GameUnit.gameUnitList.size()-1; i++) {
GameUnit.gameUnitList.get(i).paintSelf(gImage);
}
GameUnit.gameUnitList.removeAll(GameUnit.removeList);
count++;
}
if(state==2){
gImage.drawImage(GameUnit.bdImg,0,0,null);
GameUnit.drawWord(gImage,"游戏暂停",Color.YELLOW,30,220,300);
}
if(state==3){
gImage.drawImage(GameUnit.bdImg,0,0,null);
GameUnit.drawWord(gImage,"游戏失败",Color.RED,30,220,300);
}
if(state==4){
gImage.drawImage(GameUnit.bdImg,0,0,null);
GameUnit.drawWord(gImage,"游戏通关",Color.GREEN,30,220,300);
}
//绘制游戏的积分面板
GameUnit.drawWord(gImage,score+"分",Color.green,40,30,100);
//将双缓存图片绘制在游戏窗口
g.drawImage(offScreenImage, 0, 0, null);
}
//用于批量创建物体的方法
void creatObj(){
if(count%15==0) {
if (PlaneObj.times == 0) {
GameUnit.shellObjList.add(new ShellObj(GameUnit.shellImg, 14, 29, planeObj.getX() + 12, planeObj.getY() - 20, 5, this));
//添加到所有对象集合的子弹对象并不是所有子弹的对象,而是新new出来的子弹对象
GameUnit.gameUnitList.add(GameUnit.shellObjList.get(GameUnit.shellObjList.size() - 1));
}
if(PlaneObj.times==1){
GameUnit.doubleShellObjList.add(new DoubleShellObj(GameUnit.doubleShellImg, 32, 64, planeObj.getX() + 10, planeObj.getY() - 20, 8, this));
//添加到所有对象集合的子弹对象并不是所有子弹的对象,而是新new出来的子弹对象
GameUnit.gameUnitList.add(GameUnit.doubleShellObjList.get(GameUnit.doubleShellObjList.size() - 1));
}
if(PlaneObj.times>=2){
GameUnit.tripleShellObjList.add(new TripleShellObj(GameUnit.tripShellImg, 64, 182, planeObj.getX() + 12, planeObj.getY() - 20, 15, this));
//添加到所有对象集合的子弹对象并不是所有子弹的对象,而是新new出来的子弹对象
GameUnit.gameUnitList.add(GameUnit.tripleShellObjList.get(GameUnit.tripleShellObjList.size() - 1));
}
}
if(count%15==0){
GameUnit.enemy1ObjList.add(new Enemy1Obj(GameUnit.enemy1Img,32,24,(int)(Math.random()*10)*60,0,5,this));
GameUnit.gameUnitList.add(GameUnit.enemy1ObjList.get(GameUnit.enemy1ObjList.size() - 1));
}
if(count%20==0) {
if (count % 100 == 0) {
GameUnit.enemy2ObjList.add(new Enemy2Obj(GameUnit.enemy2Img, 44, 67, (int) (Math.random() * 10) * 60, 0, 3, this));
GameUnit.gameUnitList.add(GameUnit.enemy2ObjList.get(GameUnit.enemy2ObjList.size() - 1));
}
if(GameUnit.enemy2ObjList.size()>0){
//获取大飞机最新产生的飞机的位置坐标
int x = (GameUnit.enemy2ObjList.get(GameUnit.enemy2ObjList.size()-1)).getX();
int y = (GameUnit.enemy2ObjList.get(GameUnit.enemy2ObjList.size()-1)).getY();
GameUnit.enemy2BulletObjList.add(new Enemy2BulletObj(GameUnit.enemy2bulletImg,14,25,x+17,y+55,5,this));
GameUnit.gameUnitList.add(GameUnit.enemy2BulletObjList.get(GameUnit.enemy2BulletObjList.size()-1));
}
}
if(count==600&&(!GameUnit.gameUnitList.contains(littleBoss1))){
GameUnit.gameUnitList.add(littleBoss1);
}
if(count==800&&(!GameUnit.gameUnitList.contains(littleBoss2))){
GameUnit.gameUnitList.add(littleBoss2);
}
if(count%15==0) {
if (GameUnit.gameUnitList.contains(littleBoss1)) {
GameUnit.littleBoss1BulletList.add(new LittleBoss1Bullet(GameUnit.littleBoss1BulletImg, 42, 42, littleBoss1.getX() + 75, littleBoss1.getY() + 100, 4, this));
GameUnit.gameUnitList.add(GameUnit.littleBoss1BulletList.get(GameUnit.littleBoss1BulletList.size() - 1));
}
}
if(count%40==0){
if(GameUnit.gameUnitList.contains(littleBoss2)){
GameUnit.littleBoss2BulletList.add(new LittleBoss2Bullet(GameUnit.littleBoss2BulletImg,21,59,littleBoss2.getX()+78,littleBoss2.getY()+100,8,this));
GameUnit.gameUnitList.add(GameUnit.littleBoss2BulletList.get(GameUnit.littleBoss2BulletList.size()-1));
}
}
if(count==1300&&(!GameUnit.gameUnitList.contains(bossObj))){
GameUnit.gameUnitList.add(bossObj);
}
if(count%20==0) {
if (GameUnit.gameUnitList.contains(bossObj)) {
//敌方1号boss子弹
GameUnit.littleBoss1BulletList.add(new LittleBoss1Bullet(GameUnit.littleBoss1BulletImg, 42, 42, bossObj.getX() + 10, bossObj.getY() + 130, 6, this));
GameUnit.gameUnitList.add(GameUnit.littleBoss1BulletList.get(GameUnit.littleBoss1BulletList.size() - 1));
//敌方2号boss的子弹
if (count % 40 == 0) {
GameUnit.littleBoss2BulletList.add(new LittleBoss2Bullet(GameUnit.littleBoss2BulletImg, 21, 59, bossObj.getX() + 220, bossObj.getY() + 130, 10, this));
GameUnit.gameUnitList.add(GameUnit.littleBoss2BulletList.get(GameUnit.littleBoss2BulletList.size() - 1));
}
//boss子弹
GameUnit.bossBulletList.add(new BossBullet(GameUnit.bossBulletImg, 91, 90, bossObj.getX() + 70, bossObj.getY() + 100, 9, this));
GameUnit.gameUnitList.add(GameUnit.bossBulletList.get(GameUnit.bossBulletList.size() - 1));
}
}
if(count==1250&&(!GameUnit.gameUnitList.contains(waringObj))){
GameUnit.gameUnitList.add(waringObj);
}
if(count==1290){
GameUnit.removeList.add(waringObj);
}
}
public static void main(String[] args) {
StartWin startWin = new StartWin();
startWin.launch();
}
}
后记
代码到这基本结束了,其中的工具类没有展示出来,但无非就是创建一下所用到的集合与图片对象,我觉得就没有必要展示了,因为所用的图片等等可能与我所用的不一样,可以自己去找一下。最后上演示视频(因为怕打不过所以我直接把子弹效果升到满级了)。
QQ录屏20240609164701