java飞机大战的简单实现

简介

经过一段时间的学习,掌握了基本的多线程、双缓冲等知识要点,通过这些知识点简单实现一个项目,即飞机大战。

需要知道的概念

线程与进程

1、程序
是一份存在存储里的文件,固定的文件包含 (代码,素材,配置文件…)

2、进程
一个程序从载入内存,程序启动、运行、结束的整个过程。

3、线程
可简单理解为进程 > 线程,如CPU双核四线程、六核六线程。
一般来说,一个进程,可以有多个线程。

进程:游戏 - 王者荣耀
包括代码、图片素材等
运行时图片需要在屏幕上绘制出来,数据的变化

4、Java如何实现线程
(1)Thread 类

1.继承Thread 类
2.重写run方法
3.使用线程 -启动方法 - start

(2)Runnable 接口

1.实现Runnable接口
2.重写run方法
3.在构造方法中,实例化Thread类的对象(包含了实现了Runnable接口的类的对象)
4.使用Thread类的对象启动,通过start方法。

双缓冲

作用:防止绘制时图像卡顿

原来绘制JFrame,得到一个Graphcis对象来绘制时:
一个一个来绘制

1.背景 – 全尺寸的图片,整个JFrame
2.画球 – 根据球的坐标改变这个球大小范围内的像素

双缓冲绘图:
一次绘制

1.先找个地方,把下一帧要显示的东西都画好变成一张图,
2.再把这张图整个绘制一遍

项目的基本架构

1.一个Ball类,一个球=一个对象,可用此作为飞船和子弹的基本类(球的数据(坐标、大小、颜色、速度),球的方法(绘制、移动),球的不同(插入不同的飞机,子弹图片))

2.一个界面类

3.一个监听器类

4.通过Ball类构建一个飞船生成类和一个子弹生成类

Ball类的代码实现

package NewBallV2;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;


public class Ball {

	//球的属性 
	int x,y,size,speedx,speedy;
	int width,height;
	Color color;
	int r;
	ArrayList<Ball> balls;
	ArrayList<Plane> ships;
	BufferedImage img;
	
	//飞船和子弹的构造函数
	public Ball(ArrayList<Ball> balls,int x,int y,int speedx,int speedy,BufferedImage img){
		this.balls=balls;
		this.x=x;
		this.y=y;
		this.speedx=speedx;
		this.speedy=speedy;
		this.img=img;
		this.height=img.getHeight(null);
        this.width=img.getWidth(null);
	}
	
	//另一种构造函数,用于己方飞船
	public Ball(ArrayList<Plane> ships,int x,int y,BufferedImage img){
		this.ships=ships;
		this.x=x;
		this.y=y;
		this.img=img;
		this.height=img.getHeight(null);
        this.width=img.getWidth(null);
	}
	
	// 画飞船和子弹的函数
	public void drawball(Graphics g) throws IOException{
		img.getGraphics();
		g.drawImage(img, x, y, null);
	}
	
	public void drawSelf(Graphics g){
		//用于之后扩展的Plane类继承
	}
	
	// 画小球
	public void drawBall(Graphics g) {
		
		g.fillOval(x, y, size, size); 
		g.setColor(color);
	}
	// 移动小球 改变小球的坐标 
	public void moveBall() {
		if(x>1800||x<0||y>1000||y<0) {
			speedx=-speedx;
			speedy=-speedy;
		}
			x+=speedx;
			y+=speedy;
	}
	
	public void collision(ArrayList<Ball> balls){
		
		for(int i=0;i<balls.size();++i){
			Ball ball = balls.get(i);//获取小球对象
			if(ball != this){
				//判断两个小球是否碰撞
				if((ball.x - x) * (ball.x - x) + (ball.y - y) * (ball.y - y) < (ball.r + r)
						* (ball.r + r)){
					//交换移动速度
					int tempX = ball.speedx;
					ball.speedx = speedx;
					speedx = tempX;
					int tempY = ball.speedy;
					ball.speedy = speedy;
					speedy = tempY;
				}
			}
		}
	}
	
	// paint 整体擦除背景  
	public void cleanBall(Graphics g) {
		g.setColor(new Color(238,238,238));
		g.fillOval(x-size, y-size, size, size); 
		
	}
		
}

界面类的代码实现

package NewBallV2;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JFrame;


public class BallFrame extends JFrame implements Runnable{
	ArrayList<Ball> balls = new ArrayList<Ball>();  //敌方飞船队列
	ArrayList<Plane> ships = new ArrayList<Plane>();  //己方飞船队列
	ArrayList<Ball> bullets=new ArrayList<Ball>();	//敌方子弹队列
	ArrayList<Ball> bullets1=new ArrayList<Ball>();	//己方子弹队列
	Boolean game=true; //游戏开始按钮
	KeyEvent e;

	// 初始化界面
	public void initUI() {

		this.setTitle("Ball");
		this.setSize(1800, 1000);
		this.setResizable(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		
		// 注册鼠标监听器 
		BallListen ballListen = new BallListen(this,balls,bullets1,ships,game);
		this.addMouseListener(ballListen);
		this.addKeyListener(ballListen);
		
		this.setVisible(true);
		ballListen.g=this.getGraphics();
		
		// 生成飞船和子弹
		BallAI ballAI = new BallAI(balls,bullets,ships);
		ballAI.start();
		
	}

	@Override
	public void paint(Graphics bg) {
		// 休眠                                                                                     
		try {                                                                                     
			Thread.sleep(100);                                                                    
		} catch (InterruptedException e) {                                                        
			// TODO Auto-generated catch block                                                    
			e.printStackTrace();                                                                  
		}                                                                                         
		// 需要绘制的对象 都通缓冲画布来绘制到缓冲图片上                                                                
//		bg.setColor(Color.BLUE);                                                                   
//		bg.fillRect(0, 0, this.getWidth(), this.getHeight()); 
		//使用绝对路径
		ImageIcon icon = new ImageIcon("F:\\Java\\学习\\线程飞机大战\\飞机大战\\background\\back.jpg");
		//获取图片
		Image bjImg = icon.getImage();
		//每次重画一次图片,避免飞机出现残影
		bg.drawImage(bjImg,0,0,this.getWidth(),this.getHeight(),null);
		for (int i = 0; i < balls.size(); i++) {
			//绘制己方飞机
			if (i==0){
				ships.get(i).drawSelf(bg);
				ships.get(i).moveBall();
				//ships.get(i).addDirection(e);
			}
			//绘制敌方飞机
			if (balls.get(i) != null) {
				try {
					balls.get(i).drawball(bg);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				balls.get(i).moveBall();
				if(balls.get(i).y>1000||balls.get(i).x>1800||balls.get(i).x<0) {
					balls.remove(i);
				}
			}
		}
		//绘制敌方子弹
		for (int i = 0; i < bullets.size(); i++) {
			if (bullets.get(i) != null) {
				try {
					bullets.get(i).drawball(bg);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				bullets.get(i).moveBall();
				if(bullets.get(i).y>1000) {
					bullets.remove(i);
				}
			}
		}
		//绘制己方子弹
		for (int i = 0; i < bullets1.size(); i++) {
			if (bullets1.get(i) != null) {
				try {
					bullets1.get(i).drawball(bg);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				bullets1.get(i).moveBall();
				if(bullets1.get(i).y<0) {
					bullets1.remove(i);
				}
			}
		}

		System.out.println("已经生成的敌方飞船:"+balls.size());
		System.out.println("已经生成的子弹:"+bullets.size());    
					
	}
	
	// 重写run                                                                                          
	public void run() {  
		// 添加双缓存技术,解决游戏画面闪烁问题
		// 得到一张缓冲图片      
		Graphics g = this.getGraphics();
		BufferedImage bfimg = new BufferedImage(this.getWidth(), this.getHeight(),          
				BufferedImage.TYPE_INT_ARGB);                                                         
		// 通过缓冲图片对象取到一张缓冲画布                                                                           
		Graphics bg = bfimg.getGraphics();    
		//System.out.println(game);
		while (game==true) {                                                                                
			paint(bg);
			//将缓冲图片通过窗体的画布绘制到窗体上 
			g.drawImage(bfimg, 0, 0, this);
			                                                                                           
		}       
	}

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

		BallFrame bf = new BallFrame();
		bf.initUI();
		Thread t1= new Thread(bf);
		t1.start();
		
	}
}

监听器类的代码实现

package NewBallV2;

import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;

import javax.imageio.ImageIO;

public class BallListen implements MouseListener,KeyListener,ActionListener{

	Graphics g;
	String action;
	String shapeTypeStr = "";
	ArrayList<Ball> balls = new ArrayList<Ball>();
	ArrayList<Ball> bullets1 = new ArrayList<Ball>();
	ArrayList<Plane> ships = new ArrayList<Plane>();
	BallFrame ballFrame;
	Boolean game;
	
	public BallListen(BallFrame ballFrame,ArrayList<Ball> balls,ArrayList<Ball> bullets1,ArrayList<Plane> ships,Boolean game){
		this.ballFrame = ballFrame;
		this.balls=balls;
		this.ships=ships;
		this.bullets1=bullets1;
		this.game=game;
	}
	
	public void actionPerformed(ActionEvent e){
		action = e.getActionCommand();	
		shapeTypeStr = action;
	}
	
	public void keyTyped(KeyEvent e){
		
	}
	
    public void keyPressed(KeyEvent e){
    	//键盘控制飞机
    	switch(e.getKeyCode()){
	    	case 0x25 :
	    		ships.get(0).x-=5;
	    		break;
	    	case 0x26 :
	    		ships.get(0).y-=5;
	    		break;
	    	case 0x27 :
	    		ships.get(0).x+=5;
	    		break;
	    	case 0x28 :
	    		ships.get(0).y+=5;
	    		break;
    	}
    	
    }

    public void keyReleased(KeyEvent e){
    	
    }
	
	public void mouseClicked(MouseEvent e) {
		
		
	}
	Random random = new Random();
	public void mousePressed(MouseEvent e) {
		//按下鼠标操作
		
		//if("开始".equals(shapeTypeStr)){
			//game=true;
			
			//准备己方子弹数据
			int x=ships.get(0).x + 49;
			int y=ships.get(0).y - 10;
			int speedx = 0;
			int speedy = -25;
			BufferedImage img = null;
			try {
				//子弹图片
				img = ImageIO.read(new File("F:\\Java\\学习\\线程飞机大战\\飞机大战\\myplane\\bullet1.png"));
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		
			//生成己方子弹
			Ball mybullet= new Ball(bullets1, x, y, speedx, speedy, img);
			bullets1.add(mybullet);
			
	//		System.out.println("按下鼠标");
	//		
	//		int speedx = random.nextInt(10);
	//		int speedy = random.nextInt(10);
	//		int r = random.nextInt(255);
	//		int g = random.nextInt(255);
	//		int b = random.nextInt(255);
	//		Color color = new Color(r,g,b);
	//				
	//		
	//		Ball ball =  new Ball(balls,e.getX(),e.getY(),50,speedx,speedy,color);
	//		balls.add(ball);
		//}
	}

	public void mouseReleased(MouseEvent e) {
		
	}

	public void mouseEntered(MouseEvent e) {
		
	}

	public void mouseExited(MouseEvent e) {
		
	}
                                     
}

飞船生成类的代码实现

package NewBallV2;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;

import javax.imageio.ImageIO;

public class BallAI extends Thread{
	
	ArrayList<Ball>  balls;
	ArrayList<Ball>  bullets;
	ArrayList<Plane>  ships;
	Random  random = new Random();
	
	public BallAI(ArrayList<Ball>  balls,ArrayList<Ball>  bullets,ArrayList<Plane>  ships) {
		this.balls=balls;
		this.bullets=bullets;
		this.ships=ships;
	}
	@Override
	public void run() {
		// 休眠
		try {
			Thread.sleep(300);
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		//己方飞船的图片文件
		BufferedImage img1 = null;
		try {
			img1 = ImageIO.read(new File("F:\\Java\\学习\\线程飞机大战\\飞机大战\\myplane\\hero12.png"));
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		//生成己方飞船
		Plane ship= new Plane(ships, 800, 900, img1);
		ships.add(ship);
		 while (true) {
		
			//准备敌方飞船数据
			int x=random.nextInt(1800);
			int y=10;
			int speedx = random.nextInt(18) - 8;
			int speedy = random.nextInt(5) + 5;
			BufferedImage img = null;
			try {
				img = ImageIO.read(new File("F:\\Java\\学习\\线程飞机大战\\飞机大战\\enemyplane\\enemy1.png"));
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		
			//生成敌方飞船
			Ball ball= new Ball(balls, x, y, speedx, speedy, img);
			balls.add(ball);
			
			//启动这个飞船自动生成子弹的线程
			BulletAI bulletAI = new BulletAI(bullets, ball);
			bulletAI.start();
			
			// 生成飞船间隔时间
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		 }		
		
	}

}


生成子弹的代码实现

package NewBallV2;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;

import javax.imageio.ImageIO;

public class BulletAI extends Thread {
	Random random = new Random();
	ArrayList<Ball> bullets;
	Ball ball;

	public BulletAI(ArrayList<Ball> bullets, Ball ball) {
		this.bullets=bullets;
		this.ball=ball;
	}

	@Override
	public void run() {

		while (true) {
			// 准备子弹数据
			int x = ball.x + 25;
			int y = ball.y + 35;
			//int size = 15;
			int speedx = 0;
			int speedy = 8;
			BufferedImage img = null;
			try {
				//子弹图片
				img = ImageIO.read(new File("F:\\Java\\学习\\线程飞机大战\\飞机大战\\enemyplane\\bullet2.png"));
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

			//生成子弹
			Ball ball = new Ball(bullets, x, y, speedx, speedy, img);
			bullets.add(ball);
			
			
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
				

		}

	}

}

运行效果

在这里插入图片描述

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值