Java课程设计(双人对战游戏)持续更新......

少废话,当然借助了ai,就这么个实力,后续会逐渐完善......

考虑添加以下功能:

选将,选图,技能,天赋,道具,防反,反重力,物理反弹,击落,计分,粒子效果,打击感加强,陷阱,逃杀......

java 复制代码
package game;

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

public class GameFrame extends JFrame {
    public GameFrame() {
        setTitle("平台射击对战");
        setSize(800, 600);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        add(new GamePanel());
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new GameFrame());
    }
}

class GamePanel extends JPanel implements KeyListener, ActionListener {
    private Player p1, p2;
    private Timer timer;
    private boolean[] keys = new boolean[256];
    private boolean gameOver = false;
    private boolean gameStarted = false;
    private JButton startButton, restartButton, exitButton;
    private List<Platform> platforms = new ArrayList<>();
    private List<Bullet> bullets = new ArrayList<>();

    public GamePanel() {
        setLayout(null);
        setFocusable(true);
        addKeyListener(this);

        // 对称平台布局
        platforms.add(new Platform(150, 350, 200, 20));  // 左平台
        platforms.add(new Platform(300, 250, 200, 20));  // 中央平台
        platforms.add(new Platform(450, 350, 200, 20));  // 右平台

        startButton = createButton("开始游戏", 300, 250);
        restartButton = createButton("重新开始", 300, 300);
        exitButton = createButton("退出游戏", 300, 350);

        restartButton.setVisible(false);
        exitButton.setVisible(false);

        add(startButton);
        add(restartButton);
        add(exitButton);

        startButton.addActionListener(e -> startGame());
        restartButton.addActionListener(e -> restartGame());
        exitButton.addActionListener(e -> System.exit(0));
    }

    private JButton createButton(String text, int x, int y) {
        JButton button = new JButton(text);
        button.setBounds(x, y, 200, 40);
        button.setFocusable(false);
        button.setFont(new Font("微软雅黑", Font.BOLD, 18));
        button.setBackground(new Color(200, 200, 200));
        return button;
    }

    private void startGame() {
        gameStarted = true;
        gameOver = false;
        bullets.clear();
        startButton.setVisible(false);
        restartButton.setVisible(false);
        exitButton.setVisible(false);

        p1 = new Player(100, 400, Color.BLUE, KeyEvent.VK_A, KeyEvent.VK_D, KeyEvent.VK_W, KeyEvent.VK_F);
        p2 = new Player(600, 400, Color.RED, KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT, KeyEvent.VK_UP, KeyEvent.VK_M);

        if (timer != null && timer.isRunning()) {
            timer.stop();
        }
        timer = new Timer(16, this);
        timer.start();
        requestFocusInWindow();
    }

    private void restartGame() {
        gameOver = false;
        gameStarted = false;
        startGame();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (!gameStarted) {
            g.setColor(new Color(30, 30, 30));
            g.fillRect(0, 0, getWidth(), getHeight());
            g.setColor(Color.WHITE);
            g.setFont(new Font("微软雅黑", Font.BOLD, 48));
            g.drawString("平台射击对战", 250, 150);
            return;
        }

        Graphics2D g2d = (Graphics2D) g;
        g2d.setPaint(new GradientPaint(0, 0, new Color(30, 30, 50), 0, 600, new Color(10, 10, 20)));
        g2d.fillRect(0, 0, getWidth(), getHeight());

        g.setColor(new Color(80, 50, 30));
        g.fillRect(0, 450, getWidth(), 150);
        g.setColor(new Color(110, 70, 40));
        for(int i=0; i<getWidth(); i+=30){
            g.fillRect(i, 450, 15, 10);
            g.fillRect(i+15, 460, 15, 10);
        }

        for (Platform platform : platforms) {
            platform.draw(g);
        }

        p1.draw(g);
        p2.draw(g);

        for (Bullet bullet : bullets) {
            bullet.draw(g);
        }

        drawHealthBar(g, p1, 20, 20);
        drawHealthBar(g, p2, getWidth() - 220, 20);

        if (gameOver) {
            g.setColor(new Color(255, 255, 255, 200));
            g.fillRect(0, 0, getWidth(), getHeight());
            g.setColor(Color.BLACK);
            g.setFont(new Font("微软雅黑", Font.BOLD, 48));
            String winner = p1.getHealth() <= 0 ? "红方胜利!" : "蓝方胜利!";
            g.drawString(winner, getWidth()/2 - 120, getHeight()/2);

            restartButton.setVisible(true);
            exitButton.setVisible(true);
        }
    }

    private void drawHealthBar(Graphics g, Player p, int x, int y) {
        g.setColor(Color.BLACK);
        g.fillRect(x, y, 200, 25);
        g.setColor(p.getColor());
        g.fillRect(x + 2, y + 2, (int)(196 * (p.getHealth() / 100.0)), 21);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (!gameOver && gameStarted) {
            handleInput();
            updatePlayers();
            updateBullets();
            checkCollisions();
            checkGameOver();
        }
        repaint();
    }

    private void handleInput() {
        p1.setMovingLeft(keys[p1.getLeftKey()]);
        p1.setMovingRight(keys[p1.getRightKey()]);
        if (keys[p1.getJumpKey()] && p1.isOnGround()) {
            p1.jump();
        }
        if (keys[p1.getAttackKey()] && p1.canAttack()) {
            bullets.add(p1.shoot());
        }

        p2.setMovingLeft(keys[p2.getLeftKey()]);
        p2.setMovingRight(keys[p2.getRightKey()]);
        if (keys[p2.getJumpKey()] && p2.isOnGround()) {
            p2.jump();
        }
        if (keys[p2.getAttackKey()] && p2.canAttack()) {
            bullets.add(p2.shoot());
        }
    }

    private void updatePlayers() {
        p1.update(getWidth(), platforms);
        p2.update(getWidth(), platforms);
    }

    private void updateBullets() {
        List<Bullet> toRemove = new ArrayList<>();
        for (Bullet bullet : bullets) {
            bullet.update();
            if (bullet.x < -10 || bullet.x > getWidth() + 10) {
                toRemove.add(bullet);
            }
        }
        bullets.removeAll(toRemove);
    }

    private void checkCollisions() {
        List<Bullet> toRemove = new ArrayList<>();
        for (Bullet bullet : bullets) {
            for (Platform platform : platforms) {
                if (bullet.hitsPlatform(platform)) {
                    toRemove.add(bullet);
                    break;
                }
            }

            Player target = bullet.shooter == p1 ? p2 : p1;
            if (bullet.hitsPlayer(target)) {
                target.takeDamage(10);
                toRemove.add(bullet);
            }
        }
        bullets.removeAll(toRemove);
    }

    private void checkGameOver() {
        if (p1.getHealth() <= 0 || p2.getHealth() <= 0) {
            gameOver = true;
            timer.stop();
        }
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() < keys.length) {
            keys[e.getKeyCode()] = true;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() < keys.length) {
            keys[e.getKeyCode()] = false;
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {}
}

class Player {
    private static final int GRAVITY = 1;
    private static final int JUMP_FORCE = -15;
    private static final int ATTACK_COOLDOWN = 30;
    private static final int SPEED = 5;
    private static final int BULLET_SPEED = 10;

    private int x, y;
    private int width = 40, height = 80;
    private int dx, dy;
    private int health = 100;
    private Color color;
    private boolean onGround = false;
    private int attackTimer = 0;
    private boolean movingLeft = false;
    private boolean movingRight = false;
    private boolean facingRight = true;
    private int leftKey, rightKey, jumpKey, attackKey;

    public Player(int x, int y, Color color, int leftKey, int rightKey, int jumpKey, int attackKey) {
        this.x = x;
        this.y = y;
        this.color = color;
        this.leftKey = leftKey;
        this.rightKey = rightKey;
        this.jumpKey = jumpKey;
        this.attackKey = attackKey;
    }

    public void update(int screenWidth, List<Platform> platforms) {
        // 处理水平移动
        dx = 0;
        if (movingLeft) {
            dx -= SPEED;
            facingRight = false;
        }
        if (movingRight) {
            dx += SPEED;
            facingRight = true;
        }

        // 保存移动前的坐标
        int xPrev = x;
        x += dx;
        x = Math.max(0, Math.min(screenWidth - width, x));

        // 水平碰撞检测
        Rectangle playerRect = getCollisionBounds();
        for (Platform platform : platforms) {
            Rectangle platformRect = platform.getBounds();
            if (playerRect.intersects(platformRect)) {
                if (dx > 0) { // 向右移动碰撞
                    x = platformRect.x - width;
                } else if (dx < 0) { // 向左移动碰撞
                    x = platformRect.x + platformRect.width;
                }
                break;
            }
        }

        // 处理垂直移动
        dy += GRAVITY;
        int yPrev = y;
        y += dy;

        // 垂直碰撞检测
        boolean isFalling = dy > 0;
        onGround = false;

        if (isFalling) {
            // 下落碰撞检测
            int playerBottomAfter = y + height;
            int playerBottomBefore = yPrev + height;

            Platform landingPlatform = null;
            int highestPlatformY = Integer.MIN_VALUE;

            for (Platform platform : platforms) {
                Rectangle platformRect = platform.getBounds();
                int platformTop = platformRect.y;
                int platformBottom = platformTop + platformRect.height;

                boolean xOverlap = (x < platformRect.x + platformRect.width) &&
                        (x + width > platformRect.x);

                if (xOverlap &&
                        playerBottomBefore <= platformTop &&
                        playerBottomAfter >= platformTop) {

                    if (platformTop > highestPlatformY) {
                        highestPlatformY = platformTop;
                        landingPlatform = platform;
                    }
                }
            }

            if (landingPlatform != null) {
                y = landingPlatform.getY() - height;
                dy = 0;
                onGround = true;
            } else {
                // 检查地面碰撞
                if (playerBottomAfter >= 450) {
                    y = 450 - height;
                    dy = 0;
                    onGround = true;
                }
            }
        } else if (dy < 0) {
            // 上升碰撞检测(头部碰撞)
            int playerTopAfter = y;
            int playerTopBefore = yPrev;

            Platform headPlatform = null;
            int lowestPlatformBottom = Integer.MAX_VALUE;

            for (Platform platform : platforms) {
                Rectangle platformRect = platform.getBounds();
                int platformBottom = platformRect.y + platformRect.height;

                boolean xOverlap = (x < platformRect.x + platformRect.width) &&
                        (x + width > platformRect.x);

                if (xOverlap &&
                        playerTopBefore >= platformBottom &&
                        playerTopAfter <= platformBottom) {

                    if (platformBottom < lowestPlatformBottom) {
                        lowestPlatformBottom = platformBottom;
                        headPlatform = platform;
                    }
                }
            }

            if (headPlatform != null) {
                y = headPlatform.getY() + headPlatform.getHeight();
                dy = 0;
            }
        }

        // 更新攻击计时器
        if (attackTimer > 0) {
            attackTimer--;
        }
    }

    public Bullet shoot() {
        attackTimer = ATTACK_COOLDOWN;
        int bulletX = facingRight ? x + width : x - 10;
        int bulletY = y + height/2 - Bullet.SIZE/2;
        return new Bullet(bulletX, bulletY, facingRight ? BULLET_SPEED : -BULLET_SPEED, this);
    }

    public void jump() {
        if (onGround) {
            dy = JUMP_FORCE;
            onGround = false;
        }
    }

    public void takeDamage(int damage) {
        health = Math.max(0, health - damage);
    }

    public void draw(Graphics g) {
        g.setColor(color);
        g.fillRect(x, y, width, height);
    }

    public Rectangle getCollisionBounds() {
        return new Rectangle(x + 5, y + 10, width - 10, height - 20);
    }

    public int getX() { return x; }
    public int getY() { return y; }
    public int getHealth() { return health; }
    public Color getColor() { return color; }
    public boolean isOnGround() { return onGround; }
    public void setMovingLeft(boolean moving) { movingLeft = moving; }
    public void setMovingRight(boolean moving) { movingRight = moving; }
    public boolean canAttack() { return attackTimer <= 0; }
    public int getLeftKey() { return leftKey; }
    public int getRightKey() { return rightKey; }
    public int getJumpKey() { return jumpKey; }
    public int getAttackKey() { return attackKey; }
}

class Bullet {
    int x, y;
    int speed;
    Player shooter;
    static final int SIZE = 10;

    public Bullet(int x, int y, int speed, Player shooter) {
        this.x = x;
        this.y = y;
        this.speed = speed;
        this.shooter = shooter;
    }

    public void update() {
        x += speed;
    }

    public void draw(Graphics g) {
        g.setColor(Color.YELLOW);
        g.fillOval(x, y, SIZE, SIZE);
    }

    public boolean hitsPlayer(Player player) {
        Rectangle bulletRect = new Rectangle(x, y, SIZE, SIZE);
        return bulletRect.intersects(player.getCollisionBounds());
    }

    public boolean hitsPlatform(Platform platform) {
        Rectangle bulletRect = new Rectangle(x, y, SIZE, SIZE);
        return bulletRect.intersects(platform.getBounds());
    }
}

class Platform {
    private int x, y, width, height;

    public Platform(int x, int y, int width, int height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }

    public void draw(Graphics g) {
        g.setColor(new Color(100, 100, 100));
        g.fillRect(x, y, width, height);
        g.setColor(new Color(120, 120, 120));
        g.fillRect(x, y, width, 3);
        g.fillRect(x, y + height - 3, width, 3);
    }

    public Rectangle getBounds() {
        return new Rectangle(x, y, width, height);
    }

    public int getY() { return y; }
    public int getHeight() { return height; }
}
相关推荐
浮游本尊9 小时前
Java学习第22天 - 云原生与容器化
java
渣哥10 小时前
原来 Java 里线程安全集合有这么多种
java
间彧11 小时前
Spring Boot集成Spring Security完整指南
java
间彧11 小时前
Spring Secutiy基本原理及工作流程
java
Java水解12 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆14 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学14 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole15 小时前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端
华仔啊15 小时前
基于 RuoYi-Vue 轻松实现单用户登录功能,亲测有效
java·vue.js·后端