用java编写飞机大战

瑾寰 2024-10-10 12:05:02 阅读 85

游戏界面使用JFrame和JPanel构建。背景图通过BG类绘制。英雄机和敌机在界面上显示并移动。子弹从英雄机发射并在屏幕上移动。游戏有四种状态:READY、RUNNING、PAUSE、GAMEOVER。状态通过鼠标点击进行切换:点击开始游戏(从READY变为RUNNING)。点击重新开始游戏(从GAMEOVER变为READY)。鼠标移出窗口时游戏暂停(从RUNNING变为PAUSE)。鼠标移入窗口时游戏继续(从PAUSE变为RUNNING)。开局默认玩家生命值为3,分数为0。每隔一定时间随机生成敌机(小飞机、大飞机、小飞碟)。敌机在屏幕上移动,并与英雄机进行碰撞检测。英雄机可以发射子弹。子弹在屏幕上移动,并与敌机进行碰撞检测。英雄机与敌机发生碰撞时,英雄机会损失一条生命值。子弹与敌机发生碰撞时,敌机会被摧毁,玩家的分增加。当子弹与奖励机发生碰撞时,奖励机会被摧毁,玩家随机获得两张奖励(生命值加1、双倍子弹)。在屏幕左上角显示当前的生命值和得分。生命值减少到0时,游戏进入结束状态。再次点击,重新开始游戏。

1.图片素材(百度网盘分享)

链接:https://pan.baidu.com/s/10QiTcddI_Zxw5jbn8fmOpA?pwd=huan 

提取码:huan

2.主页面world.java

<code>package plane.gzeu;

import javax.swing.*;

import java.awt.*;

import java.awt.event.MouseAdapter;

import java.awt.event.MouseEvent;

import java.util.Arrays;

import java.util.Timer;

import java.util.TimerTask;

public class World extends JPanel {

//ImageIcon类:保存图片的路径----->读取图片

// ImageIcon icon = new ImageIcon("images\\background.png");

// BG bg = new BG(0,0,420,700,2);

// Airplane airplane = new Airplane(100,200,300,620,2);

// Bee bee = new Bee(200,100,200,700,2);

BG bg = new BG();

EnemyPlane [] planes;

Hero hero;

int index; //用来控制敌机的数量

Bullet[] bullets; //创建子弹的数组

int life; //英雄机的生命值

int score; //分数

//定义游戏的四种状态:准备,运行,暂停,结束(常量)

public static final int READY = 0;

public static final int RUNNING = 1;

public static final int PAUSE = 2;

public static final int GAMEOVER = 3;

//游戏的初始状态

int state = READY;

// Airplane [] airPlanes = new Airplane[10];

// Bigairplane [] bigAirPlanes = new Bigairplane[10];

// Bee [] bee = new Bee[10];

// Bom [] bom = new Bom[4];

// Bullet [] bullets = new Bullet[3];

// Hero [] hero =new Hero[2];

//初始化方法

public void init(){

bg = new BG();

hero = new Hero();

planes = new EnemyPlane[0]; //默认一个敌机都没有

bullets = new Bullet[0]; //默认一个子弹都没有

index = 0; //默认从0开始

life = 3; //默认3条命

score = 0; //分数为0

}

public World() {

init();

// for(int i=0;i<planes.length;i++){

// if(i%2==0){

// planes[i]=new Airplane();

// }

// else if(i%5==0 && i%2!=0){

// planes[i] = new Bee();

// }

// else {

// planes[i] = new Bigairplane();

// }

// }

// for(int i =0;i<airPlanes.length;i++){

// airPlanes[i] = new Airplane();

// bigAirPlanes[i]=new BigAirPlane();

// bee[i]=new Bee();

// bom[i]=new Bom();

// bullets[i]=new Bullet();

// hero[i]=new Hero();

}

//生成敌机的方法

public void createPlane(){

if(index%16==0){

int n = (int)(Math.random()*10);

EnemyPlane plane;

switch (n){

case 9 :

plane = new Bee(); //10%生成小飞碟

break;

case 8 :

case 7 :

plane = new Bigairplane(); //20%生成大飞机

break;

default:

plane = new Airplane(); //70%生成小飞机

}

//将敌机存入数组中之前,要先对数组进行扩容处理

planes = Arrays.copyOf(planes,planes.length+1);

//将生存的敌机放入数组的最后一个位置

planes[planes.length-1] = plane;

}

}

// for(int i =0;i<bigAirPlanes.length;i++){

// bigAirPlanes[i]=new Bigairplane();

// }

// }

//绘制图片printing

@Override

public void paint(Graphics g) { //paint挂载到当前类,当前类实例化(创建对象)时自动调用

// super.paint(g);

// icon.paintIcon(this,g,0,y1++); //绘制背景,默认第一个绘制

// bg.icon.paintIcon(this,g,(int)bg.x,(int)bg.y);

// bg.move();

// airplane.icon.paintIcon(this,g,(int)airplane.x,(int)airplane.y);

// bee.icon.paintIcon(this,g,(int)bee.x,(int)bee.y);

bg.painting(g);

hero.painting(g);

for(int i=0;i<planes.length;i++){

planes[i].painting(g);

}

for(int i=0;i<bullets.length;i++){

bullets[i].painting(g);

}

g.setColor(new Color(255,255,255));

//设置字体

g.setFont(new Font("微软雅黑",Font.BOLD,20));

g.drawString("生命值"+life,20,20);

g.drawString("分数"+score,20,40);

if(state==READY){

Images.start.paintIcon(this,g,0,0);

}

if(state==PAUSE){

Images.pause.paintIcon(this,g,0,0);

}

if(state==GAMEOVER){

Images.gameover.paintIcon(this,g,0,0);

}

// for(int i =0;i<airPlanes.length;i++){

// airPlanes[i].painting(g);

// bigAirPlanes[i].painting(g);

// bee[i].painting(g);

// bom[i].painting(g);

// bullets[i].painting(g);

// hero[i].painting(g);

// }

// for(int i =0;i<bigAirPlanes.length;i++){

// bigAirPlanes[i].painting(g);

// }

repaint();//刷新窗口

}

public static void main(String[] args) {

//1.显示画框(外层):JFrame

JFrame jf = new JFrame();

//2.显示面板:Jpanel

World jp =new World();

//3.将面板放入画框中:

jf.add(jp);

//对窗口进行设置

jf.setTitle("我的窗口");//设置标题

jf.setSize(436,700); //设置窗口大小

jf.setLocationRelativeTo(null); //居中显示

jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置关闭窗口后自动结束程序

//4.显示窗口

jf.setVisible(true);

jp.action();

}

//唤醒定时器的方法

public void action(){

java.util.Timer timer = new Timer();

MyTesk mt = new MyTesk();

timer.schedule(mt,1000,1000/50);

this.addMouseListener(new MouseAdapter() {

//监听鼠标点击

@Override

public void mouseClicked(MouseEvent e) {

if(state==READY){

state=RUNNING;

}

if(state==GAMEOVER){

state=READY;

init();

}

}

//鼠标移除

@Override

public void mouseExited(MouseEvent e) {

// System.out.println("鼠标移出");

if(state==RUNNING){

state=PAUSE;

}

}

//鼠标移入

@Override

public void mouseEntered(MouseEvent e) {

if(state==PAUSE){

state=RUNNING;

}

}

});

//匿名内部类

MouseAdapter mouseAdapter = new MouseAdapter() {

@Override

public void mouseMoved(MouseEvent e) {

if(state==RUNNING){

int x = e.getX();

int y = e.getY();

hero.move(x,y);

}

}

};

//安装监听器

this.addMouseMotionListener(mouseAdapter);

}

public void createBullet(){

if(!hero.isLiving()){ //英雄机死亡不发射子弹

return;

}

if(index%17==0){

Bullet[] bullets1 = hero.double_fire();

//俩个数组的合并

Bullet[] arr = Arrays.copyOf(bullets,bullets.length+bullets1.length);

System.arraycopy(bullets1,0,arr,bullets.length,bullets1.length);

bullets = arr;

// Bullet bullet =hero.fire(); //英雄机调用fire方法生成子弹

// //将子弹放入数组中

// bullets = Arrays.copyOf(bullets,bullets.length+1); //子弹扩容

// bullets[bullets.length-1] = bullet;

}

}

//加分的方法

public void addScore(FlyingObjesct plane){

if(plane.isDead()){

if(plane instanceof Enemy){

Enemy enemy = (Enemy) plane; //需要做一个强制转化

score += enemy.getScore();

}

if(plane instanceof Aword){

Aword aword = (Aword) plane;

int type =aword.getAword();

if(type == Aword.DOUBLE_FIRE){

hero.getdouble_fire();

}

if(type == Aword.LIFE){

life++;

}

}

}

}

//检测敌机与英雄机的碰撞

public void hero_hit(){

if(hero.isLiving()){

for(int i=0;i<planes.length;i++){

if(!planes[i].isLiving()){

continue;

}

if(hero.bong(planes[i])){

hero.goDead();

planes[i].goDead();

break;

}

}

}

else if(hero.isWait()){ //僵尸状态

if(life>1){

//重新开始

hero = new Hero();

//清屏

for(int i=0;i<planes.length;i++){

planes[i].goDead();

}

life--;

}

else{

life--;

state=GAMEOVER;

}

}

}

//检测每个敌机与子弹的碰撞情况

public void hit(){

for(int i=0;i<bullets.length;i++){

Bullet bullet = bullets[i]; //拿出每一颗子弹

if(!bullet.isLiving()){

continue;

}

for(int j=0;j<planes.length;j++){

FlyingObjesct p = planes[j];

if(!p.isLiving()){

continue;

}

if(p.bong(bullet)){ //被击中

p.attack();

bullet.goDead();

addScore(p);

}

}

}

}

//清理爆炸的飞机

public void clean(){

//清除飞机

EnemyPlane[] living = new EnemyPlane[planes.length];

int index = 0;

for(int i=0;i<planes.length;i++){ //遍历敌机数组

if(planes[i].isWait() || planes[i].outOfBound()){ //如果是等待状态的效果就跳过

continue;

}

living[index++] = planes[i]; //将不是等待状态的敌机存在living里面

}

planes = Arrays.copyOf(living,index);

//清除子弹

Bullet[] livingBullet = new Bullet[bullets.length];

index = 0;

for(int i=0;i<bullets.length;i++){

if(bullets[i].isDead() || bullets[i].outOfBound()){ //如果是已经爆炸的子弹就跳过

continue;

}

livingBullet[index++] = bullets[i];

}

bullets = Arrays.copyOf(livingBullet,index);

}

class MyTesk extends TimerTask {

@Override

public void run() {

index++;

if(state == RUNNING){

createPlane(); //调用生成敌机的方法

createBullet(); //调用生成子弹的方法

hit();//调用子弹击打的效果

clean(); //调用清理敌机方法

hero_hit();

bg.move();

for(int i =0;i<planes.length;i++){

planes[i].move();

}

for(int i =0;i<bullets.length;i++){

bullets[i].move();

}

}

}

}

}

3.小飞机类Airplane.java

package plane.gzeu;

import javax.swing.*;

//飞机类

public class Airplane extends EnemyPlane implements Enemy{ // 实现接口时,要实现接口中的方法

public Airplane(){

this.images = Images.airplane;

w = images[0].getIconWidth();

h = images[0].getIconHeight();

x=(int)(Math.random()*(420-images[0].getIconWidth()));

y=-2*images[0].getIconHeight();

this.step=(Math.random()*2.5+0.7);

this.icon=new ImageIcon("images\\airplane1.png");

// this.icon = Images.airplane[0];

}

public Airplane(double x, double y, double w, double h,double speed) {

// super(x, y, w, h);

this.step=speed;

this.icon=Images.airplane[0];

}

@Override

public int getScore() {

return 10;

}

}

4.大飞机类Bigairplane

package plane.gzeu;

//大飞机类

public class Bigairplane extends EnemyPlane implements Enemy{

public Bigairplane(double x, double y, double w, double h,double step) {

// super(x, y, w, h);

this.step=step;

this.icon = Images.bigairplane[0];

}

public Bigairplane(){

this.images = Images.bigairplane; //初始化数组

w = images[0].getIconWidth();

h = images[0].getIconHeight();

x=(int)(Math.random()*(420-images[0].getIconWidth()));

y=-2*images[0].getIconHeight();

this.step=(Math.random()*3.5+0.7);

// this.icon = Images.bigairplane[0];

life = 4;

}

@Override

public int getScore() {

return 50;

}

}

5.英雄机类Hero.java

package plane.gzeu;

import javax.swing.*;

import static plane.gzeu.Images.bullet;

public class Hero extends EnemyPlane{

public Hero(){

this.images = Images.hero;

x=431/2-images[0].getIconWidth()/2;

y=510;

w=images[0].getIconWidth();

h=images[0].getIconHeight();

// this.speed=0.2;

this.icon = Images.hero[0];

}

public Hero(double x, double y, double w, double h,double step) {

// super(x, y, w, h);

this.step=step;

// this.icon = new ImageIcon("images\\hero1.png"); //设置了Images类直接调用类名就可以引用图片

this.icon = Images.hero[0];

}

@Override

public void move() {}

//接收鼠标的坐标

public void move(int x,int y) {

this.x= x-images[0].getIconWidth()/2;

this.y = y-images[0].getIconHeight()/2;

}

/*

* 子弹的位置(在英雄机上) b.x = h.x-images[0].getIconWidth()/2; b.y=h.y

* 子弹的移动:向上:b.y-=b.step;

* 子弹是无限的:数序扩容

* 射击方法:当英雄机调用一次射击方法时,就发射一个子弹

* */

//射击的方法

public Bullet fire(){

double x = this.x+w/2-4; //获取英雄机的x坐标

Bullet bullet = new Bullet(x,y);//将处理过后的坐标传给子弹

return bullet; //将子弹返回

}

//获取双倍子弹的方法

int doubleTime = 0; // 双倍子弹的时间,20次

public void getdouble_fire(){

doubleTime = 20;

}

//双倍子弹方法

public Bullet[] double_fire(){

if(doubleTime>0){

double x = this.x+w/2-7;

double x1 = this.x+w/2-2; //获取英雄机的x坐标

Bullet bullet1 = new Bullet(x,y);

Bullet bullet2 = new Bullet(x1,y);//将处理过后的坐标传给子弹

Bullet [] bullets = new Bullet[]{bullet1,bullet2};

// return new Bullet[]{bullet1,bullet2};

return bullets;

}

else {

double x = this.x+w/2-4; //获取英雄机的x坐标

Bullet bullet1 = new Bullet(x,y);

return new Bullet[]{bullet1};

}

//

}

//测试

// public static void main(String[] args) {

// Hero hero = new Hero();

// hero.move(200,300);

// Bullet bullet = hero.fire();

// System.out.println(bullet.x+" "+bullet.y);

// }

}

6.敌机类Bee.java

package plane.gzeu;

import javax.swing.*;

public class Bee extends EnemyPlane implements Aword {

double speed1;

public Bee(){

this.images = Images.bee;

w = images[0].getIconWidth();

h = images[0].getIconHeight();

x=(int)(Math.random()*(420-images[0].getIconWidth()));

y=-2*images[0].getIconHeight();

this.step=(Math.random()*4.5+2.5);

this.speed1=(Math.random()*3.5+0.5);

// this.icon=new ImageIcon("images\\bee0.png");

this.icon=Images.bee[0];

life = 6;

}

public Bee(double x, double y, double w, double h,double step) {

// super(x, y, w, h);

this.step=step;

this.icon = Images.bee[0];

}

@Override

public void move() {

y+=speed1;

x+=step;

if(x>431-images[0].getIconWidth()){

step = -step;

}

if(x<=0){

step = -step;

}

}

@Override

public int getAword() {

return Math.random()>0.5?DOUBLE_FIRE:LIFE;

}

}

7.背景类BG.java

package plane.gzeu;

import javax.swing.*;

import java.awt.*;

//背景类(子类)

//继承FlyingObjesct类,得到FlyingObjesct类的方法及属性

public class BG extends FlyingObjesct {

double y0;

public BG(){

x = 0;

y = 0;

icon = Images.bg;

w = icon.getIconWidth();

h = icon.getIconHeight();

y0 = -h;

step = 2;

}

public BG(double x, double y, double w, double h,double step) {

super(x, y, w, h); //重载:调用父类的构造方法,实现方法复用

this.step = step;

this.icon = Images.bg; //背景是固定的

}

public void painting(Graphics g){

icon.paintIcon(null,g,(int)x,(int)y);

icon.paintIcon(null,g,(int)x,(int)y0);

}

@Override

public void move() {

y+=step;

y0+=step;

if(y>=h){

y=-h;

}

if(y0>=h){

y0=-h;

}

}

}

8.爆炸类Bom.java

package plane.gzeu;

import javax.swing.*;

public class Bom extends EnemyPlane{

public Bom(){

x=(int)(Math.random()*370);

y=(int)(Math.random()*370);

this.step = 0.2;

this.icon = Images.bom[0];

}

public Bom(double x, double y, double w, double h, double speed) {//要重写父类的构造方法。新增一个速度

// super(x, y, w, h);//重载:调用父类的构造方法,实现方法复用

this.step=speed;

this.icon=Images.bom[0];

}

}

9.子弹类Bullet.java

package plane.gzeu;

import javax.swing.*;

//继承FlyingObjesct类,得到FlyingObjesct类的方法及属性

public class Bullet extends EnemyPlane {

public Bullet(double x,double y){

this.icon = Images.bullet;

w = icon.getIconWidth();

h = icon.getIconHeight();

this.x = x;

this.y = y;

step = 2;

}

public Bullet(){

x=(int)(Math.random()*370);

y=(int)(Math.random()*370);

this.step = 0.2;

this.icon = Images.bullet;

}

public Bullet(double x, double y, double w, double h, double step) {

// super(x, y, w, h); //重载:调用父类的构造方法,实现方法复用

this.step = step;

this.icon = Images.bullet; //背景是固定的

}

@Override

public void move() {

y-=step;

}

}

10.三种敌机总类EnemyPlane.java

package plane.gzeu;

public abstract class EnemyPlane extends FlyingObjesct {

@Override

public void move() {

y+=step;

}

}

11.飞行物的总类(父类)FlyingObjesct.java

package plane.gzeu;

import javax.swing.*;

import java.awt.*;

//飞行物的总类(父类)

public abstract class FlyingObjesct {

public static final int LIVING = 1; //活着

public static final int DEAD = 0; //死亡

public static final int WAIT = -1; //等待死亡(播放爆炸动画)

//飞机默认是活着的

public int state = LIVING;

//飞机的生命值

public int life = 2;

public double x,y,step,w,h;//step速度

public ImageIcon icon; //图片

// Images images;

public ImageIcon[] images; //数组

public int index = 0;

public ImageIcon [] boms = Images.bom; //存放爆炸效果的图片

//赋初值:构造方法

//快速生成构建方法:快捷键Alt+Insert

public FlyingObjesct(double x, double y, double w, double h) {

this.x = x;

this.y = y;

this.w = w;

this.h = h;

}

//当飞机击打一次,生命值减一,当生命值为0时,进入死亡状态

public boolean attack(){

if(life>0){

life--;

if(life==0){

state = DEAD;

}

return true;

}

return false;

}

//让敌机快速去死

public boolean goDead(){

if(state==LIVING){

life = 0;

state = DEAD;

return true;

}else{

return false;

}

}

//判断飞机的三种状态

public boolean isLiving(){

return state==LIVING; //判断是否活着

}

public boolean isDead(){

return state==DEAD; //判断是否死了

}

public boolean isWait(){

return state==WAIT; //判断是否等待死亡

}

/*实现动画效果

* 1.用数组存储动画效果图片

* 2.初始化数组

* 3.定义一个计数器,作为切换图片的控制条件

* 4.写一个方法,实现切换图片的操作

* */

int i;

public void nextImage(){

switch (state){

case LIVING:

if(images == null) {

return;

}

icon = images[index++/300%images.length]; //0-[数组的长度-1]

break;

case DEAD:

if(boms==null){

return;

}

if(i++/300==boms.length){

state = WAIT;

return;

}

icon = boms[i++/300];

}

}

public FlyingObjesct(){}//无参构造

//移动

public abstract void move();

//绘制图形 方法

public void painting(Graphics g){

nextImage();

icon.paintIcon(null,g,(int)x,(int)y);

}

//检测敌机是否碰到子弹:判断条件中心距c=H/2+h/2

public boolean bong(FlyingObjesct bullet){

FlyingObjesct p =this;

double a = Math.min(p.w,p.h)/2;

double b = Math.min(bullet.w,bullet.h)/2;

double x1=p.x+p.w/2;

double y1=p.y+p.h/2;

double x2=bullet.x+bullet.w/2;

double y2=bullet.y+bullet.h/2;

double c = Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));

return c<=a+b;

}

//清除越界的敌机和子弹条件: y<-h-100 || y>700+100

public boolean outOfBound(){

if(y<-h-100){

return true;

}else if(y>700+100){

return true;

}

return false;

}

}

12.图片类Images.java

package plane.gzeu;

import javax.swing.*;

public class Images {

public static ImageIcon bg;

public static ImageIcon bullet;

public static ImageIcon start;

public static ImageIcon pause;

public static ImageIcon gameover;

public static ImageIcon[] hero;

public static ImageIcon[] bigairplane;

public static ImageIcon[] bee;

public static ImageIcon[] airplane;

public static ImageIcon[] bom;

static {

airplane = new ImageIcon[2];

airplane[0] = new ImageIcon("images/airplane0.png");

airplane[1] = new ImageIcon("images/airplane1.png");

bigairplane = new ImageIcon[2];

bigairplane[0] = new ImageIcon("images/bigairplane0.png");

bigairplane[1] = new ImageIcon("images/bigairplane1.png");

bee = new ImageIcon[2];

bee[0] = new ImageIcon("images\\bee0.png");

bee[1] = new ImageIcon("images\\bee1.png");

bom = new ImageIcon[4];

bom[0] = new ImageIcon("images/bom1.png");

bom[1] = new ImageIcon("images/bom2.png");

bom[2] = new ImageIcon("images/bom3.png");

bom[3] = new ImageIcon("images/bom4.png");

bg = new ImageIcon("images\\background.png");

bullet = new ImageIcon("images\\bullet.png");

start = new ImageIcon("images\\start.png");

pause = new ImageIcon("images\\pause.png");

gameover = new ImageIcon("images\\gameover.png");

hero = new ImageIcon[2];

hero[0] = new ImageIcon("images\\hero0.png");

hero[1] = new ImageIcon("images\\hero1.png");

}

//测试图片是否传过来了

public static void main(String[] args) {

System.out.println(start.getImageLoadStatus()); //如果输出8那图片传过来了,输出其他数字有问题

System.out.println(bg.getImageLoadStatus());

System.out.println(bom[0].getImageLoadStatus());

System.out.println(bee[1].getImageLoadStatus());

System.out.println(airplane[1].getImageLoadStatus());

}

}

13.获得奖励的接口Aword.java

package plane.gzeu;

//获得奖励的接口

public interface Aword {

int DOUBLE_FIRE = 1; //第一种奖励,双倍火力

int LIFE = 2; //加生命值

int getAword(); //获得奖励的方法

}

14.获得分数的接口Enemy.java

package plane.gzeu;

//获得分数的接口

public interface Enemy { //加分

// int a = 5;//都是静态常量

// public abstract void add(); //都是抽象方法

public int getScore(); //获得分数的方法

}

运行界面:

开始界面

存活界面:

暂停界面

结束界面



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。