基于Java的飞机大战游戏开发详解|纯干活,有代码

 

设计思路与技术架构

我将设计一个基于Java Swing的飞机大战游戏,实现玩家控制飞机移动、发射子弹,敌方飞机自动生成,碰撞检测以及计分系统等功能。整个游戏采用面向对象的思想设计,使用MVC架构模式:

  • 模型(Model):游戏核心逻辑(飞机、子弹、碰撞等)
  • 视图(View):游戏渲染与用户界面(Swing组件)
  • 控制器(Controller):用户输入处理(键盘事件)

主要类设计

  1. PlaneWarGame - 游戏主框架
  2. GamePanel - 游戏画布
  3. Player - 玩家飞机类
  4. Enemy - 敌机类
  5. Bullet - 子弹类
  6. Explosion - 爆炸效果类

完整代码实现

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;

// 游戏主类
public class PlaneWarGame extends JFrame {
    private GamePanel gamePanel;

    public PlaneWarGame() {
        setTitle("Java飞机大战");
        setSize(800, 600);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setResizable(false);
        
        gamePanel = new GamePanel();
        add(gamePanel);
        
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(PlaneWarGame::new);
    }
}

// 游戏主画板
class GamePanel extends JPanel implements KeyListener, ActionListener {
    private Player player;
    private List enemies;
    private List playerBullets;
    private List explosions;
    private Timer gameTimer;
    private Random random;
    private int score = 0;
    private boolean gameRunning = true;
    private Font gameFont = new Font("Arial", Font.BOLD, 24);
    
    public GamePanel() {
        setFocusable(true);
        addKeyListener(this);
        setBackground(new Color(0, 0, 30));
        
        random = new Random();
        player = new Player(400, 500);
        enemies = new ArrayList<>();
        playerBullets = new ArrayList<>();
        explosions = new ArrayList<>();
        
        gameTimer = new Timer(16, this); // 约60FPS
        gameTimer.start();
        
        // 初始创建敌机
        for (int i = 0; i < 5; i++) {
            spawnEnemy();
        }
    }
    
    // 生成敌机
    private void spawnEnemy() {
        int x = random.nextInt(getWidth() - 50);
        int y = random.nextInt(300) - 400;
        enemies.add(new Enemy(x, y));
    }
    
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        
        // 绘制星空背景
        drawStarBackground(g);
        
        // 绘制玩家飞机
        player.draw(g);
        
        // 绘制敌机
        for (Enemy enemy : enemies) {
            enemy.draw(g);
        }
        
        // 绘制子弹
        for (Bullet bullet : playerBullets) {
            bullet.draw(g);
        }
        
        // 绘制爆炸效果
        for (Explosion explosion : explosions) {
            explosion.draw(g);
        }
        
        // 绘制分数和状态
        drawGameInfo(g);
        
        // 游戏结束画面
        if (!gameRunning) {
            drawGameOver(g);
        }
    }
    
    private void drawStarBackground(Graphics g) {
        g.setColor(Color.WHITE);
        for (int i = 0; i < 100; i++) {
            int x = random.nextInt(getWidth());
            int y = random.nextInt(getHeight());
            int size = random.nextInt(3) + 1;
            g.fillOval(x, y, size, size);
        }
    }
    
    private void drawGameInfo(Graphics g) {
        g.setColor(Color.WHITE);
        g.setFont(gameFont);
        g.drawString("得分: " + score, 20, 30);
        g.drawString("生命: " + player.getHealth(), 20, 60);
    }
    
    private void drawGameOver(Graphics g) {
        g.setColor(new Color(200, 0, 0, 150));
        g.fillRect(0, 0, getWidth(), getHeight());
        
        g.setColor(Color.WHITE);
        g.setFont(new Font("Arial", Font.BOLD, 48));
        String gameOverText = "游戏结束";
        int textWidth = g.getFontMetrics().stringWidth(gameOverText);
        g.drawString(gameOverText, getWidth()/2 - textWidth/2, getHeight()/2 - 30);
        
        g.setFont(gameFont);
        g.drawString("最终得分: " + score, getWidth()/2 - 80, getHeight()/2 + 30);
        g.drawString("按R键重新开始", getWidth()/2 - 80, getHeight()/2 + 70);
    }
    
    @Override
    public void actionPerformed(ActionEvent e) {
        if (gameRunning) {
            // 玩家移动
            player.move();
            
            // 敌机移动和生成
            Iterator enemyIterator = enemies.iterator();
            while (enemyIterator.hasNext()) {
                Enemy enemy = enemyIterator.next();
                enemy.move();
                
                // 检查玩家碰撞
                if (player.checkCollision(enemy)) {
                    player.hit();
                    explosions.add(new Explosion(enemy.getX(), enemy.getY()));
                    enemyIterator.remove();
                    spawnEnemy();
                }
                
                // 超出屏幕检测
                if (enemy.getY() > getHeight()) {
                    enemyIterator.remove();
                    spawnEnemy();
                }
            }
            
            // 子弹移动
            Iterator bulletIterator = playerBullets.iterator();
            while (bulletIterator.hasNext()) {
                Bullet bullet = bulletIterator.next();
                bullet.move();
                
                // 子弹碰撞检测
                enemyIterator = enemies.iterator();
                boolean bulletHit = false;
                while (enemyIterator.hasNext() && !bulletHit) {
                    Enemy enemy = enemyIterator.next();
                    if (bullet.checkCollision(enemy)) {
                        explosions.add(new Explosion(enemy.getX(), enemy.getY()));
                        enemyIterator.remove();
                        bulletHit = true;
                        score += 10;
                        spawnEnemy();
                    }
                }
                
                // 移除超出屏幕的子弹
                if (bullet.getY() < 0 || bulletHit) {
                    bulletIterator.remove();
                }
            }
            
            // 更新爆炸效果
            Iterator explosionIterator = explosions.iterator();
            while (explosionIterator.hasNext()) {
                Explosion explosion = explosionIterator.next();
                if (explosion.update()) {
                    explosionIterator.remove();
                }
            }
            
            // 随机生成新敌机
            if (random.nextInt(100) < 2) {
                spawnEnemy();
            }
            
            // 游戏结束检查
            if (player.getHealth() <= 0) {
                gameRunning = false;
            }
        }
        
        repaint();
    }
    
    @Override
    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();
        
        if (gameRunning) {
            switch (key) {
                case KeyEvent.VK_LEFT:
                    player.setMoveLeft(true);
                    break;
                case KeyEvent.VK_RIGHT:
                    player.setMoveRight(true);
                    break;
                case KeyEvent.VK_UP:
                    player.setMoveUp(true);
                    break;
                case KeyEvent.VK_DOWN:
                    player.setMoveDown(true);
                    break;
                case KeyEvent.VK_SPACE:
                    player.fire(playerBullets);
                    break;
            }
        } else if (key == KeyEvent.VK_R) {
            restartGame();
        }
    }
    
    @Override
    public void keyReleased(KeyEvent e) {
        int key = e.getKeyCode();
        
        switch (key) {
            case KeyEvent.VK_LEFT:
                player.setMoveLeft(false);
                break;
            case KeyEvent.VK_RIGHT:
                player.setMoveRight(false);
                break;
            case KeyEvent.VK_UP:
                player.setMoveUp(false);
                break;
            case KeyEvent.VK_DOWN:
                player.setMoveDown(false);
                break;
        }
    }
    
    private void restartGame() {
        player = new Player(400, 500);
        enemies.clear();
        playerBullets.clear();
        explosions.clear();
        score = 0;
        
        for (int i = 0; i < 5; i++) {
            spawnEnemy();
        }
        
        gameRunning = true;
    }
    
    @Override
    public void keyTyped(KeyEvent e) {}
}

// 玩家飞机类
class Player {
    private int x, y;
    private int width = 60;
    private int height = 40;
    private int speed = 5;
    private int health = 100;
    private boolean moveLeft, moveRight, moveUp, moveDown;
    private long lastFireTime;
    private int fireDelay = 300; // 发射间隔(ms)
    private Color color = new Color(0, 200, 255);
    
    public Player(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    public void draw(Graphics g) {
        // 绘制飞机主体
        g.setColor(color);
        
        // 机身
        g.fillRect(x - width/2, y - height/2, width, height/3);
        g.fillRect(x - width/3, y - height/2, width*2/3, height);
        
        // 机翼
        Polygon leftWing = new Polygon();
        leftWing.addPoint(x - width/2, y - height/6);
        leftWing.addPoint(x - width/2, y + height/6);
        leftWing.addPoint(x - width/3, y);
        g.fillPolygon(leftWing);
        
        Polygon rightWing = new Polygon();
        rightWing.addPoint(x + width/2, y - height/6);
        rightWing.addPoint(x + width/2, y + height/6);
        rightWing.addPoint(x + width/3, y);
        g.fillPolygon(rightWing);
        
        // 驾驶舱
        g.setColor(Color.CYAN);
        g.fillOval(x - width/8, y - height/4, width/4, width/4);
    }
    
    public void move() {
        if (moveLeft) x = Math.max(x - speed, width/2);
        if (moveRight) x = Math.min(x + speed, 800 - width/2);
        if (moveUp) y = Math.max(y - speed, height/2);
        if (moveDown) y = Math.min(y + speed, 600 - height/2);
    }
    
    public void fire(List bullets) {
        long currentTime = System.currentTimeMillis();
        if (currentTime - lastFireTime > fireDelay) {
            bullets.add(new Bullet(x, y - height/2, 0, -8));
            lastFireTime = currentTime;
        }
    }
    
    public boolean checkCollision(Enemy enemy) {
        int distX = Math.abs(x - enemy.getX());
        int distY = Math.abs(y - enemy.getY());
        return distX < (width/2 + enemy.getWidth()/2) && 
               distY < (height/2 + enemy.getHeight()/2);
    }
    
    public void hit() {
        health -= 25;
    }
    
    public void setMoveLeft(boolean moveLeft) {
        this.moveLeft = moveLeft;
    }
    
    public void setMoveRight(boolean moveRight) {
        this.moveRight = moveRight;
    }
    
    public void setMoveUp(boolean moveUp) {
        this.moveUp = moveUp;
    }
    
    public void setMoveDown(boolean moveDown) {
        this.moveDown = moveDown;
    }
    
    public int getHealth() {
        return health;
    }
}

// 敌机类
class Enemy {
    private int x, y;
    private int width = 50;
    private int height = 30;
    private int speedY = 3;
    private int speedX;
    private Color color;
    
    public Enemy(int x, int y) {
        this.x = x;
        this.y = y;
        speedX = (new Random().nextBoolean() ? 1 : -1) * (new Random().nextInt(2) + 1);
        color = new Color(255, 100 + new Random().nextInt(100), 0);
    }
    
    public void draw(Graphics g) {
        g.setColor(color);
        
        // 机身
        g.fillRect(x - width/2, y - height/2, width, height/2);
        
        // 机翼
        g.fillPolygon(new int[]{x - width/2, x - width/2, x}, 
                     new int[]{y - height/3, y + height/3, y}, 3);
        g.fillPolygon(new int[]{x + width/2, x + width/2, x}, 
                     new int[]{y - height/3, y + height/3, y}, 3);
        
        // 驾驶舱
        g.setColor(Color.RED);
        g.fillOval(x - width/8, y - height/4, width/4, width/4);
    }
    
    public void move() {
        y += speedY;
        x += speedX;
        
        // 碰到边界反弹
        if (x < width/2 || x > 800 - width/2) {
            speedX = -speedX;
        }
    }
    
    public int getX() {
        return x;
    }
    
    public int getY() {
        return y;
    }
    
    public int getWidth() {
        return width;
    }
    
    public int getHeight() {
        return height;
    }
}

// 子弹类
class Bullet {
    private int x, y;
    private int width = 4;
    private int height = 12;
    private int speedX, speedY;
    private Color color = Color.YELLOW;
    
    public Bullet(int x, int y, int speedX, int speedY) {
        this.x = x;
        this.y = y;
        this.speedX = speedX;
        this.speedY = speedY;
    }
    
    public void draw(Graphics g) {
        g.setColor(color);
        g.fillRect(x - width/2, y, width, height);
        
        // 添加发光效果
        g.setColor(Color.WHITE);
        g.fillRect(x - width/2 + 1, y + 1, width - 2, height - 2);
    }
    
    public void move() {
        x += speedX;
        y += speedY;
    }
    
    public boolean checkCollision(Enemy enemy) {
        int distX = Math.abs(x - enemy.getX());
        int distY = Math.abs(y - enemy.getY());
        return distX < (width/2 + enemy.getWidth()/2) && 
               distY < (height/2 + enemy.getHeight()/2);
    }
    
    public int getY() {
        return y;
    }
}

// 爆炸效果类
class Explosion {
    private int x, y;
    private int maxRadius = 40;
    private int currentRadius = 5;
    private int growthRate = 3;
    private Color color = new Color(255, 150, 0, 200);
    
    public Explosion(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    public boolean update() {
        currentRadius += growthRate;
        return currentRadius >= maxRadius;
    }
    
    public void draw(Graphics g) {
        g.setColor(color);
        g.fillOval(x - currentRadius, y - currentRadius, 
                  currentRadius * 2, currentRadius * 2);
    }
}

核心技术解析

1. 游戏循环与动画

使用Timer类实现游戏主循环(约60FPS):

gameTimer = new Timer(16, this); // 约60FPS
gameTimer.start();

2. 玩家控制与移动

采用状态机模式处理玩家移动:

public void move() {
    if (moveLeft) x = Math.max(x - speed, width/2);
    if (moveRight) x = Math.min(x + speed, 800 - width/2);
    if (moveUp) y = Math.max(y - speed, height/2);
    if (moveDown) y = Math.min(y + speed, 600 - height/2);
}

3. 碰撞检测系统

使用简单的矩形碰撞检测算法:

public boolean checkCollision(Enemy enemy) {
    int distX = Math.abs(x - enemy.getX());
    int distY = Math.abs(y - enemy.getY());
    return distX < (width/2 + enemy.getWidth()/2) && 
           distY < (height/2 + enemy.getHeight()/2);
}

4. 对象池管理

使用Java集合框架高效管理游戏对象:

private List enemies = new ArrayList<>();
private List playerBullets = new ArrayList<>();
private List explosions = new ArrayList<>();

5. 粒子效果实现

爆炸效果使用逐渐放大的圆形:

public void draw(Graphics g) {
    g.setColor(color);
    g.fillOval(x - currentRadius, y - currentRadius, 
              currentRadius * 2, currentRadius * 2);
}

6. 键盘事件处理

实现KeyListener接口处理用户输入:

@Override
public void keyPressed(KeyEvent e) {
    // 处理键盘按下事件
}

@Override
public void keyReleased(KeyEvent e) {
    // 处理键盘释放事件
}

游戏功能说明

  1. 玩家控制:
  • 方向键控制飞机移动
  • 空格键发射子弹
  • 游戏结束按R键重新开始
  1. 敌机系统:
  • 随机生成不同飞行轨迹的敌机
  • 碰到屏幕边界反弹
  1. 计分系统:
  • 击落敌机获得10分
  • 屏幕上显示当前分数和生命值
  1. 生命系统:
  • 被敌机撞击损失25点生命值
  • 生命值为0时游戏结束
  1. 视觉特效:
  • 星空背景
  • 子弹发光效果
  • 圆形爆炸动画

性能优化建议

  1. 对象池技术:重用不再使用的对象(如子弹、爆炸效果)
  2. 空间分区:对游戏对象进行空间划分,优化碰撞检测
  3. 双缓冲技术:减少画面闪烁(Swing默认已实现)
  4. 碰撞优化:使用距离平方代替开方运算
  5. 多线程:可将游戏逻辑与渲染分开至不同线程

扩展方向

  1. 添加多种武器系统和道具
  2. 实现关卡系统和BOSS战
  3. 添加音效和背景音乐
  4. 实现高分榜存储功能
  5. 添加敌人弹幕系统
  6. 实现3D渲染效果

这个飞机大战游戏展示了Java在2D游戏开发中的强大能力,代码设计遵循了面向对象原则,并包含了实用的游戏开发技术。玩家可以通过这个项目学习游戏循环、事件处理、碰撞检测等核心游戏开发概念。

致每个在宿舍挑灯夜战的你:

当简历石沉大海,当笔试频频受挫,请记住—— 大厂要的不是完美的毕业生,而是能解决问题的战士

今晚你刷的每一道场景题,都在增加未来工卡上的含金量 此刻的行动,将决定你站在西二旗还是城中村

【0秒行动点→ si我发送“666”,拿下你的Offer通行证】&nbsp;

(前50名可获我1v1专属答疑,职业规划一次)

编辑

编辑

编辑

编辑

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值