飞机大战游戏是一款十分有趣的射击类小游戏,流畅的画面,高难度的挑战。游戏中,玩家驾驶英雄机,在空中进行战斗。点击并移动自己的英雄机,发射炮弹,打掉敌飞机以及蜜蜂,来获得分数和奖励,打掉一架敌飞机赢得5分,打掉一只蜜蜂赢得1条命或是获得20次双倍火力,如果撞上敌飞机或小蜜蜂,将减少命、双倍火力清零。每撞到一次蜜蜂或是敌飞机命减1,当命数为0时,则游戏结束。游戏界面如下图所示

Java飞机大战项目

下面就是教大家怎么用java来写出这个项目来。

数据建模:使用一个数据模型,描述对象的关系。使用绘图坐标系作为参考模型,英雄机、敌飞机、蜜蜂、子弹都是矩形区域。

Java飞机大战项目

类的设计

Java飞机大战项目

完整代码:

Airplane类的完整代码如下所示:

package com.itkzhan.shoot;

import java.util.Random;

/** 敌机*/
public class Airplane extends FlyingObject implements Enemy{
	private int speed=2;//走步的步数
	public Airplane(){
		image=ShootGame.airplane;
		width=image.getWidth();
		height=image.getHeight();
		Random rand=new Random();
		x=rand.nextInt(ShootGame.WIDTH-this.width);
		y=-height;//y坐标
	}
	public int getScore() {
		return 5;
	}
	public void step() {
		y+=speed;
	}
	public boolean outBounds() {
		
		return this.y>ShootGame.HEIGHT;
	}
	
}

Award类的完整代码如下所示:

package com.itkzhan.shoot;
/** 奖励*/
public interface Award {
	int DOUBLE_FIRE=0;//双倍火力值
	int LIFE=1;//命
	int getType();//得奖励类型(0或1)
}

Bee类的完整代码如下所示:

package com.itkzhan.shoot;

import java.util.Random;

/** 蜜蜂*/
public class Bee extends FlyingObject implements Award{
	private int xSpeed=1;//x坐标走步步数
	private int ySpeed=2;//y坐标走步步数
	private int awardType;//奖励类型
	/** Bee构造方法*/
	public Bee(){
		image=ShootGame.bee;//图片
		width=image.getWidth();//图片的宽
		height=image.getHeight();//图片的高
		Random rand=new Random();
		x=rand.nextInt(ShootGame.WIDTH-this.width);
		y=-this.height;
		awardType=rand.nextInt(2);
	}
	public int getType() {//奖励类型
		return awardType;
	}
	public void step() {
		x+=xSpeed;
		y+=ySpeed;
		if(this.x>=ShootGame.WIDTH-this.width){
			xSpeed=-1;
		}
		if(x<=0){
			xSpeed=1;
		}
	}
	public boolean outBounds() {
		return this.y>ShootGame.HEIGHT;
	}

}

Bullet类的完整代码如下所示:

package com.itkzhan.shoot;
/** 子弹*/
public class Bullet extends FlyingObject{
	private int speed=3;//走步的步数
	/** Bullet构造方法*/
	public Bullet(int x,int y){
		image=ShootGame.bullet;
		width=image.getWidth();
		height=image.getHeight();
		this.x=x;//x坐标
		this.y=y;//y坐标
	}
	public void step() {
		y-=speed;
		
	}
	public boolean outBounds() {
		return this.y<-height;
	}
}

Enemy类的完整代码如下所示:

package com.itkzhan.shoot;

public interface Enemy {
	int getScore();
}

FlyingObject类的完整代码如下所示:

package com.itkzhan.shoot;

import java.awt.image.BufferedImage;

/**
 * 飞行物
 * @author HP
 *
 */
public abstract class FlyingObject {
	protected int x;
	protected int y;
	protected int width;
	protected int height;
	protected BufferedImage image;
	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 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 BufferedImage getImage() {
		return image;
	}
	public void setImage(BufferedImage image) {
		this.image = image;
	}
	public abstract void step();
	//敌人被子弹打
	public  boolean shootBy(Bullet bullet){
		int x=bullet.x;//子弹的x
		int y=bullet.y;//子弹的y
		return x>this.x&&x<this.x+this.width
		&&
		y>this.y&&y<this.y+this.height;
	};
	public abstract boolean outBounds();
}

Hero类的完整代码如下所示:

package com.itkzhan.shoot;

import java.awt.image.BufferedImage;

/** 英雄机:是飞行物*/
public class Hero extends FlyingObject{
	private int life;//命
	private int doubleFire;//火力值
	private BufferedImage[] images;//图片
	private int index;//图片切换的频率
	/** Hero构造方法*/
	public Hero(){
		image=ShootGame.hero0;//图片
		width=image.getWidth();//宽
		height=image.getHeight();//高
		x=150;//固定150
		y=400;//固定的400
		life=3;//命值为3
		doubleFire=0;//火力值为0,单倍火力
		images=new BufferedImage[]{ShootGame.hero0,ShootGame.hero1};
		index=0;
	}
	public void step() {
		index++;
		int a=index/10;//每100m b=0,1
		int b=a%2;
		image=images[b];
		image=images[b];
	}
	/** 发射子弹*/
	public Bullet[] shoot(){
		int xStep=this.width/4;//1/4英雄机的宽度
		int yStep=20;//子弹离飞机的距离
		if(doubleFire>0){//双倍火力
			Bullet[] bullets=new Bullet[2];
			bullets[0]=new Bullet(this.x+xStep,this.y-yStep);
			bullets[1]=new Bullet(this.x+3*xStep,this.y-yStep);
			doubleFire-=-2;
			return bullets;
		}else{//单倍火力
			Bullet[] bullets=new Bullet[1];
			bullets[0]=new Bullet(this.x+2*xStep,this.y-yStep);
			return bullets;
		}
	}
	/** 英雄机随着鼠标移动x:鼠标的x坐标 y鼠标的y坐标*/
	public void moveTo(int x,int y){
		this.x=x-this.width/2;
		this.y=y-this.height/2;
	}
	
	/**获取命*/
	public int getLife(){
		return life;
	}
	/** 减命*/
	public void subtractLife(){
		life--;
	}
	
	public void addLife(){
		life++;
	}
	/** 增火力值*/
	public void addDoubleFire(){
		doubleFire+=40;
	}
	/** 设置火力值*/
	public void setDoubleFire(int doubleFire){
		this.doubleFire=doubleFire;
	}
	@Override
	public boolean outBounds() {
		return false;//永不越界
	}
	public boolean hit(FlyingObject other){
		int x1=other.x-this.width/2;
		int x2=other.x+other.width+this.width/2;
		int y1=other.y-this.height/2;
		int y2=other.y+other.height/2;
		int hx=this.x+this.width/2;// 
		int hy=this.y+this.height/2;
		return hx>x1 && hx<x2
		       &&
		       hy>y1 && hy<y2;
	}

}

ShootGame类的完整代码如下所示:

package com.itkzhan.shoot;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ShootGame extends JPanel{//面板
	public static final int WIDTH=400;
	public static final int HEIGHT=654;
	public static BufferedImage background;
	public static BufferedImage start;
	public static BufferedImage airplane;
	public static BufferedImage bee;
	public static BufferedImage bullet;
	public static BufferedImage hero0;
	public static BufferedImage hero1;
	public static BufferedImage pause;
	public static BufferedImage gameover;
	
	public Hero hero=new Hero();//英雄机对象
	private FlyingObject[] flyings={};//敌人数组(敌机+蜜蜂)
	private Bullet[] bullets={};//子弹数组
	
	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=0; //存储当前状态
	
	static { // 静态代码块,初始化图片资源
		try {
			background = ImageIO.read(ShootGame.class
					.getResource("background.png"));
			start = ImageIO.read(ShootGame.class.getResource("start.png"));
			airplane = ImageIO
					.read(ShootGame.class.getResource("airplane.png"));
			bee = ImageIO.read(ShootGame.class.getResource("bee.png"));
			bullet = ImageIO.read(ShootGame.class.getResource("bullet.png"));
			hero0 = ImageIO.read(ShootGame.class.getResource("hero0.png"));
			hero1 = ImageIO.read(ShootGame.class.getResource("hero1.png"));
			pause = ImageIO.read(ShootGame.class.getResource("pause.png"));
			gameover = ImageIO
					.read(ShootGame.class.getResource("gameover.png"));
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
		/** 随机生成敌人对象(敌机、小蜜蜂)*/
		public static FlyingObject nextOne(){
			Random rand=new Random();
			int type=rand.nextInt(20);//生成[0,20)随机数
			if(type==0){
				return new Bee();//若为0则返回蜜蜂对象
			}else{
				return new Airplane();//1到19则返回敌机对象
			}
			
		}
		private Timer timer;//声明定时器对象
		private int intervel=10;//定时器的时间间隔(以毫秒为单位)
		int flyEnteredIndex=0;//敌人入场计数
		/** 敌人入场(敌机、小蜜蜂)*/
        public void enterAction(){//10毫秒走一次
        	flyEnteredIndex++;
        	if(flyEnteredIndex%40==0){//每400毫秒走一次
        		FlyingObject o=nextOne();
        		flyings=Arrays.copyOf(flyings, flyings.length+1);//扩容
        		flyings[flyings.length-1]=o;//将对象加入到数组中
        	}
			
		}
        /** 飞行物走一步*/
        public void stepAction(){
        	hero.step();
        	for(FlyingObject f:flyings){
        		f.step();
        	}
        	for(Bullet b:bullets){
        		b.step();
        	}
        }
        int shootIndex=0;//子弹发射计数
        /** 英雄机发射子弹--子弹入场*/
        public void shootAction(){
        	shootIndex++;
        	if(shootIndex%30==0){
        		Bullet[] bs=hero.shoot();
        		bullets=Arrays.copyOf(bullets, bullets.length+bs.length);
        		System.arraycopy(bs,0,bullets, bullets.length-bs.length,bs.length);
        	}
        }
        int score=0;
		/**所有子弹与所有敌人的碰撞 */
        public void bangAction(){
        	for(Bullet b:bullets){
        		bang(b);//
        	}
        }
        /** 一发子弹和所有敌人的碰撞*/
        public void bang(Bullet bullet){
        	int index=-1;
        	for(int i=0;i<flyings.length;i++){
        		FlyingObject obj=flyings[i];
        		if(obj.shootBy(bullet)){
        			index=i;
        			break;
        		}
        	}
        	if(index!=-1){//被撞上了
        		FlyingObject one=flyings[index];
        		if(one instanceof Enemy){//敌机
        			Enemy e=(Enemy)one;
        			score+=e.getScore();
        		}
        		if(one instanceof Award){//奖励
        			Award a=(Award)one;
        			int type=a.getType();
        			switch (type) {
					case Award.DOUBLE_FIRE:
						hero.addDoubleFire();
						break;
					case Award.LIFE:
						hero.addLife();
						break;
					}
        		}
        		FlyingObject t=flyings[index];
        		flyings[index]=flyings[flyings.length-1];
        		flyings[flyings.length-1]=t;
        		flyings=Arrays.copyOf(flyings, flyings.length-1);//缩容
        	}
        }
        
        public void outOfBoundsAction(){
        	//越界飞行物
        	FlyingObject[] flyingLives=new FlyingObject[flyings.length];//活着的
        	int index=0;
        	for(int i=0;i<flyings.length;i++){
        		FlyingObject obj=flyings[i];
        		if(!obj.outBounds()){//不越界
        			flyingLives[index]=obj;//存储在flyingLives
        			index++;
        		}
        	}
        	flyings=Arrays.copyOf(flyingLives, index);
        	index=0;
        	Bullet[] bulletLives=new Bullet[bullets.length];
        	for(int i=0;i<bullets.length;i++){
        		Bullet b=bullets[i];
        		if(!b.outBounds()){
        			bulletLives[index]=b;
        			index++;
        		}
        	}
        	bullets=Arrays.copyOf(bulletLives, index);
        }
        /** 检查游戏结束*/
        public void checkGameOverAction(){
        	if(isGameOver()){//若游戏结束
        		state=GAME_OVER; 
        	}
        }
        /** 判断游戏是否结束*/
        public boolean isGameOver(){
        	for(int i=0;i<flyings.length;i++){
        		int index=-1;
        		FlyingObject f=flyings[i]; 
        		if(hero.hit(f)){
        			hero.subtractLife();
        			hero.setDoubleFire(0);
        			index=i;
        		}
        		if(index!=-1){
        			//将被撞的敌人删除
        			FlyingObject t=flyings[index];
        			flyings[index]=flyings[flyings.length-1];
        			flyings[flyings.length-1]=t;
        			flyings=Arrays.copyOf(flyings, flyings.length-1);
        		}
        	}
        	return hero.getLife()<=0;
        }
        
		/** 主程序流程控制*/
		public void action(){
			//鼠标操作事件
			MouseAdapter l=new MouseAdapter() {
				/** 鼠标移动事件*/
				public void mouseMoved(MouseEvent e) {
					if(state==RUNNING){
					int x=e.getX();//获取鼠标的x坐标
					int y=e.getY();//获取鼠标的y坐标
					hero.moveTo(x, y);//英雄机随鼠标移动
					}
				}
				public void mouseClicked(MouseEvent e) {//鼠标点击事件
					switch (state) {//判断当前状态
					case START:
						state=RUNNING;
						break;
					case GAME_OVER:
						flyings = new FlyingObject[0]; // 清空飞行物
						bullets = new Bullet[0]; // 清空子弹
						hero = new Hero(); // 重新创建英雄机
						score = 0; // 清空成绩
						state = START; // 状态设置为启动
					
					}
				}
				public void mouseExited(MouseEvent e) {//鼠标移开事件
					if(state==RUNNING){
						state=PAUSE;
					}
				}
				public void mouseEntered(MouseEvent e) {//移入事件
					if(state==PAUSE){
						state=RUNNING;
					}
				}
			};
			
			this.addMouseListener(l);//处理鼠标一般操作
			this.addMouseMotionListener(l);//处理鼠标滑动
			timer=new Timer();//创建定时器对象
			timer.schedule(new TimerTask(){
				public void run() {
					if(state==RUNNING){
					enterAction();//敌人入场
					stepAction();//飞行物走一步
					shootAction();//英雄机发子弹
					bangAction();//子弹和敌人的碰撞
					outOfBoundsAction();//删除出界对象
					checkGameOverAction();//检查游戏结束  
					}
					repaint();
				}}, intervel,intervel);//第一个intervel:程序启动到第一次干事的间隔
										//第二个intervel:每次干事的间隔
		}
		
		//g:画笔
		public void paint(Graphics g) {
			g.drawImage(background,0,0,null);//第四个参数不需要管,跟程序无关
			paintHero(g);
			paintFlyingObjects(g);
			paintBullets(g);
			paintScore(g);
			paintState(g);//画状态
		}
		//画子弹
	private void paintBullets(Graphics g) {
			for(Bullet b:bullets){
				g.drawImage(b.image,b.x,b.y,null);
			}
			
		}
	//画敌人
	private void paintFlyingObjects(Graphics g) {
			for(FlyingObject f:flyings){
				g.drawImage(f.image,f.x,f.y,null);
			}
			
		}
	//画英雄机
	private void paintHero(Graphics g) {
			g.drawImage(hero.image,hero.x,hero.y,null);
			
		}
	//画分和画命
	private void paintScore(Graphics g){
		g.setColor(new Color(0xFF0000));//设置颜色--红色
		g.setFont(new Font(Font.SANS_SERIF,Font.BOLD,20));//字体,加粗,字号
		g.drawString("SCORE: "+score, 10, 25);
		g.drawString("LIFE: "+hero.getLife(), 10, 45);
	}
	//画状态
	public void paintState(Graphics g){
		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;
		}
	}
	public static void main(String[] args) {
		JFrame frame=new JFrame("Fly");
		ShootGame game=new ShootGame();
		frame.add(game);//将面板添加到窗口中
		frame.setSize(WIDTH,HEIGHT);
		frame.setAlwaysOnTop(true);//总是居顶
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置默认关闭操作
		frame.setLocationRelativeTo(null);//设置位置相对与,默认相对位置就是中间点
		frame.setVisible(true);//1.设置窗口可见 2.尽快调用paint()方法
		game.action();//启动执行
	}

}

具体每一步的详细开发说明以及项目中用到的图片资源,请移步到http://www.itkzhan.com/portal/course/detail/id/8.html查看

 

相关文章: