2017-06-14 32 views
1

因此,我正在製作一款使用Java的遊戲,並希望在用戶在菜單屏幕上按下「播放」後,使用計時器從遊戲屏幕上的3倒計時。我的計時器在Java中不能正確計數

這裏是我的代碼:

int seconds = 3; 

private void countdown(Graphics g) { 

    Timer timer = new Timer(); 

    TimerTask task = new TimerTask() { 
     public void run() { 
      if(seconds >= 0) { 
       System.out.println(seconds); 
       seconds--; 
      } 
      if(seconds == -1) { 

       timer.cancel(); 
      } 
     } 
    }; 

    timer.schedule(task, 1000, 1000); 
} 

我用倒計時在我比賽的抽籤方法在這裏:

public void draw(Graphics g) { 

    //background 
    g.setColor(Color.BLACK); 
    g.fillRect(0, 0, WIDTH, HEIGHT); 

    //count 
    countdown(g); 
} 

我使用控制檯打印的數字,但是我會改變這稍後使用drawString()在屏幕上繪製倒數。

在我的菜單屏幕上按下「play」後,我的遊戲屏幕上會暫停一秒,然後數字全部打印到控制檯。問題是在打印數字之間沒有第二個延遲,他們只是同時打印所有數字。任何幫助?

+0

工作正常,我。請發佈[mcve]。 – shmosel

+0

您是否使用繪圖方法並以秒爲單位遞減1秒? –

+0

我只是做了'countdown()'方法,它以1秒爲間隔計數到0。我不明白'draw()'方法是如何與問題相關的。 – shmosel

回答

1

如果draw被重複調用,那麼將會創建多個定時器,這樣您將從每個定時器獲得打印輸出,這也會減少秒數。

您可以嘗試創建一個計時器,而不是在每個倒計時函數中創建,並且只需使倒計時功能設置秒數值即可。

+0

我該如何解決這個問題,所以它不會重複調用,但仍然將計時器繪製到屏幕上? –

+0

你的意思是這樣嗎? 'private int seconds = 3; \t private Timer timer = new Timer(); \t \t私人無效倒計時(圖形克){ \t \t \t \t TimerTask的任務=新的TimerTask(){ \t \t \t公共無效的run(){ \t \t \t \t如果(秒> = 0){ \t \t \t \t \t的System.out.println(秒); \t \t \t \t \t秒 - ; \t \t \t \t} \t \t \t \t如果(秒== -1){ \t \t \t \t \t timer.cancel(); \t \t \t \t} \t \t \t} \t \t}; \t \t \t \t timer.schedule(task,1000,1000); \t}' –

+0

我道歉,我不知道如何格式化最後一個。 –

0

,必須重置當您創建和/或取消計時器

seconds變量
 Timer timer = new Timer(); 
     seconds = 3; //Reset here 
     .......... 
     .......... 

     if(seconds == -1) { 
      timer.cancel(); 
      seconds = 3; // Reset here 
     } 
+0

當我這樣做時,它只是非常快速地重複從3到0的倒計數,並沒有停止。 –

+0

這意味着你有多個任務創建..這是你打算做什麼? – Zakir

+0

我最初打算使用_drawString()_在屏幕上進行倒計時顯示,而我只是希望計時器從3到0進行計數。我最初只需要一個任務。 –

1

你的計劃似乎是一個Swing或AWT GUI程序,如果是這樣,你使用了錯誤的類型的Timer,這裏是java.util.Timerjava.util.TimerTask,這兩者都不是Swing線程安全的。這可能會導致您的GUI凍結,並且數字不會顯示出來,就像您看到的一樣。而應使用專門爲這些GUI構建的計時器,一個Swing Timer (click on this link for the tutorial)。你也從繪圖代碼中調用計時器,這與你應該做的事情完全相反。相反,定時器應該改變你的計數變量的狀態,然後調用repaint()。繪圖代碼然後獲取計數變量的值並將其顯示在GUI中。

例如,你的揮杆定時器可以使用一個ActionListener其actionPerformed方法看起來是這樣的:

public void actionPerformed(ActionEvent e) { 
    if (counter != 0) { 
     // if the counter hasn't reached the end 
     counter--; // reduce counter by one 
     repaint(); // tell the GUI to repaint 
    } else { 
     timer.stop(); // otherwise at the end, so stop the timer 
     countDownAction.setEnabled(true); // and re-enable the button 
    } 
} 

一個完整的GUI例子看起來是這樣的:

import java.awt.Dimension; 
import java.awt.Font; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class CountDown extends JPanel { 
    public static final int TIMER_DLEAY = 1000; 
    private static final Font COUNTER_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 400); 
    private static final int TEXT_X = 200; 
    private static final int TEXT_Y = 500; 
    private int counter; 
    private JSpinner spinner = new JSpinner(new SpinnerNumberModel(5, 0, 20, 1)); 
    private CountDownAction countDownAction = new CountDownAction("Count Down"); 
    private JButton countDownButton = new JButton(countDownAction); 
    private Timer timer; 

    public CountDown() { 
     setPreferredSize(new Dimension(800, 600)); 
     add(new JLabel("Starting Value:")); 
     add(spinner); 
     add(countDownButton); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D) g; 
     g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, 
       RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 
     g.setFont(COUNTER_FONT); 
     String text = String.format("%02d", counter); 
     g.drawString(text, TEXT_X, TEXT_Y); 
    } 

    private class CountDownAction extends AbstractAction { 
     public CountDownAction(String name) { 
      super(name); 
      int mnemonic = (int) name.charAt(0); 
      putValue(MNEMONIC_KEY, mnemonic); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      // inactivate the button/action 
      countDownAction.setEnabled(false); 
      counter = (int) spinner.getValue(); 
      repaint(); 
      timer = new Timer(TIMER_DLEAY, new TimerListener()); 
      timer.start(); 
     } 
    } 

    private class TimerListener implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      if (counter != 0) { 
       // if the counter hasn't reached the end 
       counter--; // reduce counter by one 
       repaint(); // tell the GUI to repaint 
      } else { 
       timer.stop(); // otherwise at the end, so stop the timer 
       countDownAction.setEnabled(true); // and re-enable the button 
      } 
     } 
    } 

    private static void createAndShowGui() { 
     JFrame frame = new JFrame("CountDown"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(new CountDown()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
}