2012-04-05 3 views
1

Ich arbeite an einem Pong-Spiel jetzt und ich meine Ball-Animation geht zu schnell. Ich möchte meiner Animation einen Timer hinzufügen, aber ich weiß wirklich nicht, wie ich es machen soll. Ich habe es mit etwas Code versucht, den ich im Internet gefunden habe, aber es funktioniert nicht. bitte helft mir :(Pong Spiel - Timer hinzufügen, um den Ball Animation

hier ist mein Code:

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

}

+1

1) Es funktioniert nicht ... meine Kristallkugel wurde vor kurzem kaputt gemacht, also beschreibe, was du erwartest und was tatsächlich passiert 2) Hier ist mein Code ... der Code, den du gepostet hast, ist viel zu lang und wird nicht einmal kompilieren. 3) Ihre ganze "Animation" -Ding basiert darauf, "Repaint" immer wieder aufzurufen (im Timer und in Codepfaden in Ihrer Malmethode). Also sehe ich nicht den zusätzlichen Wert des Timers, und ich bin mir nicht sicher, was Sie erreichen wollen, indem Sie es verwenden – Robin

+0

Für bessere Hilfe, früher, ein [SSCCE] (http://sscce.org/). –

+0

@trashgod +1 Ich hätte mich an dieses Beispiel erinnern sollen. Hätte mir eine Menge Schreibarbeit erspart. – Robin

Antwort

3

hilft Ich bin nicht allzu vertraut mit Animationen, aber was ich denke, dass Sie tun müssen, ist den Timer verwenden, um den Ball eine bestimmte Entfernung in festen Zeitintervallen zu bewegen.

Ihr aktueller Code Pläne (Schwerpunkt auf Zeitplan, und nicht durchführen) ein repaint in fast jedem paint Anruf (durch den Aufruf der move Methode). Dies wird es sehr schwer machen, die Geschwindigkeit des Balls zu kontrollieren. Sie wissen nicht, wie viele repaint s tatsächlich ausgeführt werden, daher wissen Sie nicht, wie schnell sich der Ball bewegt (aufgrund der Tatsache, dass mehrere geplante Repaints zu einem Repaint zusammengefasst werden können). Hinzufügen einer Timer in der Mischung, um einige zusätzliche Repaints durchzuführen wird nicht helfen (und sicherlich nicht ein Timer, der Repaints jede Sekunde plant ... dies würde zu einer 1FPS Framerate führen, die so 1950 aussieht).

Wenn Sie den Timer zu ändern, um die Koordinaten der Kugel in festen Zeitintervallen (50 ms, 100 ms, ... experimentieren ein wenig) und planen ein repaint Sie haben die volle Kontrolle über die Geschwindigkeit des Balles verwenden würde. Selbst wenn zwei repaint Anrufe des Timers gruppiert sind, wird der Ball eine Position überspringen, aber die Geschwindigkeit wird konsistent sein. Und wenn Sie eine Stufe nach oben gehen, erhöhen Sie einfach die Anzahl der Male, die der Code Timer ausgelöst wird, indem Sie die Verzögerung verringern.

Vielleicht möchten Sie die freely available Animation chapter der Filthy Rich Clients Buch lesen, die mehr kostenlose Auszüge und Codebeispiele bietet. Vielleicht möchten Sie auch die Beispiele sehen here.

+0

Danke, ich werde daran arbeiten – MTHeadss

1

ein Timer Verwenden von java.util Paket:

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) 
+0

Da Swing-GUIs im EDT erstellt und aktualisiert werden müssen, ist es im Allgemeinen einfacher, einen Swing-basierten 'Timer' zu verwenden (der diese Funktion automatisch bereitstellt). –

+0

Wo muss ich diese Codezeile einfügen, weil ich es ausprobiert habe und es nichts tut. Muss ich eine Methode aufrufen? – MTHeadss

+0

@MTHeadss Platzieren Sie es in Ihrem main() oder sogar PlayPanel() -Konstruktor – Andrejs

0

Das Problem ist, dass Sie den Ball bewegen durch ein Pixel für jede Schleife, ich denke, dass Sie die X- und Y-Koordinaten von Int zu Double ändern sollten, führen Sie eine neue Variable mit dem Namen Geschwindigkeit mit dem Wert 0,1 und addiert diese Geschwindigkeit zu den Koordinaten. Dann sollte der Ball ein Pixel für alle 10 Spiel Schleifen bewegen, vielleicht ein kleinerer Wert erforderlich sein sollte, aber Sie werden zwicken müssen es

Hoffe, dass es

+3

Und nachdem Sie so für ein paar Stunden optimiert haben, senden Sie Ihren Code/Programm an einen Freund mit einem viel langsameren/schnelleren Gerät, und all Ihre Feinabstimmung war umsonst. – Robin

+0

Ja, das habe ich vergessen, schöner Fang. Obwohl ich denke, dass es gelöst werden sollte, wenn ein Schlafanruf hinzugefügt wurde, so wäre es möglich, die Menge der Schleife pro Sekunde zu steuern – nMoncho

+0

Ein Schlafanruf auf dem EDT ist nicht getan. Siehe die Antwort von Erkan Haspulat und die Kommentare dazu – Robin

Verwandte Themen