Java多线程游戏-雷霆战机

Posted 独奏夜上弦^O^

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java多线程游戏-雷霆战机相关的知识,希望对你有一定的参考价值。

Java多线程游戏-雷霆战机

先来张效果图(结尾附上源码地址,欢迎交流)

一、总述

飞机大战大家童年的时候都玩过,前两天学了线程方面的知识后,决定写一个关于多线程雷霆战机的游戏(单机)。这里用到了许多有关线程,图片处理,音乐等的技术我刚接触Java半年,做这个游戏磕磕绊绊。花费了很多时间,最后还是有一些瑕疵。素材是从另一位博主那下载的。

素材下载地址:
地址

二、相关技术

  1. 了解什么是线程,进程,多线程,并发线程
  2. 了解线程寿命以及线程的控制
  3. 了解线程安全问题,处理游戏中出现的线程安全问题
  4. 了解Java中的list类以及它的底层实现
  5. 音乐文件的读取与播放
  6. 了解键盘监听
  7. 缓冲区(解决屏幕闪烁问题)

三、功能介绍及讲解

(一)功能简介
1.加载页面
2.菜单页面
3.弹窗提示
4.多重关卡(四关)
5.多种飞机(八种)
6.音效
7.地图动态滚动,爆炸动图
8.分数达到一定程度飞机升级
9.计时
10.暂停\\继续游戏(线程控制)
11.开始新游戏(清空原有数据与加载新数据)
12.道具栏与道具使用(刷新道具栏,使用道具,四种道具)
13.关卡boss

(二)功能讲解
1.加载页面的制作

关键点:进度条的使用

加载界面,无外乎就是个界面嘛,重要的可能就是那个加载条了吧。这个加载条你可以自己做,也可以用Java中的加载条,这里我用的是Java中自带的加载条。

		JProgressBar bar = new JProgressBar(1, 100);
		bar.setStringPainted(true); //描绘文字
		bar.setString("加载飞机和子弹中,请稍候,精彩马上开始");  //设置显示文字
		bar.setBackground(Color.ORANGE);  //设置背景色
		bar.setBounds(100, 800, 1000, 100);//设置大小和位置
		bar.setValue(20); //设置进度条值

2.菜单页面的制作

就是提供一些功能按键以及弹窗实现各功能的有序进行。

关键点:弹窗、按钮监听、焦点的获取

弹窗,无外乎也是个界面嘛,要么自己做一个窗口,要么使用Java中自带的弹窗类

JDialog cs=new JDialog();

弹窗的各项操作与窗体JFrame类是一致的。
这里要注意的就是因为后面要实现键盘的监听,所以焦点必须要注意他的位置。并注意获取焦点。

3.多重关卡
这个没啥好说的,我就只是找了四张地图而已。

4.多种飞机
这个比较麻烦,在设计类的时候,可以将各种飞机不同的属性用私有数据来进行初始化。在创建飞机对象的时候将各项数据传进去即可。
下面是我的飞机类代码;

英雄机

public class MyHeroPlane {
	private int Blood;
	private int speed;
	private ImageIcon image;
	public MyHeroPlane(int blood, int speed, ImageIcon image) {
		super();
		Blood = blood;
		this.speed = speed;
		this.image = image;
	}
	public int getBlood() {
		return Blood;
	}
	public int getSpeed() {
		return speed;
	}
	public ImageIcon getImage() {
		return image;
	}
	public void setBlood(int blood) {
		Blood = blood;
	}
	
}

敌机类

public class EnemyPlane extends Thread{
	private int blood;
	private int x,y;
	private ImageIcon image;
	private int speed;
	private boolean islive;
	private int sore;
	private boolean suspend=false;
	public EnemyPlane(int blood, int x, int y, ImageIcon image,int speed,int sore) {
		super();
		this.blood = blood;
		this.x = x;
		this.y = y;
		this.image = image;
		this.speed=speed;
		this.islive=true;
		this.sore=sore;
	}
	public void run()
	{
		while(blood>=0&&islive)
		{
			while(suspend)
			{
				//暂停功能
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			y+=speed;
		}
	}
	public int getBlood() {
		return blood;
	}
	public int getX() {
		return x;
	}
	public int getY() {
		return y;
	}
	public ImageIcon getImage() {
		return image;
	}
	public int getSpeed() {
		return speed;
	}
	public boolean isIslive() {
		return islive;
	}
	public void setIslive(boolean islive) {
		this.islive = islive;
	}
	public void setBlood(int blood) {
		this.blood = blood;
	}
	public int getSore() {
		return sore;
	}
	public boolean isSuspend() {
		return suspend;
	}
	public void setSuspend(boolean suspend) {
		this.suspend = suspend;
	}
	
}

子弹类(我方,敌方子弹)
我方子弹类

public class MyHeroBullets extends Thread{
	private boolean islive=true;
	private int x;
	private int y;
	private int atk;
	private ImageIcon image;
	private int speed;
	private boolean suspend=false;
	public MyHeroBullets(int x, int y, int atk, ImageIcon image, int speed) {
		super();
		this.x = x;
		this.y = y;
		this.atk = atk;
		this.image = image;
		this.speed = speed;
	}

	public void run() {
		while(islive)
		{
			while(suspend)
			{
				//暂停功能
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			y-=speed;
		}
	}

	public boolean isIslive() {
		return islive;
	}

	public int getX() {
		return x;
	}

	public int getY() {
		return y;
	}

	public int getAtk() {
		return atk;
	}

	public ImageIcon getImage() {
		return image;
	}

	public int getSpeed() {
		return speed;
	}

	public void setIslive(boolean islive) {
		this.islive = islive;
	}

	public boolean isSuspend() {
		return suspend;
	}

	public void setSuspend(boolean suspend) {
		this.suspend = suspend;
	}
	
}

敌方子弹类

public class EnemyBullets extends Thread{
	private int atk;
	private ImageIcon image;
	private int speed;
	private boolean islive=true;
	private int x,y;
	private boolean suspend=false;
	public EnemyBullets(int atk, ImageIcon image, int speed, int x, int y) {
		super();
		this.atk = atk;
		this.image = image;
		this.speed = speed;
		this.x = x;
		this.y = y;
	}
	public void run() {
		while(islive)
		{
			while(suspend)
			{
				//暂停功能
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			y+=speed;
		}
	}
	public boolean isIslive() {
		return islive;
	}
	public void setIslive(boolean islive) {
		this.islive = islive;
	}
	public int getAtk() {
		return atk;
	}
	public ImageIcon getImage() {
		return image;
	}
	public int getSpeed() {
		return speed;
	}
	public int getX() {
		return x;
	}
	public int getY() {
		return y;
	}
	public boolean isSuspend() {
		return suspend;
	}
	public void setSuspend(boolean suspend) {
		this.suspend = suspend;
	}
	
}

这里我没有将子弹与飞机封装在一起,这个不太方便,各位可以采用封装在一起的方法来实现。

5.音效
话不多说,读取文件后播放,直接上代码。

public class GetMusic extends Thread{
	private String path;
	private boolean flag=true;
	private boolean whileplay;
	private double value ;

	public GetMusic(String path,boolean whileplay,double value) {
		super();
		this.path = path;
		this.whileplay=whileplay;
		this.value=value;
	}
	public void run()
	{
		if(whileplay)
		{
			while(flag)
			{
				playMusic();
			}
		}
		else
			playMusic();
	}
	public void playMusic() {// 背景音乐播放
		 
		try {
			AudioInputStream ais = Audiosystem.getAudioInputStream(new File("music\\\\"+path));
			AudioFormat aif = ais.getFormat();
			final SourceDataLine sdl;
			DataLine.Info info = new DataLine.Info(SourceDataLine.class, aif);
			sdl = (SourceDataLine) AudioSystem.getLine(info);
			sdl.open(aif);
			sdl.start();
			FloatControl fc = (FloatControl) sdl.getControl(FloatControl.Type.MASTER_GAIN);
			// value可以用来设置音量,从0-2.0
			double value = 2;
			float dB = (float) (Math.log(value == 0.0 ? 0.0001 : value) / Math.log(10.0) * 20.0);
			fc.setValue(dB);
			int nByte = 0;
			int writeByte = 0;
			final int SIZE = 1024 * 64;
			byte[] buffer = new byte[SIZE];
			while (nByte != -1) {
				if(flag) {
					sdl.write(buffer, 0, nByte);
					nByte = ais.read(buffer, 0, SIZE);
				}else {
					
					nByte = ais.read(buffer, 0, 0);
					
				}
			}
			sdl.stop();
 
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public boolean isFlag() {
		return flag;
	}
	public void setFlag(boolean flag) {
		this.flag = flag;
	}
}

6.飞机升级
这个挺好实现的,你在产生子弹的线程中多产生两路子弹就可以了。当然如果你有什么更好的想法,欢迎交流。
效果图:(达到4000分升级)

7.暂停\\重新开始
我在这里用的是在线程run方法中加入死循环,进入暂停时,所有线程进入死循环。当然这样也有缺点,就是对电脑资源占用较高。也可以采用对线程进行休眠与唤醒来实现,这种方法在我的程序中较为麻烦,就没采用。

8.开始新游戏
这个你可以用重新创建对象来实现,但是如果你之前创建对象使用的是static,那么,你就需要去手动清空所有数据。很不巧,我就是部分对象创建的是static,所以会稍微麻烦一些。

9.道具的使用
为了增加游戏的可玩性,你可以增加一些道具,例如,加血道具,护盾道具,僚机,强化子弹。。。。。
这个你可以自己设计。你可以通过我的源码看懂怎么设计的就不赘述了。上两张效果图。

护盾

僚机
强化子弹

10.关卡boss
这个和设计敌机一样,只是吧,你可把boss血量调高一些,发射子弹的方式调一下。

(三)关键算法
碰撞判断
先看一张图

碰撞无外乎就是上面四种情况,所以,我们可以有很多种方法去实现它,你可以通过判断两张图片中心点之间的距离,你也可以通过遍历我方飞机的四个点,是否有一个点在敌方飞机或子弹的范围内即可。

四、我这个项目明显的缺点

  1. 所有我方子弹,敌方飞机,敌方子弹都是一个新线程,游戏进行中同时运行了成百上千的线程。造成电脑卡顿,资源浪费。解决方法,移动的线程不必每次创建子弹和飞机时都启动一个线程,用一个移动线程就能控制。
  2. 图片因为是四四方方的一张图片,有一部分留白,所以在写碰撞函数时无法兼顾所有图片,存在一定视觉上的误差(明明打中了却穿过去了,或者明明看上去没打中,但实际上却打中了)
  3. 游戏难度设置不合理(啊哈哈哈哈,因为我没有考虑玩家感受,在打boss的时候我试了一下,基本很难过关)。
  4. 游戏程序稳定性不好,遇到部分不容易出现的bug 会卡死。
  5. 存在一定闪烁问题(我加了缓冲功能,但是因为程序占用了太多资源,执行起来还是有一定的闪烁)。

最后的最后,附上我源代码的链接:
源码

以上是关于Java多线程游戏-雷霆战机的主要内容,如果未能解决你的问题,请参考以下文章

python及pygame雷霆战机游戏项目实战14 游戏开始结束界面

仿《雷霆战机》飞行射击手游开发--游戏的入口

仿《雷霆战机》飞行射击手游开发--游戏对象

仿《雷霆战机》飞行射击手游开发--游戏简介

有啥好玩的飞机游戏

仿《雷霆战机》飞行射击手游开发--项目总览