Java第二个项目--基于线程实现飞机大战

2018.8.8

前言:学习Java也有好长一段时间了,前几天搞了一下线程游戏,借此写篇博客留点东西供日后回来学习,也希望能帮到刚入门线程的小伙伴。

一、先看看游戏界面:有点不美观,23333。暂时还没有太多的时间去考虑细节,红色的为飞机的血量,没有血量的飞机是玩家的,hhh无敌有点作弊。

 

二、具体实现:

        其实这个就是根据那个多线程弹跳小球改过来了。我本来想用多线程来实现,但无奈空指针错误多得我改不过来。(期待大佬指正)所以我就用了简单的循环+队列数组和一个单线程。循环主要是产生随机的敌机,线程用来控制飞机的绘制和移动。为了更好的理解游戏的结构,我新建了四个类,分别是主界面、监听、产生飞机、产生子弹。每个类干好自己的事情就好了,需要共用的数据就传一下,emmm就是这么简单。在写的时候可能会遇到空指针的错误,这是类对象在传递的时候的错误,简单的说就是当年需要用这个对象的时候,但这个对象还没有被传递过来,如果使用它就会产生空指针错误,所以线程的启动时间需要特别注意!给各位朋友的建议就是在所有数据都到位后在启动绘制飞机的线程,这样百分百不会产生空指针错误。

三、详细代码分析:

为了更方便管理我们的代码,我们将代码分成四个部分:1、主界面类 ; 2、负责画飞机的类 ; 3、负责画子弹的类; 4、监听器类;详细说明已在代码加注释。

1.主界面类:

package com.Lzh_20180727;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import com.zn.ArrayList0720.*; //自定义的数组队列,用系统自带的会发生空指针异常

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;


import java.awt.Image;
;public class MainFrame extends JFrame implements Runnable{
	
	public static void main(String[] args) {
		MainFrame mf = new MainFrame();
		mf.Init();	
	}
	public ArrayListlist = new ArrayList();//存储小球的
	public ArrayListbulletlist = new ArrayList();//存储子弹的
	public volatile boolean StopFlag = false;//是否开始游戏的标志
	public volatile boolean PauseFlag = true;//是否处于游戏暂停状态
	public int Count = 0;
	public JLabel s ,Time;//游戏剩余时间
	
	//BallAI ballai = new BallAI(this,5);//将窗体和要生成的小球数量传过去
	
	public void Init()
	{
		this.setTitle("飞机大战2`.0");
		this.setSize(1400, 1000);
		this.setResizable(false);
		this.setLocationRelativeTo(null);
		this.getContentPane().setBackground(Color.black);
		this.setDefaultCloseOperation(3);
		String type[]={"启动","暂停","恢复","停止"};
		this.setLayout(null);
		AllListener AL = new AllListener(StopFlag,PauseFlag,this,bulletlist);//建立监听器对象
		
		ImageIcon IMG = new ImageIcon("src\\1285.gif");
		JLabel score = new JLabel();
		score.setIcon(IMG);
		score.setBounds(950, 20, 150, 50);
		score.setFont(new Font("宋体",Font.BOLD,30));
		this.add(score);
		
		ImageIcon MMG = new ImageIcon("src\\1313.gif");
		JLabel time = new JLabel();
		time.setIcon(MMG);
		time.setBounds(60, 20, 150, 50);
		time.setFont(new Font("宋体",Font.BOLD,30));
		this.add(time);
		
		 Time = new JLabel();
		Time.setBounds(250,20, 50, 50);
		Time.setFont(new Font("宋体",Font.BOLD,30));
		this.add(Time);
		s = new JLabel("0");
		
		s.setText(Count+" ");
		s.setBounds(1150, 20, 150, 50);
		s.setFont(new Font("宋体",Font.BOLD,30));
		this.add(s);
		for(int i=0;i=0;t--)//倒计时,时间结束后GameOver
				{
					Time.setText(t+"");
				}
				
		
			   pan.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), null);
				
				pan.fillRect(list.get(0).x-3*list.get(0).r, list.get(0).y-2*list.get(0).r, 
				this.list.get(0).blood*10, 10);//飞机当前的生命值
				this.list.get(0).drawBall(pan);
				this.list.get(0).moveBall();
				//this.list.get(0).Iscrash(0);
				for(int i=1;i

2.负责保存飞机信息的类:

package com.Lzh_20180727;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import com.zn.ArrayList0720.*;
import java.util.Random;

import javax.swing.ImageIcon;

public class Ball {
	
	
	public int x=30,y=30,r=5,speedX=5,speedY=7,num=0;//初始化一些数据,防止空指针错误
	public int blood =0;//飞机的生命值
	private Color c = Color.black;//这个没用到
	private Image img ;//飞机的图片对象
	public MainFrame mf;//将主界面传过来
	private Graphics g;//绘制需要的画笔类
	private ArrayListlist;//存储飞机所有信息的队列数组
	private Random random = new Random();//随机数,主要用于产生敌机的位置和生命值
	public Ball(int x, int y, int r, int speedX, int speedY,int num, Color c, MainFrame mf,
			Graphics g, ArrayList list,int blood,Image img) {//构造函数
		super();
		this.x = x;
		this.y = y;
		this.r = r;
		this.speedX = speedX;
		this.speedY = speedY;
		this.c = c;
		this.mf = mf;
		this.g = g;
		this.list = list;
		this.num = num;
		this.blood = blood;
		this.img = img ;
	}
//	public Ball(int x,int y,int r,int speedX,int speedY)
//	{
//		this.x = x;
//		this.y = y;
//		this.r = r;
//		this.speedX = speedX;
//		this.speedY = speedY;
//	}
	public void drawBall(Graphics gg)
	{
//		int i = random.nextInt(255);
//		int j = random.nextInt(255);
//		int k = random.nextInt(255);
//		g.setColor(new Color(i,j,k));//设不设置颜色都无所谓了,因为我们画的是图片
		gg.setColor(Color.blue);
	//	gg.fillOval(x-r, y-r, 2*r, 2*r);
		gg.drawImage(img, x-r, y-r, null);//绘制飞机
	}
	public void moveBall()//飞机移动的方法
	{
		if(x+r>=mf.getWidth())//到达右边界
		{
			speedX*=-1;
		}
		else if(x+r<0)
		{
			speedX*=-1;
		}
		if(y+r>=mf.getHeight())
		{
			speedY*=-1;
		}
		else if(y+r<0)
		{
			speedY*=-1;
		}
		x+=speedX;
		y+=speedY;
	}
	public void clearBall()//清除飞机的,现在不需要了,用remove就好了。
	{
		g.setColor(Color.black);
		g.fillOval(x-r-speedX, y-r-speedY, 2*r, 2*r);
	}
//	public void Iscrash(int  i)//此方法原来是判断飞机间是否碰撞的,但现在判断子弹和飞机,故注释
//	{
//		for(int j=0;jmf.list.get(j).x) { 
//						speedX*=1;
//						blood-=1;
//					}
//					else	
//					{
//						speedX*=-1;
//						blood-=1;
//					}
//					if(y>mf.list.get(j).y) { 
//						speedY*=1;
//						blood-=1;
//					}
//					else	
//					{
//						speedY*=-1;
//						blood-=1;
//					}
//					
//				}
//				
//			}
//		}
	public void Craeat_Ball()//生成绘制飞机所需要的信息,并存入队列数组
	{
		
		ImageIcon image = new ImageIcon("src\\飞机1.png"); 
		Image img = image.getImage();
		Ball myball = new Ball(400,400,30,0,0,num,Color.red,mf,g,list,0,img);
		list.add(myball);
		System.out.println("生成球的方法被调用!");
		for(int i=0;i

3.绘制子弹类:

package com.Lzh_20180727;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import com.zn.ArrayList0720.*;
import java.util.Random;

import javax.swing.JOptionPane;

public class DrawBullet {
	
	//public  ArrayListbulletlist;
	public int x,y,r,speedX,speedY; //定义绘制子弹需要的信息
	public Color c ;
	private Random random = new Random();
	public boolean IsFire = false;是否开火的标志
	public MainFrame mf;
	private Image img ;
	public DrawBullet(int x,int y,int r,int speedX,int speedY,Color c,MainFrame mf ,
			Image img  )//构造函数,传入需要的数据
	{
		this.mf = mf ;
		
		this.x = x;
		this.y = y;
		this.r = r;
		this.speedX = speedX;
		this.speedY = speedY;
		this.c = c;
		this.img = img;
	}
	
	public void drawbullet(Graphics gg)//根据拿到的信息绘制子弹
	{
		//gg.setColor(Color.red);
	//	gg.fillOval(x, y, 2*r, 2*r);
		gg.drawImage(img, x+10, y-50, 40,80,null);
		
	}
	public void movebullet()//子弹移动
	{
//		if(x+r>=mf.getWidth())
//		{
//			speedX*=-1;
//		}
//		else if(x+r<0)
//		{
//			speedX*=-1;
//		}
//		if(y+r>=mf.getHeight())
//		{
//			speedY*=-1;
//		}
//		else if(y+r<0)
//		{
//			speedY*=-1;
//		}
		y+=speedY;
	}
	public void Ishit()//子弹是否击中飞机,遍历所有的子弹和飞机,计算两者的距离,小于某个值则碰撞,飞机生命值减少。
	{
		for(int i=1;i

4.监听器类:

package com.Lzh_20180727;

import java.awt.Color;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import com.zn.ArrayList0720.*;

import javax.swing.ImageIcon;

public class AllListener extends MouseAdapter implements ActionListener {
	
	
	 public  volatile boolean StopFlag ,PauseFlag;
	 public MainFrame mf ;
	 public ArrayListbulletlist;
	 private boolean Isfire = false;
	 
	 public AllListener( boolean StopFlag, boolean PauseFlag,MainFrame mf,ArrayListbulletlist)
	 {
		 this.StopFlag = StopFlag;
		 this.PauseFlag = PauseFlag;
		 this.mf = mf;
		 this.bulletlist = bulletlist;
		 
	 }
	 
	 public void actionPerformed(ActionEvent e)
	 {
		 if(e.getActionCommand().equals("启动"))
		 {
			 mf.StopFlag = true;
			 System.out.println("启动!"+StopFlag);
			 Thread t = new Thread(mf);
			 t.start();
				
		 }
		 else if(e.getActionCommand().equals("暂停"))
		 {
			 mf.PauseFlag = false;
		 }
		 else if(e.getActionCommand().equals("恢复"))
		 {
			 mf.PauseFlag = true;
		 }
		 else if(e.getActionCommand().equals("停止"))
		 {
			 mf.StopFlag = false;
		 }
	 }
	 public void mousePressed(MouseEvent e) {
		// bulletlist.clear();
		 Isfire = true;
		 int x = mf.list.get(0).x+5;
		 int y = mf.list.get(0).y-30;
		 Isfire = true;
		 ImageIcon IMG = new ImageIcon("src\\bullet2.png");
		 Image img = IMG.getImage();
		 DrawBullet mybullet = new DrawBullet(x,y,5,0,-10,Color.red,mf,img); 
		 bulletlist.add(mybullet);
		
		 
		 
	 }
	 public void mouseReleased(MouseEvent e) {
		 Isfire = false; 
		  
	 }
	 public void mouseMoved(MouseEvent e){

		 int x = e.getX();
		 int y = e.getY()-150;
		 mf.list.get(0).x = x-mf.list.get(0).r;
		 mf.list.get(0).y = y-mf.list.get(0).r;
		 
	 }
	 
	 
	 public void mouseDragged(MouseEvent e){
		 
		
		 
	 }
}

我有罪啊。。8.8就写的博客现在才完成。。请鞭策我。。。下次绝对不懒了!!

你可能感兴趣的:(Java第二个项目--基于线程实现飞机大战)