1

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

这是我的代码:

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();
    }
  }

}

4

3 回答 3

3

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

您当前的代码计划(强调计划,而不是执行)repaint几乎每次paint调用(通过对move方法的调用)。这将很难控制球的速度。您不知道实际将执行多少repaints,因此您不知道球的移动速度有多快(因为多个计划的重绘可以组合成一个重绘)。在混合中添加 aTimer来执行一些额外的重绘将无济于事(当然不是每秒安排重绘的计时器......这将导致 1FPS 帧速率,看起来如此 1950 )。

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

您可能想阅读Filthy Rich Clients书中免费提供的动画章节,其中包含更多免费摘录和代码示例。您可能还想检查此处看到的示例。

于 2012-04-05T21:31:47.450 回答
1

使用java.util包中的计时器:

new Timer().scheduleAtFixedRate(new TimerTask() {

        @Override
        public void run() {
            repaint();
        }
    }, 20, 20); // replace 20 with how often you want it to be called (in milliseconds)
于 2012-04-05T21:10:20.677 回答
0

问题是您在每个循环中将球移动一个像素,我认为您应该将 x 和 y 坐标从 int 更改为 double,引入一个名为speed的新变量,其值为 0.1,并将此速度添加到坐标中。然后球应该每 10 个游戏循环移动一个像素,也许应该需要一个更小的值,但你必须调整它

希望能帮助到你

于 2012-04-05T21:21:51.320 回答