#java ArrayList<T>、线程、Image对象示例——飞机大战开发如此简单

java ArrayList、线程、Image对象示例——飞机大战开发如此简单

学习本文需要先准备的知识:窗体编写、窗体元素添加、鼠标监听器的使用、线程的使用(可以查看我的上一篇博客:“java线程 、键盘监听器——教你写自己的球球大作战”)

1、 前期准备(知识点讲解)

(1)、java ArrayList
a、什么是ArrayList
ArrayList可以说是一个动态数组,它的容量可以随时调整

b、怎样使用ArrayList
定义语法:

ArrayList<类名> ArrayList名= new ArrayList<类名>();  //<>里面必须是除了基本数据类型外的自定义数据类型(类)

给ArrayList<>添加内容:ArrayList对象名.add(对象名);

从ArrayList<>删除内容:

ArrayList对象名.remove(i); //删除第i个ArrayList成员
ArrayList对象名.remove(对象名); //如果ArrayList中存在此对象,则删除
ArrayList对象名.removeAll(ArrayList<T>对象名); //移除所有ArrayList<T>对象

例:

ArrayList<StoreThings> things = new ArrayList<StoreThings>();
StoreThings sts = new StoreThings(image, (jsf.getWidth() - 90) / 2, jsf.getHeight() - 90, 90, 90, 0, g, "m_p",jsf, things);
things.add(sts);

(2)、Image对象的使用

a、 Image对象的用途:用于储存图片

b、 Image对象的用法

Image image对象名 = new ImageIcon(this.getClass().getResource("图片名,包括后缀名")).getImage();  //图片必须和代码文件放在同一根目录下

c、 将Image在窗体里绘制出来

 Graphics对象名. drawImage(Image对象名, 图片左上角X坐标, 图片左上角Y坐标, 图片的宽度(可选), 图片的高度(可选), 需要绘制图片的窗体对象名);

例:

Image BackGround = new ImageIcon(this.getClass().getResource("BackGround.jpg")).getImage();
g.drawImage(BackGround, 100, 0, jsf.getWidth(), jsf.getHeight(), jsf);

2、 开发飞机大战
提示:可以从网上寻找飞机图片、子弹图片以及背景图片

(1)、游戏规则
玩家控制一架飞机,窗口最上方会不断地出现敌方飞机,同时我方飞机和地方飞机都会自动发子弹,我方的飞机子弹速度稍微快一些。当我方的子弹碰到敌机后敌机消失,敌方的子弹碰到我方飞机,我方死亡,结束游戏。

(2)、代码思路
a、背景、飞机和子弹的绘制:
写一个类储存飞机和子弹的信息,要能够保存飞机和子弹的位置、大小、对应的图片、移动速度等信息,当然一定要添加一个属性区分地方和我方、飞机和子弹,同时还需要有将该图片绘制出来的方法。

import java.awt.Graphics;
import java.awt.Image;
import java.util.ArrayList;

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

public class StoreThings {
	private int x, y, width, heigth;
	private Graphics g;
	private Image image;
	private String type;
	private JFrame jsf;
	private int speed = 0;
	private ArrayList<StoreThings> things;

	public StoreThings(Image image, int x, int y, int width, int heigth, int speed, Graphics g, String type, JFrame jsf,
			ArrayList<StoreThings> things) {
		this.image = image;
		this.x = x;
		this.y = y;
		this.width = width;
		this.heigth = heigth;
		this.speed = speed;
		this.g = g;
		this.type = type;
		this.jsf = jsf;
		this.things = things;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getWidth() {
		return width;
	}

	public void setY(int y) {
		this.y = y;
	}

	public int getX() {
		return x;
	}

	public int getY() {
		return y;
	}

	public String getType() {
		return type;
	}

	public int getSpeed() {
		return speed;
	}

	public void setSpeed(int speed) {
		this.speed = speed;
	}

	public void showThings() {    //绘制图片的方法
		g.drawImage(image, x, y, width, heigth, jsf);
	}
}

定义一个上述类的ArrayList对象,用来保存出现的各个飞机和子弹;

ArrayList<StoreThings> things = new ArrayList<StoreThings>();

写一个专门负责绘制的线程,里面的内容包括:绘制背景,然后执行ArrayList对象里每个成员的绘制方法,最后将每一个对象的X坐标加上他的速度,然后在此等待一段时间。以上这些内容可以放在一个while(true)循环里面。

while (true) {
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if (pause) {
				g.drawImage(BackGround, 100, 0, jsf.getWidth(), jsf.getHeight(), jsf);
				for (int i = 0; i < things.size(); i++) {
					StoreThings temp = things.get(i);
					temp.showThings();
					temp.setY(temp.getY()+temp.getSpeed());
				}
			}
		}

b、敌机的出现:
敌机的出现的位置纵坐标为0,横坐标可以是窗体0到窗体宽度范围的随机数,可以写一个继承了线程的对象用于生成敌机(定时创建敌机对象,并添加到一个ArrayList对象里面):

public void run() {
		while (start) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if (pause) {
				x = 100 + rand.nextInt(jsf.getWidth());
				Image image = new ImageIcon(this.getClass().getResource("EnemyPlane.png")).getImage();
				StoreThings st = new StoreThings(image, x, y, 80, 80, 10, g, "e_p", jsf, things);
				things.add(st);
			}
		}
	}

c、我方飞机的出现:可在监听器类的构造函数里写,建立一个Image对象,用Graphics的drawImage方法绘制出来。

public PlaneListener(Graphics g, JFrame jsf) {
		this.g = g;
		this.jsf = jsf;
		st = new ShowThread(g, jsf, things);
		mpt = new MyPlaneThread(jsf, things, g);
		et = new EnemyThread(g, jsf, things);
Image image = new ImageIcon(this.getClass().getResource("MyPlane.png")).getImage();  //我方飞机的图片
			StoreThings sts = new StoreThings(image, (jsf.getWidth() - 90) / 2, jsf.getHeight() - 90, 90, 90, 0, g, "m_p", jsf, things);   //将我方飞机绘制出来
	}

c、子弹的出现:
创建子弹对象,位置在各个飞机的中间位置,同时注意速度属性应该要比飞机快一点,同时,我方子弹的速度和地方子弹的速度方向相反,可以单独放在一个线程里面。

try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if (pause) {
				x = 100 + rand.nextInt(jsf.getWidth());
				Image image = new ImageIcon(this.getClass().getResource("EnemyPlane.png")).getImage();
				StoreThings st = new StoreThings(image, x, y, 80, 80, 10, g, "e_p", jsf, things);
				things.add(st);
				image = new ImageIcon(this.getClass().getResource("bullet1.png")).getImage();
				for (int i = 0; i < things.size(); i++) {
					StoreThings temp = things.get(i);
					if (temp.getType().equals("e_p")) {
						StoreThings Bullet = new StoreThings(image, temp.getX() + 28, temp.getY() + 40, 25, 25, 20, g,
								"e_b", jsf, things);
						things.add(Bullet);
					}
				}
			}

d、被子弹击中后
可以用飞机与子弹的距离和宽度等信息判断二者是否相碰,当我方飞机碰到敌方子弹时,或者地方飞机碰到我方子弹时应当爆炸消失(从ArrayList里面移除该对象,此方法建议放在储存这些信息的类里的绘制方法里执行,这样可以保证能及时判断二者的位置):

public void crash(StoreThings st) {
		if (st.getType().equals("e_p")) {
			for (int i = 0; i < things.size(); i++) {
				StoreThings temp = things.get(i);
				if (temp.getType().equals("m_b")) {
					double cx = temp.getX() - st.getX();
					double cy = temp.getY() - st.getY();
					double cw = temp.getWidth() + st.getWidth();
					if (Math.sqrt(cx * cx + cy * cy) <= cw / 2) {
						things.remove(st);
					}
				}
			}
		}

		if (st.getType().equals("m_p")) {
			for (int i = 0; i < things.size(); i++) {
				StoreThings temp = things.get(i);
				if (temp.getType().equals("e_b")) {
					double cx = temp.getX() - st.getX();
					double cy = temp.getY() - st.getY();
					double cw = temp.getWidth() + st.getWidth()-40;  //经测试有偏差,此处减去40以减小判断误差
					if (Math.sqrt(cx * cx + cy * cy) <= cw / 2) {
						things.remove(st);
						JOptionPane.showMessageDialog(null, "玩家死亡,游戏结束!");
						System.exit(0);
					}
				}
			}
		}
	}

e、暂停和继续游戏的实现

在界面添加继续游戏和暂停游戏按钮,为其添加事件监听器。在每个线程while循环里加一个if(boolean类型数据)的判断,为这个boolean类型数据写一个set方法,点击暂停时将其改成false,点击继续将其改成true。
注意:while和if之间最好放上几句代码,不然可能无法实现暂停功能,可以把延时的语句(Thread.sleep())放在此处。

  case "暂停游戏":
		st.setPause(false);
		mpt.setPause(false);
		et.setPause(false);
		break;
	case "继续游戏":
		st.setPause(true);
		mpt.setPause(true);
		et.setPause(true);
		break;

3、全部的代码
–ShowFrame.java–

package com.antony.PlaneBattle0916;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;

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

public class ShowFrame {
	public static void main(String[] args) {
		showUI();
	}

	public static void showUI() {
		JFrame jsf = new JFrame();
		jsf.setDefaultCloseOperation(3);
		jsf.setSize(700, 910);
		jsf.setLocationRelativeTo(null);
		BorderLayout boder = new BorderLayout();
		FlowLayout flow = new FlowLayout();
		jsf.setLayout(boder);
		JPanel jp = new JPanel();
		jp.setLayout(flow);
		Dimension d = new Dimension(100, 910);
		jp.setPreferredSize(d);
		jp.setBackground(Color.GREEN);
		JLabel jsl_place = new JLabel();
		Dimension dl = new Dimension(100,300);
		jsl_place.setPreferredSize(dl);
		Dimension db = new Dimension(80, 26);
		Font fb = new Font("宋体",Font.PLAIN, 11);
		JButton jsb_start = new JButton("开始游戏");
		jsb_start.setFont(fb);
		jsb_start.setPreferredSize(db);
		JButton jsb_pause = new JButton("暂停游戏");
		jsb_pause.setFont(fb);
		jsb_pause.setPreferredSize(db);
		JButton jsb_continue = new JButton("继续游戏");
		jsb_continue.setFont(fb);
		jsb_continue.setPreferredSize(db);
		JButton jsb_exit = new JButton("停止游戏");
		jsb_exit.setFont(fb);
		jsb_exit.setPreferredSize(db);
		jp.add(jsl_place);
		jp.add(jsb_start);
		jp.add(jsb_pause);
		jp.add(jsb_continue);
		jp.add(jsb_exit);
		jsf.getContentPane().add("West", jp);
		jsf.setVisible(true);
		Graphics g = jsf.getGraphics();
		PlaneListener pl = new PlaneListener(g, jsf);
		jsf.addMouseListener(pl);
		jsf.addMouseMotionListener(pl);
		jsb_start.addActionListener(pl);
		jsb_pause.addActionListener(pl);
		jsb_continue.addActionListener(pl);
		jsb_exit.addActionListener(pl);
	}
}

–PlaneListener.java–

package com.antony.PlaneBattle0916;

import java.awt.Graphics;
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 java.util.ArrayList;

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

public class PlaneListener extends MouseAdapter implements ActionListener {
	private Graphics g;
	private JFrame jsf;
	private ArrayList<StoreThings> things = new ArrayList<StoreThings>();
	private ShowThread st = new ShowThread(g, jsf, things);
	private MyPlaneThread mpt = new MyPlaneThread(jsf, things, g);
	private EnemyThread et = new EnemyThread(g, jsf, things);

	public PlaneListener(Graphics g, JFrame jsf) {
		this.g = g;
		this.jsf = jsf;
		st = new ShowThread(g, jsf, things);
		mpt = new MyPlaneThread(jsf, things, g);
		et = new EnemyThread(g, jsf, things);
		Image BackGround = new ImageIcon(this.getClass().getResource("BackGround.jpg")).getImage();
		g.drawImage(BackGround, 100, 0, jsf.getWidth(), jsf.getHeight(), jsf);
	}

	public void mouseMoved(MouseEvent e) {
		int x = e.getX();
		int y = e.getY();
		for (int i = 0; i < things.size(); i++) {
			StoreThings temp = things.get(i);
			if (x < 145) {
				x = 145;
			}
			if (temp.getType().equals("m_p")) {
				temp.setX(x - 45);
				temp.setY(y - 45);
			}
		}
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		String BT = e.getActionCommand();
		switch (BT) {
		case "开始游戏":
			if (!(mpt.isAlive() || st.isAlive() || st.isAlive())) {
				mpt.start();
				et.start();
				st.start();
			}
			things.removeAll(things);
			Image image = new ImageIcon(this.getClass().getResource("MyPlane.png")).getImage();
			StoreThings sts = new StoreThings(image, (jsf.getWidth() - 90) / 2, jsf.getHeight() - 90, 90, 90, 0, g, "m_p",
					jsf, things);
			things.add(sts);
			break;
		case "暂停游戏":
			st.setPause(false);
			mpt.setPause(false);
			et.setPause(false);
			break;
		case "继续游戏":
			st.setPause(true);
			mpt.setPause(true);
			et.setPause(true);
			break;
		case "停止游戏":
			System.exit(0);
			break;
		}
	}
}

–StoreThings.java–

package com.antony.PlaneBattle0916;

import java.awt.Graphics;
import java.awt.Image;
import java.util.ArrayList;

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

public class StoreThings {
	private int x, y, width, heigth;
	private Graphics g;
	private Image image;
	private String type;
	private JFrame jsf;
	private int speed = 0;
	private ArrayList<StoreThings> things;

	public StoreThings(Image image, int x, int y, int width, int heigth, int speed, Graphics g, String type, JFrame jsf,
			ArrayList<StoreThings> things) {
		this.image = image;
		this.x = x;
		this.y = y;
		this.width = width;
		this.heigth = heigth;
		this.speed = speed;
		this.g = g;
		this.type = type;
		this.jsf = jsf;
		this.things = things;
	}

	public void crash(StoreThings st) {
		if (st.getType().equals("e_p")) {
			for (int i = 0; i < things.size(); i++) {
				StoreThings temp = things.get(i);
				if (temp.getType().equals("m_b")) {
					double cx = temp.getX() - st.getX();
					double cy = temp.getY() - st.getY();
					double cw = temp.getWidth() + st.getWidth();
					if (Math.sqrt(cx * cx + cy * cy) <= cw / 2) {
						things.remove(st);
					}
				}
			}
		}

		if (st.getType().equals("m_p")) {
			for (int i = 0; i < things.size(); i++) {
				StoreThings temp = things.get(i);
				if (temp.getType().equals("e_b")) {
					double cx = temp.getX() - st.getX();
					double cy = temp.getY() - st.getY();
					double cw = temp.getWidth() + st.getWidth()-40;
					if (Math.sqrt(cx * cx + cy * cy) <= cw / 2) {
						things.remove(st);
						JOptionPane.showMessageDialog(null, "玩家死亡,游戏结束!");
						System.exit(0);
					}
				}
			}
		}
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getWidth() {
		return width;
	}

	public void setY(int y) {
		this.y = y;
	}

	public int getX() {
		return x;
	}

	public int getY() {
		return y;
	}

	public String getType() {
		return type;
	}

	public int getSpeed() {
		return speed;
	}

	public void setSpeed(int speed) {
		this.speed = speed;
	}

	public void showThings() {
		for (int i = 0; i < things.size(); i++) {
			StoreThings temp = things.get(i);
			crash(temp);
		}
		g.drawImage(image, x, y, width, heigth, jsf);
	}
}

–EnemyThread.java–

package com.antony.PlaneBattle0916;

import java.awt.Graphics;
import java.awt.Image;
import java.util.ArrayList;
import java.util.Random;

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

public class EnemyThread extends Thread {
	private int x, y = 0;
	private Graphics g;
	private JFrame jsf;
	private ArrayList<StoreThings> things;
	private Random rand = new Random();
	private boolean start = true;
	private boolean pause = true;

	public EnemyThread(Graphics g, JFrame jsf, ArrayList<StoreThings> things) {
		this.g = g;
		this.jsf = jsf;
		this.things = things;
	}
	
	public void setStart(boolean start){
		this.start = start;
	}
	
	public void setPause(boolean pause){
		this.pause =pause;
	}

	public void run() {
		while (start) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if (pause) {
				x = 100 + rand.nextInt(jsf.getWidth());
				Image image = new ImageIcon(this.getClass().getResource("EnemyPlane.png")).getImage();
				StoreThings st = new StoreThings(image, x, y, 80, 80, 10, g, "e_p", jsf, things);
				things.add(st);
				image = new ImageIcon(this.getClass().getResource("bullet1.png")).getImage();
				for (int i = 0; i < things.size(); i++) {
					StoreThings temp = things.get(i);
					if (temp.getType().equals("e_p")) {
						StoreThings Bullet = new StoreThings(image, temp.getX() + 28, temp.getY() + 40, 25, 25, 20, g,
								"e_b", jsf, things);
						things.add(Bullet);
					}
				}
			}
		}
	}
}

–MyPlaneThread.java–

package com.antony.PlaneBattle0916;

import java.awt.Graphics;
import java.awt.Image;
import java.util.ArrayList;

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

public class MyPlaneThread extends Thread {
	private boolean start = true;
	private JFrame jsf;
	private ArrayList<StoreThings> things;
	private Image image;
	private Graphics g;
	private boolean pause = true;

	public MyPlaneThread(JFrame jsf, ArrayList<StoreThings> things, Graphics g) {
		this.jsf = jsf;
		this.things = things;
		this.g = g;
		image = new ImageIcon(this.getClass().getResource("bullet2.png")).getImage();
	}
	
	public void setStart(boolean start){
		this.start = start;
	}
	
	public void setPause(boolean pause){
		this.pause =pause;
	}

	public void run() {
		while (start) {
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if (pause) {
				for (int i = 0; i < things.size(); i++) {
					StoreThings temp = things.get(i);
					if (temp.getType().equals("m_p")) {
						StoreThings Bullet = new StoreThings(image, temp.getX() + 31, temp.getY(), 30, 30, -40, g,
								"m_b", jsf, things);
						things.add(Bullet);
					}
				}
			}
		}
	}
}

–ShowThread.java–

package com.antony.PlaneBattle0916;

import java.awt.Graphics;
import java.awt.Image;
import java.util.ArrayList;

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

public class ShowThread extends Thread {
	private Graphics g;
	private Image BackGround = new ImageIcon(this.getClass().getResource("BackGround.jpg")).getImage();
	private JFrame jsf;
	private boolean start = true;
	private boolean pause = true;
	private ArrayList<StoreThings> things;
	
	public ShowThread(Graphics g, JFrame jsf, ArrayList<StoreThings> things) {
		this.g = g;
		this.jsf = jsf;
		this.things = things;
	}
	
	public void setStart(boolean start){
		this.start = start;
	}
	
	public void setPause(boolean pause){
		this.pause =pause;
	}

	public void run() {
		while (start) {
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if (pause) {
				g.drawImage(BackGround, 100, 0, jsf.getWidth(), jsf.getHeight(), jsf);
				for (int i = 0; i < things.size(); i++) {
					StoreThings temp = things.get(i);
					temp.showThings();
					temp.setY(temp.getY()+temp.getSpeed());
				}
			}
		}
	}
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值