java - 向简单的 java 游戏添加开始、停止、重置按钮

标签 java multithreading swing animation 2d-games

我是一名新编码员。我在为我正在处理的这段示例代码添加开始和停止按钮时遇到问题。我确定我必须在游戏类中处理 Thread.sleep(10); 。该代码在程序运行时启动游戏。有没有办法添加开始按钮来启动线程。我已经创建了 j 按钮。谢谢。

游戏类

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class Game extends JPanel {

    Ball ball = new Ball(this);
    Racquet racquet = new Racquet(this);

    public Game() {
        addKeyListener(new KeyListener() {
            @Override
            public void keyTyped(KeyEvent e) {
            }

            @Override
            public void keyReleased(KeyEvent e) {
                racquet.keyReleased(e);
            }

            @Override
            public void keyPressed(KeyEvent e) {
                racquet.keyPressed(e);
            }
        });
        setFocusable(true);
    }

    private void move() {
        ball.move();
        racquet.move();
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        ball.paint(g2d);
        racquet.paint(g2d);
    }

    public void gameOver() {
        JOptionPane.showMessageDialog(this, "Game Over", "Game Over", JOptionPane.YES_NO_OPTION);
        System.exit(ABORT);
    }

    public static void main(String[] args) throws InterruptedException {
        JFrame frame = new JFrame("Mini Tennis");
        Game game = new Game();
        frame.add(game);
        frame.setSize(300, 400);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        while (true) {
            game.move();
            game.repaint();
            Thread.sleep(10);
        }
    }
}

球类

import java.awt.Graphics2D;
import java.awt.Rectangle;

public class Ball {
    private static final int DIAMETER = 30;
    int x = 0;
    int y = 0;
    int xa = 1;
    int ya = 1;
    private Game game;

    public Ball(Game game) {
        this.game= game;
    }

    void move() {
        if (x + xa < 0)
            xa = 1;
        if (x + xa > game.getWidth() - DIAMETER)
            xa = -1;
        if (y + ya < 0)
            ya = 1;
        if (y + ya > game.getHeight() - DIAMETER)
            game.gameOver();
        if (collision()){
            ya = -1;
            y = game.racquet.getTopY() - DIAMETER;
        }
        x = x + xa;
        y = y + ya;
    }

    private boolean collision() {
        return game.racquet.getBounds().intersects(getBounds());
    }

    public void paint(Graphics2D g) {
        g.fillOval(x, y, DIAMETER, DIAMETER);
    }

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

Racket 类

import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;

public class Racquet {
    private static final int Y = 330;
    private static final int WIDTH = 60;
    private static final int HEIGHT = 10;
    int x = 0;
    int xa = 0;
    private Game game;

    public Racquet(Game game) {
        this.game = game;
    }

    public void move() {
        if (x + xa > 0 && x + xa < game.getWidth() - WIDTH)
            x = x + xa;
    }

    public void paint(Graphics2D g) {
        g.fillRect(x, Y, WIDTH, HEIGHT);
    }

    public void keyReleased(KeyEvent e) {
        xa = 0;
    }

    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_LEFT)
            xa = -1;
        if (e.getKeyCode() == KeyEvent.VK_RIGHT)
            xa = 1;
    }

    public Rectangle getBounds() {
        return new Rectangle(x, Y, WIDTH, HEIGHT);
    }

    public int getTopY() {
        return Y;
    }
}

最佳答案

这是一个mcve演示 Hovercraft Full Of Eels comment 中概述的结构:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionListener;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class AnimationUsingTimer {

    private Timer timer;

    AnimationUsingTimer() {

        JFrame window = new JFrame();
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        AnimationPanel animationPanel = new AnimationPanel();
        window.add(animationPanel);

        JButton start = new JButton("Start");
        start.addActionListener(e -> animationPanel.start());
        window.add(start, BorderLayout.PAGE_START);

        JButton stop = new JButton("Stop");
        stop.addActionListener(e -> animationPanel.stop());
        window.add(stop, BorderLayout.PAGE_END);
        window.pack();
        window.setVisible(true);
    }

    class AnimationPanel extends JPanel{

        private BufferedImage img;
        private Area ball, walls;
        private final static int W = 450,  H = 300,  DIAMETER = 20;
        private int x = W/2,  y = H/2, xDelta = 3,  yDelta = 2;

        AnimationPanel() {
            img = new BufferedImage(W, H, BufferedImage.TYPE_INT_RGB);
            JLabel imageLabel = new JLabel(new ImageIcon(img));
            add(imageLabel);
            walls = new Area(new Rectangle(0,0,W,H));

            ActionListener animate = e -> {
                animate();
                repaint();
            };
            timer = new Timer(50, animate);
        }

        public void animate() {
            x+=xDelta;      y+=yDelta;
            ball = new Area(new Ellipse2D.Double(x, y, DIAMETER, DIAMETER));

            if (checkCollision(ball,walls)) {
                if ( x+DIAMETER>img.getWidth() || x<0 ) {
                    xDelta *= -1;
                }
                if(y+DIAMETER>img.getHeight() || y<0 ) {
                    yDelta *= -1;
                }
            }
        }

        @Override
        protected void paintComponent(Graphics g){
            super.paintComponent(g);

            Graphics2D g2D = img.createGraphics();
            g2D.setRenderingHint(
                    RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);

            g2D.setColor(Color.CYAN);
            g2D.fillRect(0, 0, img.getWidth(), img.getHeight());

            if(ball != null){
                g2D.setColor(Color.RED);
                g2D.fill(ball);
            }
            g2D.dispose();
        }

        void start(){
            timer.start();
        }

        void stop(){
            timer.stop();
        }

        private boolean checkCollision(Area area1, Area area2) {

            return area1.getBounds().intersects(area2.getBounds());
        }
    }

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

关于java - 向简单的 java 游戏添加开始、停止、重置按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53699325/

相关文章:

java - Android SeekBar 值未正确传递给计算方法

java - Collections.reverse 方法不反转条目

python - 在python中同时并行化不同的功能

java - 用java编写一个简单的基准测试工具

java - 如何涂黑一个Swing组件?

java - 拾取点的 WorldWind 颜色

java - 打印 JTable 时遇到问题

java - MySql连接太多

java - 有条件地创建 Spring bean @ConditionalOn

python - 使用 GNU parallel 并行化多线程命令