简易版打飞机

学得线程后应该就可以进行“雷霆战机”的制作了,这个拖了好久了。
首先进行界面设计,如图设计:
[img]http://dl2.iteye.com/upload/attachment/0106/5571/ac37c6ad-1b87-3015-b971-934dc8d3e07f.png[/img]
主要使用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时各个线程要确定关闭。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值