Java实现简单的飞机大战游戏(敌机下落篇)
本文实例为大家分享了Java实现简单飞机大战游戏,敌机下落的具体代码,供大家参考,具体内容如下
在实现这个游戏之前,我们首先需要知道项目可能要用到哪些知识点:
重绘,线程,双缓冲,数据结构的应用
差不多是这大概有这些,如果不够的话我们再加。
首先,我们应该实现敌机下落,在这里大概思路和利用线程使小球下落差不多。不同的是,我在这里用到了三种敌机,分别为小、大、BOSS机三种。然后给予这三种敌机不同的下落规则(即速度、出现的时间、是否伴随子弹的发射等等)来给游戏适当的增加点难度。
以下是我的大概设计思路和下落规则,大家可以参考一下
1.飞机是在一开始的时候就出现的,先出现什么飞机?速度?什么位置出现?频率?
先出小飞机,再出大飞机,当所有的大小飞机都消失以后出现BOSS机.
小飞机的速度较快:8 大飞机的速度较慢:4 BOSS机的速度最慢:2
频率:每隔1秒出现一架小飞机,每出现4架小飞机后出现一架大飞机,最后出现BOSS机.
位置:在窗体的范围内,考虑到png图片的高度和宽度,所以出现的时候注意减去相应的高度和宽度.
2.小飞机,大飞机,BOSS机需要使用不同的vector类来保存,取出的时候再使用一个vector类来保存(保存的时候应该将三个vector类中原来的飞机移除).再将保存起来的飞机依次进行画出.当出现4架小飞机的时候就出现一架大飞机,当小飞机和大飞机都出现完了以后,出现BOSS机.注意:大飞机和BOSS机的时候伴随着子弹的发出.
3.子弹:
子弹在大飞机和BOSS机出现的时候出现.且速度优于大飞机和BOSS机.因为小飞机没有子弹,在这里我们利用byte标记来区别于小飞机和其他两种飞机,另外也需要将子弹标记,以防止子弹生成子弹。
4.使用两个线程:
(1)一个线程用来实现将不同的vector向量取出的飞机(先将大小飞机取出以后,再取出BOSS机,每取一次小飞机的时候将count记一次数,当count==4的时候,取出一架大飞机.当小飞机和大飞机全部取完以后再取出BOSS机),并保存在一个统一的vector向量中.
(2)另一个线程用来实现画飞机和子弹并使其移动.
5.效果图出现过于闪烁的情况可以利用双缓冲技术来减少闪烁。
以下是代码主类,主要生成窗体和敌机,并将敌机保存在不同的vector向量中。
public class BallMain { public Graphics g; public Vector<Ball> vector, minVector, maxVector, bossVector; public ImageIcon img; public static void main(String[] args) { BallMain bm = new BallMain(); bm.init(); } public void init() { JFrame frame = new JFrame(); frame.setTitle("飞机大战"); frame.setSize(800, 800); frame.setDefaultCloseOperation(3); frame.setLocationRelativeTo(null); frame.setBackground(Color.white); frame.setResizable(false); // 不允许改变窗体大小 frame.setVisible(true); this.g = frame.getGraphics(); minVector = new Vector<Ball>(); maxVector = new Vector<Ball>(); bossVector = new Vector<Ball>(); vector = new Vector<Ball>(); initPlane(frame); BallThread bt = new BallThread(vector, minVector, maxVector, bossVector, frame); bt.start(); BallGraThread bll = new BallGraThread(vector, frame, frame.getGraphics()); bll.start(); } public void initPlane(JFrame frame) { Random rand = new Random(); // 小飞机的生成 for (int i = 0; i < 8; i++) { ImageIcon icon = new ImageIcon("plane/plane0.png"); int r = icon.getIconWidth() / 2; int x = rand.nextInt(frame.getWidth() - icon.getIconWidth()) + r; int y = -icon.getIconHeight(); int vy = 8; Ball b = new Ball(icon.getImage(), x, y, r, vy, (byte) 1); minVector.add(b); } // 大飞机的生成 for (int i = 0; i < 2; i++) { ImageIcon icon = new ImageIcon("plane/plane1.png"); int r = icon.getIconWidth() / 2; int x = rand.nextInt(frame.getWidth() - icon.getIconWidth()) + r; int y = -icon.getIconHeight(); int vy = 4; Ball b = new Ball(icon.getImage(), x, y, r, vy, (byte) 2); maxVector.add(b); } // Boss机的生成 ImageIcon icon = new ImageIcon("plane/plane2.png"); int r = icon.getIconWidth() / 2; int x = rand.nextInt(frame.getWidth() - icon.getIconWidth()) + r; int y = -icon.getIconHeight(); int vy = 2; Ball b = new Ball(icon.getImage(), x, y, r, vy, (byte) 3); bossVector.add(b); } }
以下为飞机的下落规则:
public BallThread(Vector<Ball> vector, Vector<Ball> minVector, Vector<Ball> maxVector, Vector<Ball> bossVector, JFrame frame) { this.vector = vector; this.minVector = minVector; this.maxVector = maxVector; this.bossVector = bossVector; this.frame = frame; } public void run() { int count = 0; while (true) { if (minVector.size() > 0) { vector.add(minVector.remove(0)); ++count; if (count == 4) { if (maxVector.size() > 0) { vector.add(maxVector.remove(0)); count = 0; } } } if (vector.size() == 0) { vector.add(bossVector.remove(0)); break; } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
利用双缓冲减少闪烁,画出飞机并擦除,使其不断更新位置:
public class BallGraThread extends Thread { public Vector<Ball> vector; public JFrame frame; public Graphics g; public BufferedImage image; public Graphics ig; public BallGraThread(Vector<Ball> vector, JFrame frame, Graphics g) { this.vector = vector; this.frame = frame; this.g = g; } public void run() { if (image == null) { //创建一个带透明色的BufferedImage对象 image = new BufferedImage(frame.getWidth(), frame.getHeight(), BufferedImage.TYPE_INT_ARGB); //获取画笔对象. ig = image.getGraphics(); } while (true) { //擦除. ig.setColor(frame.getContentPane().getBackground()); ig.fillRect(0, 0, frame.getWidth(), frame.getHeight()); for (int i = 0; i < vector.size(); i++) { Ball ball = vector.get(i); ball.draw(ig); ball.move(vector, frame, ig); } g.drawImage(image, 0, 0, frame); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }
子弹类,标记子弹来区分三种敌机,当飞机和子弹飞出窗体外后将其移除与vector:
public class Ball { public int x, y; public int flag = 1; public Color color; public Image img; public BulletThread ba; int r; int vy; byte type; Random random = new Random(); public Ball(Image img, int x, int y, int r, int vy, byte type) { this.img = img; this.x = x; this.y = y; this.r = r; this.vy = vy; this.type = type; } public void move(Vector<Ball> vector, JFrame frame, Graphics g) { if (y >= 0 && flag == 1) { // 如果是大飞机或者BOSS机的话,就发射子弹. if (type == 2 || type == 3) { ba = new BulletThread(vector, this); ba.start(); flag = 2; System.out.println(ba); } } if (y >= frame.getHeight()) { img = new ImageIcon("planne/bullet.png").getImage(); g.drawImage(img, x, y, 2 * r, 2 * r, null); System.out.println(ba); if (type == 2 || type == 3) ba.stopFlag = false; vector.remove(this); } y = y + vy; } public void draw(Graphics g) { // 需要将ImageIcon转为Image类型的. g.drawImage(img, x, y, 2 * r, 2 * r, null); } }
画出子弹并添加于vector向量中,使其移动:
public class BulletThread extends Thread { public Vector<Ball> vector; public Ball ball;// 大飞机的数据来生成子弹 public boolean stopFlag = true; public boolean pauseFlag = true; public BulletThread(Vector<Ball> vector, Ball ball) { this.vector = vector; this.ball = ball; } public void run() { while (stopFlag) { if (pauseFlag) { int x = ball.x + ball.r; int y = ball.y + 2 * ball.r; int r = 20; Image img = new ImageIcon("plane/bullet.png").getImage(); int vy = ball.vy + 4; Ball bullet = new Ball(img, x, y, r, vy, (byte) 0); vector.add(bullet); } try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
以上差不多就是敌机的下落,其他的一些功能尚未完善,比如可以给敌机添加不同的血量再来增加难度,大家可以根据自己的发挥来写出属于自己的飞机大战游戏。
希望这篇文章对大家的学习有所帮助,也希望大家多多支持脚本之家。
相关文章
Security框架:如何使用CorsFilter解决前端跨域请求问题
这篇文章主要介绍了Security框架:如何使用CorsFilter解决前端跨域请求问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-11-11SpringBoot配置文件中数据库密码加密两种方案(推荐)
SpringBoot项目经常将连接数据库的密码明文放在配置文件里,安全性就比较低一些,尤其在一些企业对安全性要求很高,因此我们就考虑如何对密码进行加密,文中给大家介绍加密的两种方式,感兴趣的朋友一起看看吧2019-10-10SpringBoot使用RedisTemplate.delete删除指定key失败的解决办法
本文主要介绍了SpringBoot使用RedisTemplate.delete删除指定key失败的解决办法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下2022-03-03Java中的 BigDecimal 和 String 的相互转换问题
这篇文章主要介绍了Java中的 BigDecimal 和 String 的相互转换问题,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2023-05-05
最新评论