2015-08-24 93 views
1

我目前正在嘗試用Java構建一個基本的Pong遊戲,並且我在兩件事情上遇到困難。首先是我的球拍應該上下移動,但是一旦他們到達球拍邊緣,球拍就會完全凍結。我不明白爲什麼。接下來,我不確定如何使用Timer或Thread.sleep在每次得分後立即暫停遊戲。一旦其中一名球員得分,我希望比賽將球送回中鋒並等待大約3秒鐘,然後球再次移動以開始下一個點。任何幫助都會很棒。謝謝!在Java Pong遊戲中KeyListener和Timer的問題

這裏是我的代碼

傍類

import java.awt.*; 

import javax.swing.*; 


public class Pong extends JFrame{ 

    public static final int appWIDTH = 500;  //width of jframe 
    public static final int appHEIGHT = 500; //height of jframe 
    public final int rWIDTH = 20;    //width of racket 
    public final int rHEIGHT = 60;    //height of racket 
    PongPanel panel;       //Jpanel to be added 


    /* 
    * constructor for a Pong object 
    */ 
    public Pong() { 
     setSize(appWIDTH, appHEIGHT); 
     setTitle("PONG"); 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 
     setBackground(Color.BLACK); 
    } 

    /* 
    * Starts the application 
    */ 
    public void start() { 
     panel = new PongPanel(this); 
     add(panel); 
     addKeyListener(panel); 
     setVisible(true); 
     setFocusable(true); 
    } 

    //Returns a PongPanel 
    public PongPanel getPanel() { 
     return panel; 
    } 

    public static void main(String[] args) { 
     Pong game = new Pong(); 
     game.start(); 
    } 
} 

面板類

import java.awt.*; 
import java.awt.event.*; 

import javax.swing.*; 


public class PongPanel extends JPanel implements KeyListener { 

    private Pong game; 
    private Ball ball; 
    private Racket p1, p2; 
    private int score1, score2; 
    Timer timer; 

    /* 
    * Constructor for a PongPanel which is a JPanel that holds two rackets and a ball 
    */ 
    public PongPanel(Pong game) { 
     this.game = game; 
     p1 = new Racket(game, KeyEvent.VK_W, KeyEvent.VK_S, 0); 
     p2 = new Racket(game, KeyEvent.VK_UP, KeyEvent.VK_DOWN, game.getWidth() - game.rWIDTH); 
     ball = new Ball(game); 
     addKeyListener(this); 
     setFocusable(true); 
     setVisible(true); 
    } 

    /* 
    * Returns the Racket object associated with player 1 
    */ 
    public Racket getRacket1() { 
     return p1; 
    } 

    /* 
    * Returns the Racket object associated with player 2 
    */ 
    public Racket getRacket2() { 
     return p2; 
    } 

    //Increases score of the player indicated by the parameter 
    public void increaseScore(int playerNo) { 
     if(playerNo == 1) 
      score1++; 
     else 
      score2++; 
    } 

    //Returns the score of the player indicated by the parameter 
    public int getScore(int playerNo) { 
     if(playerNo == 1) 
      return score1; 
     else 
      return score2; 
    } 

    public void update() { 
     ball.hitBTS(); 
     p1.move(); 
     p2.move(); 
     repaint(); 
    } 

    public void keyPressed(KeyEvent ke) { 
     p1.kpressed(ke.getKeyCode()); 
     p2.kpressed(ke.getKeyCode()); 
    } 

    public void keyReleased(KeyEvent ke){ 
     p1.krelease(ke.getKeyCode()); 
     p2.krelease(ke.getKeyCode()); 
    } 

    public void keyTyped(KeyEvent ke) {} 

    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     ball.paint(g); 
     p1.paint(g); 
     p2.paint(g); 
     update(); 
    } 
} 

球類

import java.awt.Graphics; 
import java.awt.Rectangle; 

import javax.swing.JFrame; 
import javax.swing.JOptionPane; 


public class Ball { 

    private JFrame frame = new JFrame(); 
    private Pong game; 
    final int bWIDTH = 30;     //ball width  
    final int bHEIGHT = 30;     //ball height 
    private int xspeed = 1;     //horizontal speed of the ball 
    private int yspeed = 1;     //vertical speed of the ball 
    int x;         //x-coordinate of the ball 
    int y;         //y-coordinate of the ball 


    /* 
    * Constructor of a ball object. Sets the ball in the center of frame 
    */ 
    public Ball(Pong game) { 
     x = game.getWidth()/2 - (bWIDTH/2); 
     y = game.getHeight()/2 - (bHEIGHT/2); 
     this.game = game; 
    } 

    /* 
    * Checks whether the ball has hit the bottom or top of the frame 
    * or if it has reached the left or right edge (score) 
    */ 
    public void hitBTS() { 
     x += xspeed; 
     y += yspeed; 

     if((x + bWIDTH) > game.getWidth()) { 
      game.getPanel().increaseScore(1); 
      x = game.getWidth()/2 - (bWIDTH/2); 
      y = game.getHeight()/2 -(bHEIGHT/2); 
     } 

     else if(x < 0) { 
      game.getPanel().increaseScore(2); 
      x = game.getWidth()/2 - (bWIDTH/2); 
      y = game.getHeight()/2 -(bHEIGHT/2); 
     } 

     else if(y < 0 || (y > game.getHeight() + bHEIGHT)) { 
      yspeed = -yspeed; 
     } 

     checkScore(); 
     checkCollision(); 
    } 

    //Shows a dialog box indicating the winter if one player reaches 
    //a score of 3 
    public void checkScore() { 
     if(game.getPanel().getScore(1) == 3) { 
      JOptionPane.showMessageDialog(frame, "Player 1 wins"); 
     } 
     else if(game.getPanel().getScore(2) == 3) { 
      JOptionPane.showMessageDialog(frame, "Player 2 wins"); 
     } 
    } 

    //Checks if the ball has hit a racket 
    public void checkCollision() { 
       if(getBallBounds().intersects(game.getPanel().getRacket1().getBounds()) || 
getBallBounds().intersects(game.getPanel().getRacket2().getBounds())) { 
      xspeed = -xspeed; 
     } 
    } 

    public Rectangle getBallBounds() { 
     return new Rectangle(x, y, bWIDTH, bHEIGHT); 
    } 

    public void paint(Graphics g) { 
     g.fillRect(x, y, bWIDTH, bHEIGHT); 
    } 

} 

球拍類

import java.awt.*; 
import java.awt.event.*; 

public class Racket { 

    private Pong game; 
    private int yspeed = 0;  //Number of pixels that the racket moves 
    int x;      //x-coordinate of racket 
    int y;      //y-coordinate of racket 
    int keyUp, keyDown;   //key code associated with the key pressed 

    /* 
    * Constructor for a racket object. Racket receives a keycode and horizontal 
    * starting position. 
    */ 
    public Racket(Pong game, int keyUp, int keyDown, int x) { 
     this.game = game; 
     this.x = x; 
     this.keyUp = keyUp; 
     this.keyDown = keyDown; 
     y = game.getHeight()/2; 
    } 

    /* 
    * Indicates how the racket should move depending on its position. 
    */ 
    public void move() { 
     if(y > 0 && y < game.getHeight() - game.rHEIGHT)  
      y += yspeed; 
     else if(y <= 0) 
      y = y + 3; 
     else if(y == game.getHeight() - game.rHEIGHT) 
      y = y - 3; 
    } 

    /* 
    * If key has been pressed, the number of pixels the 
    * racket moves becomes positive or negative 
    */ 
    public void kpressed(int keyCode) { 
     if(keyCode == keyUp) { 
      yspeed = -3; 
     } 

     if(keyCode == keyDown) 
      yspeed = 3; 
    } 

    /* 
    * When the key is no longer being pressed, the 
    * racket stops moving. 
    */ 
    public void krelease(int keyCode) { 
     if(keyCode == keyUp) 
      yspeed = 0; 
     else if (keyCode == keyDown) 
      yspeed = 0; 
    } 

    public Rectangle getBounds() { 
     return new Rectangle(x, y, game.rWIDTH, game.rHEIGHT); 
    } 

    public void paint(Graphics g) { 
     g.fillRect(x, y, game.rWIDTH, game.rHEIGHT); 
    } 
} 
+0

開始由具有看看[如何使用按鍵綁定(http://docs.oracle的.com/JavaSE的/教程/ uiswing /雜項/ keybinding.html)。關鍵事件不應直接修改UI的狀態或UI可能依賴的任何值,而應該簡單地設置一個標誌來指示哪些鍵當前處於活動狀態。使用Swing'Timer'或'Thread'作爲主要的「遊戲循環」,通過每個循環確定遊戲是否暫停,如果是,則什麼都不做,否則根據標誌更新UI狀態並重新計劃重畫 – MadProgrammer

回答

1

要回答你的第一個問題,改變你的球拍類的移動方法如下:

public void move() { 
    if(y > 0 && y < game.getHeight() - game.rHEIGHT)  
     y += yspeed; 
    else if(y <= 0) 
     y = y + 3; 
    else if(y >= game.getHeight() - game.rHEIGHT) 
     y = y - 3; 
} 

否則,當y變得比game.getHeight()放大 - game.rHEIGHT,它會凍結它將再次與移動方法中的三個條件中的任何一個都不匹配。

要回答你的第二個問題,你可以按照以下步驟改變你的球類的checkScore方法:

public void checkScore() { 
    if(game.getPanel().getScore(1) == 3) { 
     JOptionPane.showMessageDialog(frame, "Player 1 wins"); 
    } 
    else if(game.getPanel().getScore(2) == 3) { 
     JOptionPane.showMessageDialog(frame, "Player 2 wins"); 
    } 
    else { 
     x = game.getWidth()/2 - (bWIDTH/2); 
     y = game.getHeight()/2 - (bHEIGHT/2); 
     Thread.sleep(3000); 
    } 
} 
+1

,在EDT的上下文中調用'Thread.sleep'是非常不重要的,因爲它會停止繪畫過程 – MadProgrammer

+0

我試圖按照你說的uoyilmaz來做;但是,當JFrame啓動時,我會在3000毫秒內出現黑屏,然後當球和球拍出現時,屏幕仍然凍結。 –

+0

正如MadProgrammer所說,當Thread.sleep處於同一個線程時,它將干擾繪畫過程。你應該改變你的程序的體系結構,因爲他在他對你的問題的評論中說過。但是,我的答案的第一部分仍然是正確的。 – uoyilmaz