简易版打飞机

   学得线程后应该就可以进行“雷霆战机”的制作了,这个拖了好久了。
    首先进行界面设计,如图设计:
                   
   主要使用JFrame、JPanel和JButton组件,及添加一些监听器。
   
package 最_雷霆战机;

/**
 * 游戏界面设计
 * @author asus
 */

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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

public class LeidianUI extends JFrame {

	public static void main(String[] arg) {
		new LeidianUI().initUI();
	}

	public void initUI() {
		this.setTitle("雷电");
		this.setSize(400, 600);
		this.setResizable(false);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		this.setLayout(new BorderLayout());

		// 添加游戏界面
		final GamePanel jp1 = new GamePanel();
		jp1.setPreferredSize(new Dimension(380, 500));
		jp1.setBackground(Color.BLACK);

		// 添加操作界面
		JPanel jp2 = new JPanel();
		jp2.setBackground(Color.WHITE);

		this.add(jp1, BorderLayout.NORTH);
		this.add(jp2, BorderLayout.CENTER);

		final JButton start = new JButton("start");
		final JButton pause = new JButton("pause");
		final JButton over = new JButton("over");

		pause.setEnabled(false);
		over.setEnabled(false);

		jp2.add(start);
		jp2.add(pause);
		jp2.add(over);

		this.setVisible(true);

		ActionListener alis = new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				String s = e.getActionCommand();
				if (s.equals("start")) {
					jp1.initGamePanel(15);

					// 禁用开始按钮,其他按钮启动
					start.setEnabled(false);
					pause.setEnabled(true);
					over.setEnabled(true);
				} else if (s.equals("pause")) {

					pause.setText("continue");

					GamePanel.pauseThread();
				} else if (s.equals("continue")) {

					pause.setText("pause");

					GamePanel.continueThread();
				} else if (s.equals("over")) {

					pause.setText("pause");

					start.setEnabled(true);
					pause.setEnabled(false);
					over.setEnabled(false);

					// 停止敌机
					for (int i = 0; i < jp1.airList.size(); i++) {
						jp1.airList.get(i).stopThread();
					}
					jp1.airList.clear();

					// 停掉子弹线程
					// 停止敌机
					for (int i = 0; i < jp1.myAir.bulletList.size(); i++) {
						jp1.myAir.bulletList.get(i).stopThread();
					}
					jp1.myAir.bulletList.clear();
					// 自己的飞机
					jp1.myAir.stopThread();
					jp1.myAir = null;

				}

			}

		};

		start.addActionListener(alis);
		pause.addActionListener(alis);
		over.addActionListener(alis);

		start.setFocusable(false);
		pause.setFocusable(false);
		over.setFocusable(false);
		
		//添加键盘监听器(GamePanel实现了KeyListener的接口,所以他就是一个监听器)
		this.addKeyListener(jp1);

	}

}


    将一个JPanel写成一个监听器,implements KeyListener。
              
package 最_雷霆战机;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;

import javax.swing.JPanel;

/***
 * 重写paint方法绘制
 * 
 * @author asus
 * 
 */
public class GamePanel extends JPanel implements KeyListener {

	public static boolean isRun = true; // 游戏是否终止

	ArrayList<EAir> airList = new ArrayList<EAir>();// 敌机对象个体存储的动态数组

	MyAir myAir;

	private BackgroundThread bgThread;

	public void initGamePanel(int num) {

		myAir = new MyAir(this);
		myAir.start();

		for (int i = 0; i < num; i++) {
			EAir air = new EAir(this);
			air.start();
			airList.add(air);
		}

	}

	@Override
	public void paint(Graphics g) {
		super.paint(g);

		if (bgThread != null) {
			bgThread.draw(g);
		}

		// 绘制战机
		if (myAir != null) {
			if (myAir.isLive) {
				myAir.draw(g);
			}
			for (int i = 0; i < myAir.bulletList.size(); i++) {
				BulletThread but = myAir.bulletList.get(i);
				// 如果活着就绘制,否则就删除掉
				if (but.isLive) {
					but.draw(g);
				} else {
					myAir.bulletList.remove(i);
				}
			}
		}

		// 绘制敌机
		for (int i = 0; i < airList.size(); i++) {

			EAir air = airList.get(i);
			if (air.isLive) {
				air.draw(g);
			} else {
				airList.remove(i);
			}

		}
		this.repaint();
	}

	@Override
	public void keyTyped(KeyEvent e) {

	}

	public static void pauseThread() {
		isRun = false;
	}

	public static void continueThread() {
		isRun = true;
	}

	@Override
	public void keyPressed(KeyEvent e) {
		int code = e.getKeyCode();
		switch (code) {
		case KeyEvent.VK_LEFT:
			MyAir.left = true;
			break;
		case KeyEvent.VK_RIGHT:
			MyAir.right = true;
			break;
		case KeyEvent.VK_UP:
			MyAir.up = true;
			break;
		case KeyEvent.VK_DOWN:
			MyAir.down = true;
			break;
		}

	}

	@Override
	public void keyReleased(KeyEvent e) {
		int code = e.getKeyCode();
		switch (code) {
		case KeyEvent.VK_LEFT:
			MyAir.left = false;
			break;
		case KeyEvent.VK_RIGHT:
			MyAir.right = false;
			break;
		case KeyEvent.VK_UP:
			MyAir.up = false;
			break;
		case KeyEvent.VK_DOWN:
			MyAir.down = false;
			break;
		}

	}

}


    新建自己的战机的类MyAir,作为一个线程。
package 最_雷霆战机;

/**
 * 
 * 战机的类
 * 
 * @author asus
 */
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.net.URL;
import java.util.ArrayList;

import javax.swing.ImageIcon;

public class MyAir extends Thread {

	// 飞机属性
	int x = 10, y = 10;
	int width = 70;
	int height = 70;
	int xc = 2;
	int yc = 2;
	int blood = 20;

	Image img;

	private int panelWidth;
	private int panelHeight;
	private GamePanel panel;

	boolean isLive = true;// 线程是否活着

	// 方向指令
	public static boolean up, down, left, right;

	// 装子弹的队列
	ArrayList<BulletThread> bulletList = new ArrayList<BulletThread>();

	public MyAir(GamePanel gamePanel) {

		this.panel = gamePanel;
		Dimension dim = gamePanel.getPreferredSize();
		panelWidth = dim.width;
		panelHeight = dim.height;

		// 获取战机图片
		URL url = EAir.class.getResource("feiji.png");
		img = new ImageIcon(url).getImage();

		x = (panelWidth - width) / 2;
		y = panelHeight - height;

	}

	// 绘制战机
	public void draw(Graphics g) {

		g.drawImage(img, x, y, width, height, null);

	}

	public void stopThread() {
		isLive = false;
	}

	public void fire() {
		BulletThread bullet = new BulletThread(panel, x + width / 2, y);
		bullet.start();
		bulletList.add(bullet);
	}

	@Override
	public void run() {

		while (isLive) {
			if (GamePanel.isRun) {

				if (left) {
					xc = -2;
				} else if (right) {
					xc = 2;
				} else {
					xc = 0;
				}

				if (up) {
					yc = -2;
				} else if (down) {
					yc = 2;
				} else {
					yc = 0;
				}

				x += xc;
				y += yc;

				// 战机不出边界
				if (x <= 0) {
					x = 0;
				}

				if (y <= 0) {
					y = 0;
				}

				if (x >= panelWidth - width) {
					x = panelWidth - width;
				}

				if (y >= panelHeight - height) {
					y = panelHeight - height;
				}

			}

			num++;

			if (num % 20 == 0) {
				this.fire();
			}
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	int num = 0;
}

     新建敌机类,extends Thread。存储到GamePanel中的动态数组里。
package 最_雷霆战机;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.net.URL;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.ImageIcon;

/**
 * 敌机的属性
 * 
 * @author asus
 * 
 */
public class EAir extends Thread {

	// 敌机
	int x = 10, y = 10;
	int width = 50, height = 50;
	int xc = 2, yc = 2;
	int blood = 5;

	Image img;

	Random rd = new Random();

	int[] c = { 5, 4, 3, 2, 1 };

	ArrayList<EAir> airList;

	private int panelWidth;
	private int panelHeight;
	private GamePanel panel;

	boolean isLive = true; // 线程是否还存在
	// static boolean isRun = true; // 线程是否还在执行逻辑处理-->进行数据的交换

	public EAir(GamePanel gamePanel) {
		
		this.panel = gamePanel;
		this.airList = gamePanel.airList;
		Dimension dim = gamePanel.getPreferredSize();
		panelWidth = dim.width;
		panelHeight = dim.height;

		URL url = EAir.class.getResource("diji.png");
		img = new ImageIcon(url).getImage();

		initDiji();
	}

	// 敌机动作命令初始化
	public void initDiji() {

		yc = c[rd.nextInt(c.length)];

		x = rd.nextInt(panelWidth - width);

		y = -height;

	}

	// 绘制自身
	public void draw(Graphics g) {

		g.drawImage(img, x, y, width, height, null);

	}

	@Override
	public void run() {
		while (isLive) {
			
			check();
			
			if (GamePanel.isRun) {
				if (y >= panelHeight - height) {
					initDiji();
				}

				y += yc;
			}
			try {
				Thread.sleep(20);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public void stopThread() {
		isLive = false;
	}
	
	// 检测两个小球是否相碰
	public void check() {
		// 获得玩家飞机
		MyAir myAir = panel.myAir;
		if (myAir != null) {
			// 检测玩家飞机和敌机是否碰撞
			// 计算敌机的圆心
			int xa = this.x + this.width / 2;
			int ya = this.y + this.width / 2;

			// 计算玩家的圆心
			int xb = myAir.x + myAir.width / 2;
			int yb = myAir.y + myAir.width / 2;

			// 计算斜边
			int c2 = Math.abs(xa - xb) * Math.abs(xa - xb) + Math.abs(ya - yb)
					* Math.abs(ya - yb);

			// 计算半径之和
			int r = this.width / 2 + this.width / 2;
			// 碰撞到了
			if (c2 <= r * r) {
				if (this.blood < myAir.blood) {
					myAir.blood -= this.blood;
					this.blood = 0;
				} else {
					myAir.stopThread();
				}
				this.stopThread();
			}

			for (int i = 0; i < myAir.bulletList.size(); i++) {
				// 取出一个子弹
				BulletThread bullet = myAir.bulletList.get(i);

				int xc = bullet.x + bullet.width / 2;
				int yc = bullet.y + bullet.width / 2;

				// 计算斜边
				int c3 = Math.abs(xa - xc) * Math.abs(xa - xc)
						+ Math.abs(ya - yc) * Math.abs(ya - yc);

				// 计算半径之和
				int r3 = this.width / 2 + this.width / 2;
				// 碰撞到了
				if (c3 <= r3 * r3) {

					this.blood -= bullet.blood;
					bullet.blood = 0;
					if (this.blood <= 0) {
						// 敌机Over
						this.stopThread();
					}
					// 子弹OVer
					bullet.stopThread();
				}

			}
		}
	}

	

}


         设置子弹类,由战机发射子弹。
         
package 最_雷霆战机;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

public class BulletThread extends Thread{

	int x, y;
	int width = 5, height = 5;
	int xc = 0, yc = -5;
	boolean isLive = true;
	int blood = 1;

	int screenWidth, screenHeight;

	public BulletThread(GamePanel gamePanel, int a, int b) {

		Dimension dim = gamePanel.getPreferredSize();
		screenWidth = dim.width;
		screenHeight = dim.height;
		this.x = a - width / 2;
		this.y = b - height;

	}

	public void run() {

		while (isLive) {
			if (GamePanel.isRun) {
				if (y <= -height) {
					stopThread();
				}
				// 子弹于飞出屏幕终止

				x += xc;
				y += yc;

			}
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

	}

	public void stopThread() {
		isLive = false;
	}
	
	public void draw(Graphics g){
		g.setColor(Color.green);
		g.fillOval(x, y, width, height);
	}

}


        注意isRun和isLive是否为静态,这里容易出错。并且over时各个线程要确定关闭。

猜你喜欢

转载自2548540761.iteye.com/blog/2191235