先看演示

Java简易飞机大战

源码链接:(内置图片)

此项目源码链接【百度网盘】提取码:1234https://pan.baidu.com/s/1EoBdg_47nYgLWgB6Zee9gg

一、基本介绍

1、创作背景:老师教完多线程后留的作业,主要是熟悉多线程,然后自己感兴趣就多多了一些功能,这个项目中没有用到接口相关的知识(创作的时候忘记了),感兴趣的可以自己改进

2、本人背景:大二在读学生,没有很深的java功底,如果有哪里需要改进的话还请指教

3、游戏大概内容:可选择是否双人游玩,随着分数的增高会增加玩家的攻击力和攻速,还有敌人的生命值和生成速度,有暂停功能

4、游戏需求分析:玩家可以灵活的操作飞机并发射子弹,敌人行进的速度不能相同(行进路线全是直行)

二、部分源码介绍

·1、主类

主要功能:创建一个JFrame和一个继承了JPanel类的GameJPanel对象,设置窗口的主要属性、添加按键监听

package playplane;import javax.swing.*;public class theWarOfPlane {public static final int WIDTH = 480;    //定义常量 窗口的宽public static final int HEIGHT = 750;   //定义常量 窗口的高public static void main(String[] args) {//定义主窗口和面板JFrame mainWindow = new JFrame("飞机大战/playplane");playplane.Global.gameJPanel=new GameJPanel();//给主窗口添加按键监听mainWindow.addKeyListener(new KeyListen());//加载这个工具类Global g=new Global();//布局为空才可以设置各组件和图片的位置playplane.Global.gameJPanel.setLayout(null);mainWindow.add(Global.gameJPanel);//主窗口的基础设置mainWindow.setSize(WIDTH, HEIGHT);                                      //设置窗口的长宽mainWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);     //设置窗口的关闭mainWindow.setLocationRelativeTo(null);                                 //窗口居中mainWindow.setVisible(true);                                            //窗口显示出来}}

2、所有飞行物类的父类

主要功能:规定所有飞行物的标准,例如:玩家的飞机、敌人的飞机和子弹这些类都继承这个类,并拥有一些飞行物必须有的属性

部分属性介绍:

1、坐标:这个对象所处的位置(图片的左上角)

2、图片:存有图片的对象

3、宽高:为了后面计算两个图片是否相碰,所有初始化时由程序员输入这个图片的宽和高

4、生命:这个对象的生命值,子弹也有生命值,虽然目前生命值都为1,但是后期扩展这个游戏时可能添加特殊子弹

5、速度:图片移动的速度

6、阵营:方便识别友方、敌方、中立,例如:敌机碰到右方子弹才会消失

package playplane;import java.awt.image.BufferedImage;/*** 所有飞行物的父类*/
public abstract class FlyingObject {//坐标private int x;private int y;//图片private BufferedImage img;//宽高private int width;private int height;//生命private int life;//速度private int speed;//阵营Camp camp;FlyingObject(int x, int y, BufferedImage img, int life, int speed, playplane.Camp camp) {this.img = img;//获取图片的宽和高用于判断子弹是否击中飞机this.width = img.getWidth();this.height = img.getHeight();this.x = x;this.y = y;this.life = life;this.speed=speed;this.camp=camp;}public int getSpeed() {return speed;}public void setSpeed(int speed) {this.speed = speed;}//移动public abstract void move();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 BufferedImage getImg() {return img;}public void setImg(BufferedImage 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 getLife() {return life;}public void setLife(int life) {this.life = life;}
}

3、子弹类

主要功能:生成子弹,在生成时指定这个子弹各方面的数值

属性介绍:

1、子弹方向:子弹生成时就决定它要行驶的方向,方向一开始有8种,后来为了增加游戏性,又加了两种,这里的wsad分别代表前后左右(玩过4399游戏的都懂)

方法介绍:

1、move():这是子弹的移动,有线程会不断的调用这个方法来移动子弹,仔细看会发现每次移动的距离就是它的速度

2、Injured():子弹受伤时调用这个方法,传入的num参数是收到的伤害数值(当时想的是也许后期有超级子弹呢,子弹生命比敌机还厚时,一个子弹就可以击毁多架飞机,所以子弹也可以受伤),Global类的介绍在下面

package playplane;import java.awt.image.BufferedImage;/*** 子弹类*/
public class Bullet extends FlyingObject {//子弹方向BulletDirection direction;Bullet(int x, int y, BufferedImage img, int life, int speed, Camp camp, BulletDirection direction) {super(x, y, img, life, speed, camp);this.direction = direction;}@Overridepublic void move() {//子弹移动的8种方向switch (direction) {case W -> setY(getY() - getSpeed());case S -> setY(getY() + getSpeed());case A -> setX(getX() - getSpeed());case D -> setX(getX() + getSpeed());case WA -> {setX(getX() - getSpeed() / 2);setY(getY() - getSpeed());}case WD -> {setX(getX() + getSpeed() / 2);setY(getY() - getSpeed());}case SA -> {setX(getX() - getSpeed() / 2);setY(getY() + getSpeed());}case SD -> {setX(getX() + getSpeed() / 2);setY(getY() + getSpeed());}case WWA -> {setX(getX() - getSpeed() / 3);setY(getY() - getSpeed());}case WWD -> {setX(getX() + getSpeed() / 3);setY(getY() - getSpeed());}}}/*** 收到伤害调用此方法*/public void Injured(int num) {//当前生命减去伤害setLife(getLife() - num);//如果生命小于0if (getLife() <= 0) {//删除这个对象的存在Global.allFlying.remove(this);}}
}

4、玩家一的类

基本介绍:这里我把2个玩家写了2个类,其实没必要,写之前没有想清楚,所以大家写项目前一定先构思清楚

主要功能:规定玩家的一些基本属性,初始化玩家时,直接创建对象就行

属性介绍:

1、射击模式:根据分数的不断增长,射击模式会变化,例如:发射多行子弹

方法介绍:

1、move():方法开始会判断是否达到地图边界,如果达到了,就调用Global中的方法将玩家一的WSAD都变为false,这样就不会移动了。Global.W类型是boolean,有专门的按键监听,按下时这个会变为true,松开按键时会变为false,有线程会不断的执行move()这个方法,这样就可以实现8个方向的灵活移动了,如果用Scanner的话是实现不了灵活移动的(会有卡顿和延迟)。仔细看move()方法可以看见有8个方向的判断。这里我把2个玩家的方向属性(W、S、A、D)都放在了Global里,其实这样不好,当时没想清楚,这些可以是类中的属性,大家写的时候可以把这些都写进类里。

2、shoot():会有线程不断的调用这个方法,方法中判断玩家一的射击模式然后在它的指定方向上生成子弹,生成时就是new一个对象出来,可以规定属性。ShootModel是自己写的枚举类型

3、Injred():受伤时调用这个方法

package playplane;import java.awt.image.BufferedImage;public class HeroPlane1 extends FlyingObject {//射击模式private playplane.ShootModel shoot;//创建玩家飞机时,需要指定初始坐标,图片和生命HeroPlane1(int x, int y, BufferedImage img, int life, int speed, playplane.Camp camp) {super(x, y, img, life,speed,camp);//射击等级初始为1shoot= playplane.ShootModel.SHOOT1;}//受伤/*** 收到伤害调用此方法*/public void Injured(int num){//当前生命减去伤害setLife(getLife()-num);//如果生命小于0if(getLife()<=0){//删除这个对象的存在playplane.Global.heroPlane1=null;}}//每个飞行物都有自己独特的移动方法@Overridepublic void move(){if(playplane.Global.heroPlane1.getY()<=10)playplane.Global.W=false;if(playplane.Global.heroPlane1.getX()<=-20)playplane.Global.A=false;if(playplane.Global.heroPlane1.getX()>=400)playplane.Global.D=false;if(playplane.Global.heroPlane1.getY()>=600)playplane.Global.S=false;//上if(playplane.Global.W&&!playplane.Global.A&&!playplane.Global.S&&!playplane.Global.D){setY(getY()-getSpeed());}//下if(!playplane.Global.W&&!playplane.Global.A&& playplane.Global.S&&!playplane.Global.D){setY(getY()+getSpeed());}//左if(!playplane.Global.W&& playplane.Global.A&&!playplane.Global.S&&!playplane.Global.D){setX(getX()-getSpeed());}//右if(!playplane.Global.W&&!playplane.Global.A&&!playplane.Global.S&& playplane.Global.D){setX(getX()+getSpeed());}//左上if(playplane.Global.W&& playplane.Global.A&&!playplane.Global.S&&!playplane.Global.D){setX(getX()-getSpeed());setY(getY()-getSpeed());}//右上if(playplane.Global.W&&!playplane.Global.A&&!playplane.Global.S&& playplane.Global.D){setX(getX()+getSpeed());setY(getY()-getSpeed());}//左下if(!playplane.Global.W&& playplane.Global.A&& playplane.Global.S&&!playplane.Global.D){setX(getX()-getSpeed());setY(getY()+getSpeed());}//右下if(!playplane.Global.W&&!playplane.Global.A&& playplane.Global.S&& playplane.Global.D){setX(getX()+getSpeed());setY(getY()+getSpeed());}}//需要生成子弹时调用这个方法public void shoot(){switch(shoot){case SHOOT1:playplane.Global.allFlying.add(new playplane.Bullet(getX()+45,getY()+10, playplane.Global.bullet,1,10, playplane.Camp.FRIEND1, playplane.BulletDirection.W));break;case SHOOT2:playplane.Global.allFlying.add(new playplane.Bullet(getX()+50,getY()+10, playplane.Global.bullet,1,10, playplane.Camp.FRIEND1, playplane.BulletDirection.W));playplane.Global.allFlying.add(new playplane.Bullet(getX()+40,getY()+10, playplane.Global.bullet,1,10, playplane.Camp.FRIEND1, playplane.BulletDirection.W));break;case SHOOT3:playplane.Global.allFlying.add(new playplane.Bullet(getX()+45,getY()+10, playplane.Global.bullet,1,10, playplane.Camp.FRIEND1, playplane.BulletDirection.W));playplane.Global.allFlying.add(new playplane.Bullet(getX()+40,getY()+10, playplane.Global.bullet,1,10, playplane.Camp.FRIEND1, playplane.BulletDirection.WA));playplane.Global.allFlying.add(new playplane.Bullet(getX()+50,getY()+10, playplane.Global.bullet,1,10, playplane.Camp.FRIEND1, playplane.BulletDirection.WD));break;case SHOOT4:playplane.Global.allFlying.add(new playplane.Bullet(getX()+50,getY()+10, playplane.Global.bullet,1,10, playplane.Camp.FRIEND1, playplane.BulletDirection.W));playplane.Global.allFlying.add(new playplane.Bullet(getX()+40,getY()+10, playplane.Global.bullet,1,10, playplane.Camp.FRIEND1, playplane.BulletDirection.W));playplane.Global.allFlying.add(new playplane.Bullet(getX()+40,getY()+10, playplane.Global.bullet,1,10, playplane.Camp.FRIEND1, playplane.BulletDirection.WA));playplane.Global.allFlying.add(new playplane.Bullet(getX()+50,getY()+10, playplane.Global.bullet,1,10, playplane.Camp.FRIEND1, playplane.BulletDirection.WD));break;case SHOOT5:playplane.Global.allFlying.add(new playplane.Bullet(getX()+50,getY()+10, playplane.Global.bullet,1,10, playplane.Camp.FRIEND1, playplane.BulletDirection.W));playplane.Global.allFlying.add(new playplane.Bullet(getX()+40,getY()+10, playplane.Global.bullet,1,10, playplane.Camp.FRIEND1, playplane.BulletDirection.W));playplane.Global.allFlying.add(new playplane.Bullet(getX()+40,getY()+10, playplane.Global.bullet,1,10, playplane.Camp.FRIEND1, playplane.BulletDirection.WA));playplane.Global.allFlying.add(new playplane.Bullet(getX()+50,getY()+10, playplane.Global.bullet,1,10, playplane.Camp.FRIEND1, playplane.BulletDirection.WD));playplane.Global.allFlying.add(new playplane.Bullet(getX()+40,getY()+10, playplane.Global.bullet,1,10, playplane.Camp.FRIEND1, playplane.BulletDirection.WWA));playplane.Global.allFlying.add(new Bullet(getX()+50,getY()+10, Global.bullet,1,10, playplane.Camp.FRIEND1, playplane.BulletDirection.WWD));}}public playplane.ShootModel getShoot() {return shoot;}public void setShoot(playplane.ShootModel shoot) {this.shoot = shoot;}}

5、按键监听(重磅)

主要功能:这个按键监听添加在JFrame上,负责游戏的全局监听。会跟根据Global.state(游戏状态:准备、暂停、开始、结束).。这两个方法分别是按键按下时的监听和松开时的监听

准备状态:按下空格键将state转变为开始状态,然后调用GameJpanel.action()后线程就开始运行

开始状态:按下i时游戏变为暂停状态,所有线程在运行的同时都在不停的判断游戏是否时暂停状态,如果是的话就用wait()暂停线程。玩家一的方向是WSAD,玩家二是wsad(上面我也说过,这个我写的并不好,还望大家引以为戒)。玩家的攻击键分别是J和1

暂停状态:按o唤醒线程继续开始游戏。开始游戏时记得将方向键和射击键的判断变为false,不然可能一结束暂停飞机就乱跑,用的notifyAll()幻想所有线程

结束状态:所有玩家都阵亡了,按p会重新调用GameJpanel.action()初始化游戏,游戏就可以重新开始了

package playplane;import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;public class KeyListen extends KeyAdapter {@Overridepublic void keyPressed(KeyEvent e) {//如果游戏是准备状态if (playplane.Global.state == playplane.GameState.READY) {if (e.getKeyChar() == ' ') {GameJPanel.action();//游戏状态转为【开始】playplane.Global.state = playplane.GameState.START;}}//游戏是暂停状态if (playplane.Global.state == playplane.GameState.PAUSE) {if (e.getKeyChar() == 'o') {synchronized (playplane.Global.object) {//方向键和攻击键状态清除playplane.Global.clearDirection();//唤醒所有线程playplane.Global.object.notifyAll();playplane.Global.state = playplane.GameState.START;}}}//如果游戏已经开始if (playplane.Global.state == playplane.GameState.START) {if (e.getKeyChar() == 'i') {playplane.Global.state= playplane.GameState.PAUSE;}switch (e.getKeyChar()) {case 'w' -> playplane.Global.W = true;case 's' -> playplane.Global.S = true;case 'a' -> playplane.Global.A = true;case 'd' -> playplane.Global.D = true;case 'j' -> playplane.Global.shoot1 = true;case '1' -> playplane.Global.shoot2 = true;}switch (e.getKeyCode()) {case KeyEvent.VK_LEFT:playplane.Global.a = true;break;case KeyEvent.VK_RIGHT:playplane.Global.d = true;break;case KeyEvent.VK_UP:playplane.Global.w = true;break;case KeyEvent.VK_DOWN:playplane.Global.s = true;break;}}if (playplane.Global.state == playplane.GameState.GAMEOVER) {if (e.getKeyChar() == 'p') {GameJPanel.action();playplane.Global.state = playplane.GameState.START;}}}@Overridepublic void keyReleased(KeyEvent e) {//如果游戏已经开始if (playplane.Global.state == GameState.START) {switch (e.getKeyChar()) {case 'w' -> playplane.Global.W = false;case 's' -> playplane.Global.S = false;case 'a' -> playplane.Global.A = false;case 'd' -> playplane.Global.D = false;case 'j' -> playplane.Global.shoot1 = false;case '1' -> playplane.Global.shoot2 = false;}switch (e.getKeyCode()) {case KeyEvent.VK_LEFT:playplane.Global.a = false;break;case KeyEvent.VK_RIGHT:playplane.Global.d = false;break;case KeyEvent.VK_UP:playplane.Global.w = false;break;case KeyEvent.VK_DOWN:Global.s = false;break;}}}
}

6、GameJPanel(游戏的主面板)

主要功能:这个类继承了JPanle类,主要为了重写paint()方法,重写后调用repaint()方法就会重绘面板了

方法介绍:

1、action()和chushihua():action()中会调用chushihua(),chushihua()主要负责重新初始化一些游戏属性,例如存飞行物的allFlying(ArrayLIst类型),游戏分数,敌人生成间隔,敌人初始生命值,玩家的攻速和攻击力都进行初始化。action()中会重新new一个玩家出来和新的线程。

2、paint():里面的内容就是面板上绘画的内容。根据游戏内容会绘画上不同的界面例如暂停和结束都会显示指定的界面。因为绘画的东西太多所以写在了不同的方法里,因为都继承了FlyingObject类所以绘画的时候有具体的X和Y坐标

package playplane;import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;public class GameJPanel extends JPanel {static void chushihua() {//飞行物品刷新playplane.Global.allFlying = new ArrayList<>();//清除之前的方向操作playplane.Global.clearDirection();//分数清零playplane.Global.score = 0;//敌人属性初始化if (playplane.Global.doublePerson)playplane.Global.productEnemyTime = 800;elseplayplane.Global.productEnemyTime = 1200;playplane.Global.enemySmallLife = 4;playplane.Global.enemyBigLife = 6;//玩家射速攻击力初始化playplane.Global.playerShootTIme1 = 250;playplane.Global.playerShootTIme2 = 250;playplane.Global.playerDamage1 = 1;playplane.Global.playerDamage2 = 1;}/*** 调用此方法,游戏开始*/public static void action() {//所有属性初始话chushihua();//创建玩家飞机playplane.Global.heroPlane1 = new HeroPlane1(80, 480, playplane.Global.playerPlane1, 3, 5, playplane.Camp.FRIEND1);//如果有第二个玩家if (playplane.Global.doublePerson) {playplane.Global.heroPlane2 = new HeroPlane2(250, 480, playplane.Global.playerPlane2, 3, 5, playplane.Camp.FRIEND2);//生成敌人时间间隔从1200->800playplane.Global.productEnemyTime = 800;}playplane.Global.t = new Time();playplane.Global.t.start();playplane.Global.m = new MainThread();playplane.Global.m.start();playplane.Global.shootThread1 = new ShootThread1();playplane.Global.shootThread1.start();playplane.Global.shootThread2 = new ShootThread2();playplane.Global.shootThread2.start();playplane.Global.e = new EnemyProduct();playplane.Global.e.start();}@Overridepublic void paint(Graphics g) {if (Global.state == GameState.GAMEOVER) {paintOver(g);return;}//如果游戏暂停if (Global.state == GameState.PAUSE) {paintPause(g);return;}//清空之前绘图super.paint(g);//绘制背景paintbackground(g);//绘制玩家飞机paintHeroPlane(g);//绘制除玩家飞机外的所有飞行物paintAllFlying(g);//设置字体格式Font font = new Font("幼圆", 1, 20);g.setFont(font);//左上角显示信息g.drawString("时间:" + Global.timeText, 10, 20);g.drawString("分数:" + Global.score, 10, 40);if (Global.heroPlane1 != null) {g.drawString("玩家一生命:" + playplane.Global.heroPlane1.getLife(), 10, 60);g.drawString("玩家一攻速:" + 1000 / playplane.Global.playerShootTIme1, 310, 20);g.drawString("玩家一攻击力:" + playplane.Global.playerDamage1, 310, 40);}if (playplane.Global.heroPlane2 != null) {g.drawString("玩家二生命:" + playplane.Global.heroPlane2.getLife(), 10, 80);g.drawString("玩家二攻速:" + 1000 / playplane.Global.playerShootTIme2, 310, 60);g.drawString("玩家二攻击力:" + playplane.Global.playerDamage2, 310, 80);}if (playplane.Global.state == GameState.START) {g.drawString("小飞机生命值:" + playplane.Global.enemySmallLife, 300, 100);g.drawString("大飞机生命值:" + playplane.Global.enemyBigLife, 300, 120);}}//绘制背景void paintbackground(Graphics g) {g.drawImage(playplane.Global.background, 0, 0, this);}//绘制暂停界面void paintPause(Graphics g) {g.drawImage(playplane.Global.backgroundPause, 0, 0, this);}//绘制游戏结束界面void paintOver(Graphics g) {g.drawImage(playplane.Global.backgroundOver, 0, 0, this);}//绘制玩家飞机void paintHeroPlane(Graphics g) {if (playplane.Global.heroPlane1 != null) {g.drawImage(playplane.Global.heroPlane1.getImg(), playplane.Global.heroPlane1.getX(), playplane.Global.heroPlane1.getY(), this);}if (playplane.Global.heroPlane2 != null) {g.drawImage(playplane.Global.heroPlane2.getImg(), playplane.Global.heroPlane2.getX(), playplane.Global.heroPlane2.getY(), this);}}//绘制所有除玩家外的飞行物void paintAllFlying(Graphics g) {if (playplane.Global.allFlying.size() != 0) {for (int i = 0; i < playplane.Global.allFlying.size(); i++) {FlyingObject f = Global.allFlying.get(i);if (f != null)g.drawImage(f.getImg(), f.getX(), f.getY(), this);}}}}

7、Global(工具类)

主要功能:提供两个图片是否相交的方法,加载图片到内存中,提供全局变量,从配置文件中读取信息

static代码块:负责加载图片到内存中,加载配置文件中的信息

package playplane;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Objects;
import java.util.ResourceBundle;/*** 工具类* 存储所有全局变量,方便各个类之间使用*/
public class Global {//玩家飞机static HeroPlane1 heroPlane1 = null;static HeroPlane2 heroPlane2 = null;//游玩时间static String time = "";//游戏主面板static GameJPanel gameJPanel;//分数static int score = 0;//显示时间和分数的文本框static String timeText = "--:--";//各种图片static BufferedImage playerPlane1;static BufferedImage playerPlane2;static BufferedImage enemyPlaneSmall;static BufferedImage enemyPlaneBig;static BufferedImage bullet;static BufferedImage background;static BufferedImage backgroundPause;static BufferedImage backgroundOver;//游戏是否已开始static GameState state = GameState.READY;//存储所有敌对飞行物static ArrayList<FlyingObject> allFlying = new ArrayList<>();//玩家发射子弹的间隔,默认是250static int playerShootTIme1 = 250;static int playerShootTIme2 = 250;//玩家初始伤害static int playerDamage1 = 1;static int playerDamage2 = 1;//是否是双人游戏static boolean doublePerson = true;static final Object object = new Object();//敌人生成间隔static int productEnemyTime = 1200;//敌人生命值static int enemySmallLife = 4;static int enemyBigLife = 6;//各种线程static Time t;static MainThread m;static ShootThread1 shootThread1;static ShootThread2 shootThread2;static EnemyProduct e;//玩家一的方向键状态是否按下static boolean W = false;static boolean S = false;static boolean A = false;static boolean D = false;static boolean w = false;static boolean s = false;static boolean a = false;static boolean d = false;//玩家是否处于发射状态static boolean shoot1 = false;static boolean shoot2 = false;//音乐文件static File file1 = new File("../music_plane/flight.wav");static File file2 = new File("../music_plane/菜单长.wav");static File file3 = new File("../music_plane/菜单短.wav");{//加载所有图片到内存中try {InputStream i1 = this.getClass().getResourceAsStream("img_plane/Hero1.png");InputStream i2 = this.getClass().getResourceAsStream("img_plane/Hero2.png");InputStream i3 = this.getClass().getResourceAsStream("img_plane/airplane.png");InputStream i4 = this.getClass().getResourceAsStream("img_plane/bigplane.png");InputStream i5 = this.getClass().getResourceAsStream("img_plane/bullet.png");InputStream i6 = this.getClass().getResourceAsStream("img_plane/background.png");InputStream i7 = this.getClass().getResourceAsStream("img_plane/pause.png");InputStream i8 = this.getClass().getResourceAsStream("img_plane/gameover.png");if (i1 != null)playerPlane1 = ImageIO.read(i1);if (i2 != null)playerPlane2 = ImageIO.read(i2);if (i3 != null)enemyPlaneSmall = ImageIO.read(i3);if (i4 != null)enemyPlaneBig = ImageIO.read(i4);if (i5 != null)bullet = ImageIO.read(i5);if (i6 != null)background = ImageIO.read(i6);if (i7 != null)backgroundPause = ImageIO.read(i7);if (i8 != null)backgroundOver = ImageIO.read(i8);} catch (IOException e) {e.printStackTrace();}//使用资源绑定器绑定属性配置文件ResourceBundle bundle = ResourceBundle.getBundle("playplane_basic_information");//读取配置文件中的信息String str1 = bundle.getString("whether_Doueble_Player");doublePerson = Boolean.parseBoolean(str1);}/*** 清楚之前按键的操作*/static void clearDirection() {W = false;S = false;A = false;D = false;shoot1 = false;shoot2 = false;w = false;s = false;a = false;d = false;}/*** 判断两个飞行物是否相交* 相交返回true** @param f1* @param f2* @return*/static boolean pictureIntersection(FlyingObject f1, FlyingObject f2) {int x01, x02, y01, y02, x11, x12, y11, y12;x01 = f1.getX();x02 = f1.getX() + f1.getWidth();y01 = f1.getY();y02 = f1.getY() + f1.getHeight();x11 = f2.getX();x12 = f2.getX() + f2.getWidth();y11 = f2.getY();y12 = f2.getY() + f2.getHeight();int zx = Math.abs(x01 + x02 - x11 - x12);int x = Math.abs(x01 - x02) + Math.abs(x11 - x12);int zy = Math.abs(y01 + y02 - y11 - y12);int y = Math.abs(y01 - y02) + Math.abs(y11 - y12);if (zx <= x && zy <= y)return true;return false;}}

结尾

我把所有线程都写在一个java文件中了,所以这里就不展示了,想看的话可以下载原文件。

此文章仅供学习分享,禁止未授权转载!

本人也觉得项目的结构不够好,请大家引以为戒,在写项目前先构思好

用Java实现简易的飞机大战---附源码和图片相关推荐

  1. java计算机毕业设计婚恋网站(附源码、数据库)

    java计算机毕业设计婚恋网站(附源码.数据库) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(Inte ...

  2. Java Swing图书管理系统桌面软件附源码

    Java Swing图书管理系统桌面软件附源码,亲测可运行. 功能界面如下: 登录界面,默认账号admin密码admin 主功能界面: 添加图书功能界面: 部分源码: 完整源码下载地址: JavaSw ...

  3. 使用Java实现发送微信消息(附源码)_此程序在手再也不怕对象跟你闹了

    使用Java实现发送微信消息(附源码)_此程序在手再也不怕对象跟你闹了 此程序在手再也不怕女朋友跟你闹了!!!!自从有了女朋友比如:早安.晚安之类的问候语可不能断,但是也难免有时候会忘记那么该咋么办呢 ...

  4. java计算机毕业设计后勤管理系统(附源码、数据库)

    java计算机毕业设计后勤管理系统(附源码.数据库) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(In ...

  5. java计算机毕业设计网上拍卖系统(附源码、数据库)

    java计算机毕业设计网上拍卖系统(附源码.数据库) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(In ...

  6. java计算机毕业设计健身俱乐部管理系统(附源码、数据库)

    java计算机毕业设计健身俱乐部管理系统(附源码.数据库) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ Eclispe ...

  7. JAVA计算机毕业设计美容院管理系统(附源码、数据库)

    JAVA计算机毕业设计美容院管理系统(附源码.数据库) 目运行 环境项配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(I ...

  8. java计算机毕业设计汽车美容管理(附源码、数据库)

    java计算机毕业设计汽车美容管理(附源码.数据库) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(In ...

  9. JAVA计算机毕业设计企业门户网站(附源码、数据库)

    JAVA计算机毕业设计企业门户网站(附源码.数据库) 目运行 环境项配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(In ...

最新文章

  1. 通过transpose和flip实现图像旋转90/180/270度
  2. hadoop集群运维碰到的问题汇总
  3. 90.前端 :执行方法前提示功能
  4. ASCII码表完整版
  5. Oracle学习:数值函数与转换函数
  6. python如何安装wordcloud_不知如何利用Python中wordcloud的安装和使用?这里手把手教你...
  7. x86汇编语言-从实模式到保护模式----第五章
  8. codeforces——961A Tetris
  9. 获取css样式的方法
  10. 在 Panorama 页面中添加 ApplicationBar
  11. map赋值给另一个map_如何写出一个能让面试官直呼“666”的深拷贝?
  12. java怎么反编译_Java入门教程-Java的反编译
  13. 智能家居有线系统KNX的介绍
  14. 第二章:项目管理的主要作用
  15. HTML5 QQ登录背景动态图片
  16. PDF怎么转图片?快把这些方法收好
  17. 剖析公司技术栈,看看是否对大家适用!
  18. 神经网络学习4【误差传递与权重更新】
  19. 字符串格式化(format()使用)
  20. Android 接入VK登录

热门文章

  1. 鹅厂机器狗花式穿越10m梅花桩:前空翻、单桩跳、起身作揖...全程不打一个趔趄...
  2. SEO单页优化技巧与软文推广
  3. 【原创】SystemVerilog中的多态和虚方法
  4. Excel函数大全-09逻辑函数
  5. Docker容器中启动Arthas异常
  6. NE555芯片知识应用讲解
  7. android平台mmi开发,落实产品本土化,奥迪选择从全新MMI系统开始下手!
  8. v8引擎编译全记录2021-2-23
  9. 阅读笔记:Universal Domain Adaptation through Self-Supervision
  10. java 安装报错2503,Windows运维之Win10安装msi程序报错2503和2502错误解决方案