写一个JAVA飞机大战小游戏AirPlaneWar

纷争开始了


开发环境

开发工具:eclipse2021-12
JDK版本:JDK15.0.1


前言

展示一下游戏画面

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


一、代码部分

1.项目结构及下载方法

如图:

在这里插入图片描述
链接:https://pan.baidu.com/s/1XGY_HIqsIIKUyP8CLRZsRw
提取码:whp5

2.代码

1.AirPlane.java

AirPlane.java:

package AirPlaneWar;

import java.awt.image.BufferedImage;

public class AirPlane extends FlyingObject implements Enemy{

	public static BufferedImage[] images;//定义小敌机图片集
	
	static {
		images=new BufferedImage[5];
		for(int i=0;i<images.length;i++) {
			images[i]=loadImage("/AirPlaneWar/images/airplane"+i+".png");
		}
	}
	
	private int speed;
	public AirPlane() {
		super(49, 36);//小敌机的宽度和高度
		speed=2;
	}

	@Override
	public int getScore() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public void step() {
		// TODO Auto-generated method stub
		y+=speed;
	}

	int deadIndex=1;//定义小敌机死了的下标
	/* 获得小敌机图片--爆炸效果 */
	public BufferedImage getImage() {
		if(isLife()) {
			return images[0];
		}else if(isDead()){
			BufferedImage img=images[deadIndex++];
			if(deadIndex==images.length) {///判断是否切换到最后一张图片
				state=REMOVE;//飞行物移除
			}
			return img;
		}
		return null;
	}

	public boolean outOfBounds() {
		return this.y>=ShootGame.jframeHeight;
	}

}

2.Award.java

Award.java:

package AirPlaneWar;

/**
 * 打中蜜蜂后的接口奖励
 * 定义双倍活力或者生命值的奖励类型为0或者1
 * -目的是为了随机产生数字0或者1来确定奖励类型
 * @author chenz
 *
 */
public interface Award {
	public int DOUBLE_FIRE=0;//定义双倍火力
	public int LIFE=1;//生命值
	
	public int getAward();//获取奖励类型的方法
}

3.Bee.java

Bee.java:

package AirPlaneWar;

import java.awt.image.BufferedImage;
import java.util.Random;

public class Bee extends FlyingObject implements Award{

	private static BufferedImage[] images;
	static {
		images=new BufferedImage[5];
		for(int i=0;i<images.length;i++) {
			images[i]=loadImage("/AirPlaneWar/images/bee"+i+".png");
		}
	}
	
	private int xSpeed;//x坐标增量
	private int ySpeed;//y坐标增量
	private int awardType;//奖励类型0或者1
	public Bee() {
		super(60, 50);
		xSpeed=1;
		ySpeed=1;
		
		Random rand=new Random();
		awardType=rand.nextInt(2);
	}

	@Override
	public int getAward() {
		return awardType;
	}

	@Override
	public void step() {
		x+=xSpeed;
		y+=ySpeed;
		if(x<=0||x>=ShootGame.jframeWidth) {
			xSpeed*=-1;//改变方向
		}
	}

	int deadIndex=1;
	@Override
	public BufferedImage getImage() {
		if(isLife()) {
			return images[0];
		}else if(isDead()){
			BufferedImage img=images[deadIndex++];
			if(deadIndex==images.length) {
				state=REMOVE;
			}
			return img;
		}
		return null;
	}

	@Override
	public boolean outOfBounds() {
		return this.y>ShootGame.jframeHeight;
	}

}

4.BigAirPlane.java

BigAirPlane.java:

package AirPlaneWar;

import java.awt.image.BufferedImage;

public class BigAirPlane extends FlyingObject implements Enemy{

	public static BufferedImage[] images;
	
	static {
		images=new BufferedImage[5];
		for(int i=0;i<images.length;i++) {
			images[i]=loadImage("/AirPlaneWar/images/bigplane"+i+".png");
		}
	}
	
	private int speed;
	public BigAirPlane() {
		super(69, 99);
		speed=3;
	}


	@Override
	public void step() {
		// TODO Auto-generated method stub
		y+=speed;
	}

	
	int deadIndex=1;
	@Override
	public BufferedImage getImage() {
		if(isLife()) {
			return images[0];
		}else if(isDead()) {
			BufferedImage img=images[deadIndex++];
			if(deadIndex==images.length) {
				state=REMOVE;
			}
			return img;
		}
		return null;
	}

	@Override
	public boolean outOfBounds() {
		return this.y>=ShootGame.jframeHeight;
	}

	@Override
	public int getScore() {
		// TODO Auto-generated method stub
		return 10;
	}

}

5.Bullet.java

Bullet.java:

package AirPlaneWar;

import java.awt.image.BufferedImage;

public class Bullet extends FlyingObject{

	public static BufferedImage image;
	
	static {
		image=loadImage("/AirPlaneWar/images/bullet.png");
	}
	
	/* 当前子弹的坐标增量 */
	private int speed=5;
	
	
	public Bullet(int x, int y) {
		super(8, 14, x, y);
	}

	@Override
	public BufferedImage getImage() {
		// TODO Auto-generated method stub
		if(isLife()) {
			return image;
		}else if(isDead()) {
			state=REMOVE;
		}
		return null;
	}

	/* 子弹移动函数 */
	@Override
	public void step() {
		// TODO Auto-generated method stub
		y-=speed;
	}

	@Override
	public boolean outOfBounds() {
		// TODO Auto-generated method stub
		return this.y<=-this.height;
	}

}

6.Enemy.java

Enemy.java:

package AirPlaneWar;
/**
 * 打中大小敌机以后的奖励
 */
public interface Enemy {
	/* 得分 */
	public int getScore();
	
}

7.FlyingObject.java

FlyingObject.java:

package AirPlaneWar;

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.management.RuntimeErrorException;

public abstract class FlyingObject {
	/* 定义飞行物的基本属性 */
	//飞行的状态
	public static final int LIFE=0;//活着
	public static final int DEAD=1;//死了
	public static final int REMOVE=2;//删除
	//定义当前飞行物的初始状态--活着
	public int state=LIFE;
	/* 定义飞行物的基本属性 */
	protected int width;//宽
	protected int height;//高
	protected int x;//x坐标
	protected int y;//y坐标
	
	/**
	 * 定义不同的构造方法
	 * 两种
	 * 1、英雄机、天空、子弹提供的
	 * 2.大小敌机、蜜蜂提供的
	 * @param filename
	 * @return
	 */

	//定义英雄机、天空、子弹提供的构造方法
	public FlyingObject(int width,int height,int x,int y) {
		this.width=width;//图片本身的宽度
		this.height=height;//图片本身的高度
		this.x=x;
		this.y=y;
	}
	/* 定义大小敌机、蜜蜂提供的构造方法 */
	public FlyingObject(int width,int height) {
		this.width=width;
		this.height=height;
		//初始化飞行物出现的范围
		Random ran=new Random();
		x=ran.nextInt(ShootGame.jframeWidth-this.width);
		y=-this.height;
	}
	
	/* 自定义方法-读取图片的方法 */
	public static BufferedImage loadImage(String filename) {
		BufferedImage imgBufferedImage;
		try {
			imgBufferedImage=ImageIO.read(FlyingObject.class.getResource(filename));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException();
		}
		return imgBufferedImage;
	}
	
	public abstract void step();
	public abstract BufferedImage getImage();
	public abstract boolean outOfBounds();
	
	public void paintObject(Graphics g) {
		g.drawImage(getImage(), x, y, null);
	}
	
	/* 碰撞算法:this-敌人 other:子弹或者英雄 */
	public boolean hit(FlyingObject other) {
		//计算X的最大最小边界
		int x1=this.x-other.width;
		int x2=this.x+this.width;
		
		//计算Y的最大最小边界
		int y1=this.y-other.height;
		int y2=this.y+this.height;
		
		//获取英雄机或者子弹的XY坐标
		int x=other.x;
		int y=other.y;
		
		return (x>=x1)&&(x<=x2)&&(y>=y1)&&(y<=y2);
		
	}
	
	
	/* 判断是否活着 */
	public boolean isLife() {
		return state==LIFE;
	}
	/*判断是否被删除*/
	public boolean isRemove() {
		return state==REMOVE;
	}
	/* 判断是否死了 */
	public boolean isDead() {
		return state==DEAD;
	}
	
	//飞行物去死
	public void goDead() {
		state=DEAD;//死了但是没有删除
	}
	
}

8.Hero.java

Hero.java:

package AirPlaneWar;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;

public class Hero extends FlyingObject{

	private static BufferedImage[] images;
	
	static {
		images=new BufferedImage[2];
		for(int i=0;i<images.length;i++) {
			images[i]=loadImage("/AirPlaneWar/images/hero"+i+".png");
		}
	}
	private int life;//定义生命值
	private int doubleFire;//定义双倍火力
	public Hero() {
		super(97,124,150,400);
		life=3;
		doubleFire=0;//初始为单倍活力
	}
	
	/* 英雄机随鼠标移动 */
	public void moveTo(int x,int y) {
		this.x=x-this.width/2;//减去自身宽度的一半
		this.y=y-this.height;
	}

	public Bullet[] shoot() {
		int xStep=this.width/4;//计算英雄机的1/4宽
		int yStep=20;//英雄机和子弹之间的距离
		if(doubleFire>0) {
			Bullet[] bs=new Bullet[3];
			bs[0]=new Bullet(this.x+xStep, this.y-yStep);
			bs[1]=new Bullet(this.x+2*xStep, this.y-yStep);
			bs[2]=new Bullet(this.x+3*xStep, this.y-yStep);
			
			//双倍子弹发射一定量以后自动变为单倍
			doubleFire-=2;
			return bs;
		}else {
			Bullet[] bs=new Bullet[1];
			bs[0]=new Bullet(this.x+2*xStep, this.y-yStep);
			return bs;
		}
		
	}
	
	public void paintObject(Graphics g) {
		g.drawImage(getImage(), x, y, null);
	}

	int deadIndex=0;
	public BufferedImage getImage() {
		// TODO Auto-generated method stub
		if(isLife()) {
			if(deadIndex==2) {
				deadIndex=0;
			}
			return images[deadIndex++%2];//循环刷新图片,再0与1来回选择,形成英雄机喷火的效果。
			
		}
		return null;
	}

	@Override
	public void step() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public boolean outOfBounds() {
		// TODO Auto-generated method stub
		return false;
	}
	
	/* 自定义方法--英雄机减少性命 */
	public void substractLife() {
		life--;
	}
	public void addLife() {//英雄机增加性命
		life++;
	}
	public int getLife() {
		return life;
	}
	public void addDoubleFire() {
		doubleFire+=40;
	}
	public void clearDoubleFire() {
		doubleFire=0;
	}
}

9.ShootGame.java

ShootGame.java:

package AirPlaneWar;

import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class ShootGame extends JPanel{

	/* 定义窗口的基本数据 */
	public static int width=Toolkit.getDefaultToolkit().getScreenSize().width;//获取屏幕的宽度
	public static int height=Toolkit.getDefaultToolkit().getScreenSize().height;//获取屏幕的高度
	
	public static int jframeWidth=400;//窗体的宽度
	public static int jframeHeight=700;//窗体的高度
	
	public static int jframeX=width/2-jframeWidth/2;//获取窗体居中的X坐标
	public static int jframeY=height/2-jframeHeight/2;//获取窗体居中的Y坐标
	/* 窗体、图片都是以坐上角的坐标为起点开始向右和向下扩展的 */
	
	/* 定义实体类 */
	private Sky sky=new Sky();//天空
	private Hero hero=new Hero();//英雄机
	private FlyingObject[] enemies= {};//敌人(大小敌机和蜜蜂)数组
	private Bullet[] bullets= {};//子弹数组
	
	/* 生成敌人核心算法 */
	public FlyingObject nextOne() {
		Random ran=new Random();//实例化随机数对象--随机产生敌人的类型(大、小敌机、蜜蜂)
		int type=ran.nextInt(20);//0-20内的随机数来生成对象
		if(type<4) {
			return new Bee();
		}else if(type<12) {
			return new AirPlane();//小敌机
		}else {
			return new BigAirPlane();//大敌机
		}
	}
	
	/**
	 * 设置游戏状态
	 * 启动、运行、暂停、结束
	 * 默认状态为启动
	 * @param args
	 */
	public static final int START=0;//启动
	public static final int RUNNING=1;//运行
	public static final int PAUSE=2;//暂停
	public static final int GAME_OVER=3;//结束
	private int state=START;//默认状态为启动
	
	/* 定义图片集 */
	public static BufferedImage start;//启动图
	public static BufferedImage pause;//暂停图
	public static BufferedImage gameover;//游戏结束图
	
	/* 加载图片 */
	static {
		start=FlyingObject.loadImage("/AirPlaneWar/images/start.png");//开始图片
		pause=FlyingObject.loadImage("/AirPlaneWar/images/pause.png");//暂停图片
		gameover=FlyingObject.loadImage("/AirPlaneWar/images/gameover.png");//结束图片
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		JFrame jf=new JFrame();//实例化窗口对象
		jf.setTitle("飞机大战==第3版");//设置标题
		jf.setBounds(jframeX, jframeY, jframeWidth, jframeHeight);//设置窗体位置以及窗体大小
		ShootGame sg=new ShootGame();//实例化当前类对象
		jf.add(sg);
		jf.setVisible(true);//窗体可见
		sg.action();//程序启动
		jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	int enterIndex=0;//敌人入场计数器
	public void enterAction() {
		enterIndex++;
		if(enterIndex%8==0) {
			FlyingObject obj=nextOne();//随机生成一个敌人
			enemies = Arrays.copyOf(enemies, enemies.length+1);//扩容
			enemies[enemies.length-1]=obj;//将敌人放在数组的最后
		}
	}
	
	int shootIndex=0;//子弹入场计数器
	public void shootAction() {
		shootIndex++;
		if(shootIndex % 10 ==0) {//每300ms走一次
			Bullet[] bs=hero.shoot();//获取子弹数组
			bullets=Arrays.copyOf(bullets, bullets.length+bs.length);//扩容
			//将英雄机发射的子弹数组存进子弹数组中
			System.arraycopy(bs, 0, bullets, bullets.length-bs.length, bs.length);
		}
	}
	
	/* 飞行物移动事件 */
	public void stepAction() {
		for(int i=0;i<bullets.length;i++) {//子弹移动事件
			bullets[i].step();
		}
		
		for(int i=0;i<enemies.length;i++) {
			enemies[i].step();
		}
		
	}
	public void outOfBoundsAction() {
		int index=0;
		FlyingObject[] enemiesLives=new FlyingObject[enemies.length];
		for(int i=0;i<enemies.length;i++) {
			FlyingObject fo=enemies[i];
			if(!fo.outOfBounds()) {
				enemiesLives[index++]=fo;
			}
		}
		enemies=Arrays.copyOf(enemiesLives, index);
		
		index=0;
		//获取每一个子弹
		//定义不越界子弹数组
		Bullet[] bulletsLives=new Bullet[bullets.length];
		for(int i=0;i<bullets.length;i++) {
			Bullet b=bullets[i];
			if(!b.outOfBounds()) {
				bulletsLives[index]=b;
				index++;
			}
		}
		bullets=Arrays.copyOf(bulletsLives, index);
	}
	
	
	
	public void action() {
		MouseAdapter l=new MouseAdapter() {
			
			public void mouseClicked(MouseEvent e) {
				// TODO Auto-generated method stub
				//根据不同的状态做出不同的结果
				switch(state) {
				case START:
					state=RUNNING;//开始-》运行
					break;
				case RUNNING:
					state=PAUSE;//运行->暂停
					break;
				case PAUSE:
					state=RUNNING;
					break;//暂停->运行
				case GAME_OVER:
					state=START;//结束->启动
					break;
				}
			}

			@Override
			public void mouseExited(MouseEvent e) {
				// TODO Auto-generated method stub
				if(state==RUNNING) 
					state=PAUSE;//运行->暂停
			}

			@Override
			public void mouseMoved(MouseEvent e) {//鼠标移动事件
				//判断当前状态是否为运行状态
				if(state==RUNNING) {
					int x=e.getX();//获取鼠标X轴位置
					int y=e.getY();
					hero.moveTo(x, y);//英雄机移动到鼠标位置
				}
			}

			@Override
			public void mouseEntered(MouseEvent e) {
				if(state==PAUSE)
					state=RUNNING;//暂停->运行
			}
			
		};
		
		this.addMouseListener(l);//添加鼠标监听事件
		this.addMouseMotionListener(l);//添加鼠标滑动事件
		
		Timer timer=new Timer();
		int intervel=10;//10ms
		timer.schedule(new TimerTask() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				if(state==RUNNING) {
					enterAction();//大小敌机和蜜蜂入场
					shootAction();//子弹入场
					stepAction();//飞行物移动
					outOfBoundsAction();//删除越界飞行物
					bulletBangAction();//
				}
				repaint();
			}
		},intervel,intervel);
	}

	int score=0;//定义玩家得分
	public void bulletBangAction() {
		for(int i=0;i<bullets.length;i++) {
			Bullet b=bullets[i];
			for(int j=0;j<enemies.length;j++) {
				FlyingObject f=enemies[j];//获取每一个敌人
				if(f.hit(b)&&f.isLife()&&b.isLife()) {
					f.goDead();
					b.goDead();
					if(f instanceof Enemy) {
						Enemy en=(Enemy)f;
						score+=en.getScore();
					}
					if(f instanceof Award) {
						Award aw=(Award)f;
						int type=aw.getAward();//根据奖励类型判断奖励项
						switch(type) {
						case Award.DOUBLE_FIRE:
							hero.addDoubleFire();
							break;
						case Award.LIFE:
							hero.addLife();
							break;
						}
					}
				}
			}
		}
	}

	public void paint(Graphics g){
//		g.drawImage(start, 0, 0, null);
		sky.paintObject(g);//绘制天空
		hero.paintObject(g);
		for(int i=0;i<enemies.length;i++) {//绘制敌人
			enemies[i].paintObject(g);
		}
		for(int i=0;i<bullets.length;i++) {
			bullets[i].paintObject(g);//绘制子弹
		}
		/* 绘制得分 */
		g.drawString("SCORE:"+score, 10, 25);
		/* 绘制生命值 */
		g.drawString("LIFE:"+hero.getLife(), 10, 45);
		/* 根据不同状态绘制不同图片 */
		switch(state) {
		case START:
			g.drawImage(start, 0,0, null);
			break;
		case PAUSE:
			g.drawImage(pause,0, 0, null);
			break;
		case GAME_OVER:
			g.drawImage(gameover, 0, 0, null);
			break;
		}
	}
}

10.Sky.java

Sky.java:

package AirPlaneWar;

import java.awt.Graphics;
import java.awt.image.BufferedImage;

public class Sky extends FlyingObject{

	public Sky() {
		super(ShootGame.jframeWidth, ShootGame.jframeHeight, 0, 0);
		// TODO Auto-generated constructor stub
	}

	public static BufferedImage image;//定义背景图片
	
	/* 静态代码块加载图片 */
	static {
		image=loadImage("/AirPlaneWar/images/background.png");
	}
	
	public BufferedImage getImage() {
		return image;
	}
	
	public void paintObject(Graphics g) {
		g.drawImage(getImage(), x, y, null);
	}

	@Override
	public void step() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public boolean outOfBounds() {
		// TODO Auto-generated method stub
		return false;
	}
}


总结

游戏主要是利用鼠标左键点击开始和暂停,飞机移动到边界以后也会暂停。
飞机一直跟随鼠标移动。
下载连接:
链接:https://pan.baidu.com/s/1XGY_HIqsIIKUyP8CLRZsRw
提取码:whp5

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值