java飞机大战

游戏实现的功能:玩家通过鼠标操作飞机,飞机自动发射子弹,系统随机生成敌机,并且检测子弹是否与敌机相碰,英雄机是否与敌机相碰;英雄机是否死亡;系统随时更新分数,游戏结束时,提醒点击屏幕开始游戏

用到的知识点:
java swing
多线程
集合

java飞机大战编程思路:
编写游戏面板和窗体----------编写App工具类,用来读取照片-----------在面板中添加背景图---------
面板使用画图方法,画出图片------------------------------
编写FlyObject类,里面的成员变量代表的图片、宽度、高度、纵坐标、横坐标---------------

英雄机的创建与移动:
编写英雄机类继承FlyObject类,设置英雄机的初始位置和大小,血量--------------------
在面板中使用画图方法,画出英雄机,从而在面板中显示英雄机-------------------------
自定义moveToMouse方法,让英雄机跟着鼠标移动--------------窗体中添加鼠标监听器,并让英雄机注册监听器-------------
英雄机调用moveToMouse方法,实现英雄机随着鼠标移动的功能

敌机的创建与移动:
编写敌机类继承FlyObject类,设置敌机的大小,初始血量----------------------------
统一设置敌机的纵坐标为-h,横坐标通过rd.nextInt(1024-w)方法决定,从而让敌机随机出现---------------------------------
为不同的敌机设置不同的速度,使它们的下落速度不同
在面板中利用集合创建敌机的大本营,即:List<Ep>eps = new ArrayList<Ep>();-----------
在面板中使用画图方法,遍历整个大本营,画出敌机,显示敌机-----------------------------------

子弹与敌机相碰,英雄机与敌机相碰:
编写子弹类继承FlyObject类,设置子弹的大小-------------------
在面板中利用集合创建火药库,即:List<Fire>fs = new ArrayList<Fire>();
在构造方法中设置子弹与英雄机的坐标相同---------------
自定义move方法,固定子弹移动的速度、方向------------------在面板中使用画图方法,画出子弹,在面板中显示子弹----
设置初始发射一颗子弹,逐渐增加子弹,直到三颗子弹,并且每颗子弹移动的速度不同-------------------------------------
进行子弹与敌机的碰撞检测,碰撞检测公式为 boolean hit = (x<=f.x+f.w) && (x>=f.x-w)&& (y<=f.y+f.h) && (y>=f.y-h);
判断子弹是否与敌机相碰,若相碰,调用remove()方法,移除子弹,并且如果敌机的血量<=0,移除敌机----------------
利用类似的方法判断敌机是否与英雄机相碰,若相碰,移除敌机,并且英雄机的血量-1,当英雄机的血量<=0时,游戏结束

开始游戏:
设置初始分数为0,每击倒一个敌机,分数+10
设置布尔类型的变量gameover为false,作为游戏的开关,当gameover为true时,游戏结束
利用单线程,固定格式为public void action(){new Thread(){}.start();},在里面while循环,运行游戏
当英雄机死亡时,提示“游戏结束,点击屏幕重新开始”,调用mouseCliked(Event e)方法,监听鼠标点击,若鼠标点击,重新开始游戏
并且重新开始游戏时,随机更换背景



代码实现:

import java.awt.*;
import javax.swing.*;
import javax.imageio.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.*;
//处理图片的工具类
public class App{
	//读取指定位置上的图片
	public static BufferedImage getImg(String path){
		try{
			BufferedImage img = ImageIO.read(App.class.getResource(path));
			return img;
		}
		catch(IOException e){
			e.printStackTrace();
		}

		return null;
	}
}
import java.awt.image.*;
import java.util.Random;
import java.util.List;
import java.awt.*;
public class Ep extends FlyObject{
	int speed;
	int hp = 3;
	int type;
	public Ep(){
		Random rd = new Random();
		int index = rd.nextInt(12)+1;
		type = index;//道具机
		img = App.getImg("/Img/ep"+index+".PNG");
		w = img.getWidth();
		h = img.getHeight();
		x = rd.nextInt(1024-w);
		y = -h;
		speed = 13 - index;
	}
	public void move(){
		if(type==5){
			y += speed/2;
			x += 2;
		}
		else if(type==6){
			y += speed/2;
			x -= 2;
		}
		else{
			y += speed;
		}
	}
	public boolean shootBy(Fire f){
		boolean hit = (x<=f.x+f.w) && (x>=f.x-w)
			&& (y<=f.y+f.h) && (y>=f.y-h);
		return hit;
	}
	public boolean hitBy(Hero hero){
		boolean hit = (x<=hero.x+hero.w) && (x>=hero.x-w)
			&& (y<=hero.y+hero.h) && (y>=hero.y-h);
		return hit;
	}
}
public class Fire extends FlyObject{
	int dir;//子弹移动的方向
	//dir=0		左上角
	//dir=1		垂直上飞
	//dir=2		右上角
	public Fire(int hx, int hy, int dir){
		img = App.getImg("/img/fire.PNG");
		w = img.getWidth();
		h = img.getHeight();
		//确定子弹的位置
		x = hx;
		y = hy;
		this.dir = dir;
	}
	public void move(){
		if(dir==0){
			y -= 10;
			x -= 1;
		}
		else if(dir==1){
			y -= 10;
		}
		else if(dir==2){
			y -= 10;
			x += 1;
		}
	}
}

 

import java.awt.image.*;
//在开发中,将相同的特点抽离出来形成父类,从而提高代码的复用性
public class FlyObject{
	BufferedImage img;
	int x;//横坐标
	int y;//纵坐标
	int w;//宽度
	int h;//高度
}
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.*;
public class GameFrame extends JFrame{
	public GameFrame(){
		setTitle("飞机大战");
		setSize(1024, 768);//宽1024, 高768
		//默认界面居中显示
		setLocationRelativeTo(null);
		//不允许玩家改变页面大小
		setResizable(false);
		//设置默认的关闭选项
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	public static void main(String args[]){
		GameFrame frame = new GameFrame();
		GamePanel panel = new GamePanel(frame);
		panel.action();
		frame.add(panel);//将面板添加到窗体中
		frame.setVisible(true);

	}
}
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Random;
public class GamePanel extends JPanel{
	BufferedImage bg;//背景图
	Hero hero = new Hero();
	//Ep ep = new Ep();
	List<Ep> eps = new ArrayList<Ep>();
	List<Fire> fs = new ArrayList<Fire>();
	//定义分数
	int score = 0;
	boolean gameover = false;
	int power = 1;//英雄机的火力
	public void action(){
		//创建并启动一个线程,控制游戏场景中物体活动
		new Thread(){
			public void run(){
				//写一个死循环
				while(true){
					if(!gameover){
						epEnter();
						epMove();
						shoot();
						fireMove();
						shootEp();
						hit();
						try{
							Thread.sleep(10);
						}catch(InterruptedException e){
							e.printStackTrace();
						}
						repaint();
					}		
				}
			}
		}.start();
	}
	
	protected void hit(){
		for(int i=0;i<eps.size();i++){
			Ep e = eps.get(i);
			if(e.hitBy(hero)){
				eps.remove(e);
				hero.hp--;
				score += 10;
				power = 1;
				if(hero.hp<=0){
					gameover = true;
				}
			}
		}
	}
	protected void shootEp(){
		//遍历所有的子弹
		for(int i=0;i<fs.size();i++){
			Fire f = fs.get(i);
			bang(f);
		}
	}
	//判断子弹是否击中敌机
	private void bang(Fire f){
		//遍历所有的敌机
		for(int i=0;i<eps.size();i++){
			Ep e = eps.get(i);
			//判断子弹是否击中敌机
			if(e.shootBy(f)){
				e.hp--;
				if(e.hp<=0){
					if(e.type==8){
						power++;
						if(power > 3){
							hero.hp++;
							power = 3;
							if(hero.hp > 3){
								hero.hp = 3;
							}
						}
					}
					eps.remove(e);
					score += 10;
				}
				fs.remove(f);
			}
		}
	}
	protected void fireMove(){
		for(int i=0;i<fs.size();i++){
			Fire fire = fs.get(i);
			fire.move();
		}
	}
	int index1 = 0;
	protected void shoot(){
		index1 ++;
		if(index1>=20){
			if(power == 1){
				Fire fire2 = new Fire(hero.x-20, hero.y-20, 1);
				fs.add(fire2);
			}else if(power == 2){
				Fire fire1 = new Fire(hero.x-50, hero.y, 0);
				fs.add(fire1);
				Fire fire2 = new Fire(hero.x-20, hero.y-20, 1);
				fs.add(fire2);
			}else{
				Fire fire1 = new Fire(hero.x-50, hero.y, 0);
				fs.add(fire1);
				Fire fire2 = new Fire(hero.x-20, hero.y-20, 1);
				fs.add(fire2);
				Fire fire3 = new Fire(hero.x+10, hero.y, 2);
				fs.add(fire3);
			}
			index1 = 0;	
		}
	}
	protected void epMove(){
		for(int i=0;i<eps.size();i++){
			Ep e = eps.get(i);
			e.move();
		}
	}
	int index = 0;
	protected void epEnter(){
		index ++;
		if(index>=20){
			Ep e = new Ep();
			eps.add(e);
			index = 0;
		}
	}

	public GamePanel(GameFrame frame){
		//设置背景
		setBackground(Color.green);
		//初始化图片
		bg = App.getImg("/Img/start.BMP");
		//添加鼠标适配器
		MouseAdapter adapter = new MouseAdapter(){
			public void mouseClicked(MouseEvent e){
				if(gameover){
					//重新开始游戏
					hero = new Hero();
					gameover = false;
					score = 0;
					eps.clear();
					fs.clear();
					//随机背景图
					Random rd = new Random();
					int index = rd.nextInt(6)+1;
					bg = App.getImg("/img/bg"+index+".BMP");
					power = 1;
					action();
				}
			}
			public void mouseMoved(MouseEvent e){
				int mx = e.getX();
				int my = e.getY();
				if(!gameover){
					hero.moveToMouse(mx, my);
					//刷新界面
					repaint();
				}
			}
		};
		//将适配器加入到监听器(固定格式)
		addMouseListener(adapter);
		addMouseMotionListener(adapter);
		
		//使用键盘监听器(固定格式)
		KeyAdapter kd = new KeyAdapter(){
			public void keyPressed(KeyEvent e){
				int keyCode = e.getKeyCode();
				if(!gameover){
					if(keyCode == KeyEvent.VK_UP){
						hero.moveUP();
					}else if(keyCode == KeyEvent.VK_DOWN){
						hero.moveDOWN();
					}else if(keyCode == KeyEvent.VK_LEFT){
						hero.moveLEFT();
					}else if(keyCode == KeyEvent.VK_RIGHT){
						hero.moveRIGHT();
					}
					repaint();
				}
			}
		};
		//将适配器加到窗体监听器中
		frame.addKeyListener(kd);
	}

	//专用画图方法
	//Graphics g 画笔
	public void paint(Graphics g){
		super.paint(g);
		//画图片 g.drawImage(图片,横坐标,纵坐标,null)
		g.drawImage(bg, 0, 0, 1024, 768, null);
		g.drawImage(hero.img, hero.x, hero.y, hero.w, hero.h, null);
		for(int i=0;i<eps.size();i++){
			Ep ep = eps.get(i);
			g.drawImage(ep.img, ep.x, ep.y, ep.w, ep.h, null);
		}
		for(int i=0;i<fs.size();i++){
			Fire fire = fs.get(i);
			g.drawImage(fire.img, fire.x, fire.y, fire.w, fire.h, null);
		}
		g.setColor(Color.white);
		g.setFont(new Font("楷体", Font.BOLD, 20));
		g.drawString("分数:"+score, 10, 30);
		//画英雄机的血量
		for(int i=0;i<hero.hp;i++){
			g.drawImage(hero.img, 350+i*35, 5, 30, 30, null);
		}
		//游戏结束
		if(gameover == true){
			g.setColor(Color.black);
			g.setFont(new Font("楷体", Font.BOLD, 35));
			g.drawString("GAMEOVER! 菜鸡!鸡你太美", 20, 300);
			g.setColor(Color.red);
			g.setFont(new Font("楷体", Font.BOLD, 35));
			g.drawString("点击屏幕重新开始游戏,沙雕", 40, 350);	
		}
	}
}
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.*;
public class Hero extends FlyObject{
	int hp;
	public Hero(){
		img = App.getImg("/Img/me3.PNG");
		x = 500; y = 500;
		w = img.getWidth();
		h = img.getHeight();
		hp = 3;//英雄机有三条生命
	}
	public void moveToMouse(int mx, int my){
		x = mx-w/2;
		y = my-h/2;
	}
	public void moveUP(){
		y = y - 10;
	}
	public void moveDOWN(){
		y = y + 10;
	}
	public void moveLEFT(){
		x = x - 10;
	}
	public void moveRIGHT(){
		x = x + 10;
	}
}

 

上一篇:查找单链表倒数第k个节点(算法入门)


下一篇:extra 额外附加