目前版本的飞机大战游戏由五个类构成,分别是:GameUI类(主界面窗体类),Fighter类(敌我飞机类),GameListener类(键盘监听类), MainThread类(主线程类),Bullet类(子弹类)
下面分为五个类讲解:
1.GameUI类
此类主要作用在于显示游戏的主界面,所以继承JFrame类。这里采用重写paint方法,使用缓冲图片将绘制内容一次性画到窗体上
java
package 多线程游戏0321;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyListener;
/**
* @author jinhuang
* @date 2026/3/21 19:44
* @description
*/
public class GameUI extends JFrame{
// 全局监听器,方便线程访问
GameListener listener = new GameListener();
MainThread thread;
public GameUI() {
// 1. 窗体设置
this.setTitle("飞机大战");
this.setSize(500, 800);
this.setLocationRelativeTo(null); // 居中
this.setResizable(false);//禁止用户调整窗口大小
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 2. 添加键盘监听器
this.addKeyListener( listener);
// 3. 启动游戏线程
thread = new MainThread(this);
thread.start();
// 4. 显示窗体
this.setVisible(true);
/*Graphics g=this.getGraphics();
g.drawRect(25,25,100,50);
g.setColor(Color.GREEN);
g.fillRect(25,25,thread.myFighter.hp,50);*/
}
// 重写paint方法,使用双缓冲解决闪烁
@Override
public void paint(Graphics g) {
// 创建缓冲图片
Image buffer = createImage(500, 800);
Graphics gBuffer = buffer.getGraphics();
// 在缓冲图片上绘制游戏内容
thread.paintSelf(gBuffer);
// 将缓冲图片一次性绘制到屏幕上
g.drawImage(buffer, 0, 0, this);
}
public static void main(String[] args) {
new GameUI();
}
}
2.Fighter类
此类主要用于引入飞机大战中的形象,以及战机的生成,移动,攻击,被攻击判定,死亡判定等
1\]这里飞机形象采用静态资源块加载.在类首次加载的时候自动执行
```java
package 多线程游戏0321;
/**
* @author jinhuang
* @date 2026/3/21 19:44
* @description
*/
import java.awt.*;
import java.util.ArrayList;
import java.util.Random;
public class Fighter {
int x, y;
int width = 60;
int height = 60;
int speed;
boolean isEnemy;
int hp = 100;//血量
boolean alive = true;//存活情况
// 敌机专用
static Random random = new Random();
static Image enemyImg;
static Image heroImg;
static {
// 实际使用时请加载图片
enemyImg = Toolkit.getDefaultToolkit().getImage("D:\\练习图片\\image_436466818269426.png");
heroImg = Toolkit.getDefaultToolkit().getImage("D:\\练习图片\\image_051206973203939.png");
}
public Fighter(int x, int y, boolean isEnemy) {
this.x = x;
this.y = y;
this.isEnemy = isEnemy;
this.speed = isEnemy ? 3 : 8; // 敌机慢,我机快
}
public void draw(Graphics g) {
Image currentImg = isEnemy ? enemyImg : heroImg;
if (currentImg != null) {
g.drawImage(currentImg, x, y, width, height, null);
} else {
g.setColor(isEnemy ? Color.GREEN : Color.BLUE);
g.fillRect(x, y, width, height);
g.setColor(Color.WHITE);
g.drawString(isEnemy ? "敌机" : "我机", x+15, y+30);
}
}
// 核心逻辑:移动
public void move(int direction) {
if (isEnemy) {
// 敌机逻辑:自动向下移动
y += speed;
// 敌机出界销毁
if (y > 850) {
alive = false;
}
} else {
// 我方逻辑:键盘控制
if (direction == 1) y -= speed; // 上
if (direction == 2) y += speed; // 下
if (direction == 3) x -= speed; // 左
if (direction == 4) x += speed; // 右
// 边界穿越逻辑
if (x < -width) x = 500; // 从左边出去,右边回来
if (x > 500) x = -width; // 从右边出去,左边回来
if (y < -height) y = 800; // 从上边出去,下边回来
if (y > 800) y = -height; // 从下边出去,上边回来
}
}
// 开火
public Bullet fire() {
if (isEnemy) {
// 敌机随机开火逻辑通常在主线程控制,这里只负责生成
return new Bullet(x + width/2, y + height, true);
} else {
return new Bullet(x + width/2 - 5, y, false);
}
}
// 碰撞检测(矩形碰撞)
public boolean isCollide(Fighter f) {
return (this.x < f.x + f.width && this.x + this.width > f.x &&
this.y < f.y + f.height && this.y + this.height > f.y);
}
public boolean isCollide(Bullet b) {
return (this.x < b.x + b.width && this.x + this.width > b.x &&
this.y < b.y + b.height && this.y + this.height > b.y);
}
}
```
3.GameListener类
事件监听类:
实现键盘监听器,用direction方向指示飞机走向,键盘按下时给direction相应的值,松开时direction重置为0
```java
package 多线程游戏0321;
/**
* @author jinhuang
* @date 2026/3/21 19:47
* @description
*/
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class GameListener implements KeyListener {
// 方向状态:1上, 2下, 3左, 4右
public int direction = 0;
public boolean fire = false;
@Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
switch (key) {
case KeyEvent.VK_W: direction = 1; break;
case KeyEvent.VK_S: direction = 2; break;
case KeyEvent.VK_A: direction = 3; break;
case KeyEvent.VK_D: direction = 4; break;
case KeyEvent.VK_SPACE: fire = true; break;
}
}
@Override
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
// 松开按键时重置方向,避免按键冲突
if (key == KeyEvent.VK_W || key == KeyEvent.VK_S ||
key == KeyEvent.VK_A || key == KeyEvent.VK_D) {
direction = 0;
}
if (key == KeyEvent.VK_SPACE) {
fire = false;
}
}
@Override
public void keyTyped(KeyEvent e) {}
}
```
4.MainThread类
\[1\]:创建己方战机对象,敌方战机数组,子弹数组,定义变量记录击杀数
\[2\]:无限循环的敌机生成数组,每隔1s生成一个
\[3\]:
```java
package 多线程游戏0321;
/**
* @author jinhuang
* @date 2026/3/21 19:47
* @description
*/
import java.awt.*;
import java.util.ArrayList;
import java.util.Iterator;
public class MainThread extends Thread {
GameUI mui;
Fighter myFighter;
ArrayList