java - 乒乓球游戏 - 为球动画添加计时器

标签 java swing timer jpanel pong

我现在正在开发 Pong 游戏,我的球动画速度太快了。我想为我的动画添加一个计时器,但我真的不知道该怎么做。我用在互联网上找到的一些代码进行了尝试,但它不起作用。请帮助我:(

这是我的代码:

private static final long serialVersionUID = 1L;

private int posX = SCREEN_WIDTH / 2;
private int posY;
int x;
int y;
private int scoreCountPlayer1 = 0;
private int scoreCountComputer = 0;

private int delay = 10;

  // Create a timer with delay 1000 ms
private Timer timer = new Timer(delay, new TimerListener());


private Rectangle ballRect;
private Rectangle padRect;

private int upLimit;
private int downLimit;
private int padPosition;

public boolean backX = false;
public boolean backY = false;
public boolean move = true;

public Point posMouse = new Point();

private int playPanelWidth;
private int playPanelHeight;

private int padPanelWidth;
private int padPanelHeight;

private int panPanelWidth;
private int panPanelHeight;

private JLabel player1Score = new JLabel("1");
private JLabel ComputerScore = new JLabel("0");

private JPanel panPlayer1;
public JPanel panComputer;

public JPanel padPlayer1;
public JPanel padComputer;

public ScorePanel scorePanel;

private JButton but_Escape = new JButton("Press Space to continue !");

/*
 * Constructeur de classe : PlayPanel.java
 */
// ==============================================
public PlayPanel() {
    super(new BorderLayout());
    setBackground(PANPLAY_COLOR);

    scorePanel = new ScorePanel();

    panPlayer1 = new JPanel();
    panComputer = new JPanel();

    padPlayer1 = new JPanel();
    padComputer = new JPanel();

    padPlayer1.setBackground(Color.DARK_GRAY);
    padComputer.setBackground(Color.DARK_GRAY);

    padPlayer1.setPreferredSize(PADPANEL_SIZE);
    padComputer.setPreferredSize(PADPANEL_SIZE);

    panPlayer1.setBackground(PANPLAY_COLOR);
    panComputer.setBackground(PANPLAY_COLOR);

    panPlayer1.add(padPlayer1);
    panComputer.add(padComputer);

    add(panPlayer1, BorderLayout.WEST);
    add(panComputer, BorderLayout.EAST);
    add(scorePanel, BorderLayout.SOUTH);

    player1Score.setFont(FONT_SCORE);
    ComputerScore.setFont(FONT_SCORE);

    addMouseMotionListener(this);

    timer.start();

}

/*
 * Add the ball
 */
// ==============================================
public void paintComponent(Graphics g) {

    super.paintComponent(g);

    Graphics2D g2 = (Graphics2D) g;

    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setColor(Color.BLACK);

    initBall(g2);

    // trait épais
    g2.setColor(Color.DARK_GRAY);

    g2.setStroke(new BasicStroke(10));
    g2.drawLine((getPlayPanelWidth() / 2) - 5, getPlayPanelHeight(),
            (getPlayPanelWidth() / 2) - 5, 0);
}

/*
 * Init ball
 */
// ==============================================
private void initBall(Graphics2D graphics2d) {

    Graphics2D g2 = graphics2d;

    x = getPosX();
    y = getPosY();

    ballRect = new Rectangle(posX, posY, BALL_WIDTH, BALL_HEIGHT);
    padRect = new Rectangle(playPanelWidth
            - (getPanComputer().getWidth() + 2), (int) getPosMouse().getY()
            - getPadPanelHeight() / 2, padPanelWidth, padPanelHeight);

    g2.fillOval(posX, posY, BALL_WIDTH, BALL_HEIGHT);

    if (posX == 763) {

        if (ballRect.intersects(padRect)) {

            System.out.println("collision");
            Move();

        } else {

            int posMouseY = getPosMouse().y;
            System.out.println("pas collision");
            stopBall(g2, posMouseY);
        }

    } else {
        Move();

    }
}

private void Move() {

    if (x < 1 + 15) {
        backX = false;
        scorePanel.getLab_Player1().setText("" + scoreCountPlayer1);
    }

    if (x > getWidth() - 52) {
        backX = true;
    }

    if (y < 1) {
        backY = false;
    }

    if (y > getHeight() - (SCOREPANEL_SIZE.getHeight() + BALL_HEIGHT)) {
        backY = true;
    }

    if (!backX) {
        setPosX(++x);
    }

    else {
        setPosX(--x);
    }

    if (!backY) {
        setPosY(++y);
    } else {
        setPosY(--y);
    }

    repaint();
}

private void stopBall(final Graphics2D g2, int posBallY) {
    move = false;
}

@Override
public void mouseDragged(MouseEvent arg0) {
}

@Override
public void mouseMoved(MouseEvent arg0) {

    // Définit les limite de le souris, la position
    // des pads et de la souris.
    upLimit = getPadPanelHeight() / 2;
    downLimit = playPanelHeight - scorePanel.getScorePanHeight()
            - (getPadPanelHeight() / 2);
    padPosition = playPanelHeight - scorePanel.getScorePanHeight()
            - (getPadPanelHeight());

    posMouse.setLocation(arg0.getX(), arg0.getY());

    setPosMouse(posMouse);


    if (arg0.getY() >= downLimit) {

        padPlayer1.setLocation(getPanPanelWidth() - 10, padPosition);
        padComputer.setLocation(0, padPosition);


    } else if (arg0.getY() <= upLimit) {

        padPlayer1.setLocation(getPanPanelWidth() - 10, 0);
        padComputer.setLocation(0, 0);


    } else {

        padPlayer1.setLocation(getPanPanelWidth() - 10,
                (int) posMouse.getY());
        padComputer.setLocation(0, (int) posMouse.getY()
                - (getPadPanelHeight() / 2));
    }
}

private class TimerListener implements ActionListener {
    /** Handle the action event */
    public void actionPerformed(ActionEvent e) {
      repaint();
    }
  }

最佳答案

我不太熟悉动画,但我认为你需要做的是使用计时器以固定的时间间隔将球移动一定的距离。

您当前的代码计划(强调计划,而不是执行)几乎每个paint 调用中的repaint(通过调用移动 方法)。这将使控制球的速度变得非常困难。您不知道实际会执行多少次 repaint,因此您不知道球移动的速度有多快(因为多个预定的重绘可以归为一个重绘)。在混合中添加一个 Timer 来执行一些额外的重绘将无济于事(而且肯定不是一个每秒安排重绘的计时器......这将导致 1FPS 帧速率,看起来像 1950 年)。

如果您使用计时器以固定的时间间隔(50 毫秒、100 毫秒,……稍微试验一下)更改球的坐标并安排重绘,您可以完全控制速度的球。即使将计时器的两次 repaint 调用组合在一起,球也会跳过一个位置,但速度会保持一致。当您上升一个级别时,只需通过减少延迟来增加 Timer 代码被触发的次数。

您可能想阅读 freely available Animation chapterFilthy Rich Clients书,其中包含更多免费摘录和代码示例。您可能还想查看示例 here .

关于java - 乒乓球游戏 - 为球动画添加计时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10035986/

相关文章:

java - 是否有可能在jsp中保存或缓存表单数据

java - 安卓java : delete selected file/folder

Java JPanel.add(...) 不工作

java - JOptionPane 元素之间的交替焦点

java - JScrollPane 可以调整得更小,但 JTextArea 不能

java - 如何允许请求参数有多个预定义(枚举)值?

java - 将数据从列表传递到对象[][]

javascript - 使用倒数计时器自动刷新页面

JavaScript 秒表 - 显示前导数字时遇到问题

java - 如何制作可以启动和停止的线程之类的东西?