1

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

}

4

3 に答える 3

3

私はアニメーションにあまり詳しくありませんが、あなたがしなければならないと思うのは、タイマーを使って一定の時間間隔でボールを一定の距離だけ動かすことです。

現在のコードスケジュール(スケジュールを強調し、実行しない)はrepaint、ほとんどすべての呼び出しで(メソッドpaintの呼び出しを介して)実行されます。moveこれにより、ボールの速度を制御することが非常に困難になります。実際に実行される秒数がわからrepaintないため、ボールがどれだけ速く移動するかがわかりません(複数のスケジュールされた再描画を1つの再描画にグループ化できるため)。いくつかの追加の再描画を実行するためにミックスにを追加してTimerも効果はありません(そして確かに毎秒再描画をスケジュールするタイマーではありません...これは1FPSフレームレートになります。これは1950のように見えます)。

タイマーを使用して一定の時間間隔(50ms、100ms、...少し実験)でボールの座標を変更し、スケジュールを設定するrepaint場合は、ボールの速度を完全に制御できます。repaintタイマーの2つの呼び出しがグループ化されている場合でも、ボールは位置をスキップしますが、速度は一定になります。Timerレベルを上げるときは、遅延を減らしてコードがトリガーされる回数を増やすだけです。

より多くの無料の抜粋とコード例が掲載されている、FilthyRichClientsの本の無料で入手できるアニメーションの章を読むことをお勧めします。ここで見られる例を調べることもできます。

于 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

問題は、ループごとに1ピクセルずつボールを移動していることです。x座標とy座標をintからdoubleに変更し、値0.1のspeedという名前の新しい変数を導入して、この速度を座標に追加する必要があると思います。次に、ボールは10ゲームループごとに1ピクセル移動する必要があります。おそらく、より小さな値が必要ですが、微調整する必要があります。

それが役に立てば幸い

于 2012-04-05T21:21:51.320 に答える