2017-06-06 63 views
3

我正在嘗試製作遊戲Snake,儘管我目前無法不斷重新繪製蛇。我正在使用一個計時器,並且當我將間隔設置爲150毫秒時,它可以工作,但是當我將其設置爲更快的時間(例如30毫秒)時,屏幕上不會顯示任何內容。定時器w/repaint()調用在Game類中。謝謝!Java如何不斷重新繪製

遊戲類

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.FlowLayout; 
import java.awt.Frame; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.GridLayout; 
import java.awt.Panel; 
import java.awt.RenderingHints; 
import java.awt.Toolkit; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 

import javax.swing.*; 
import java.util.*; 
import java.util.Timer; 
import java.util.TimerTask; 

public class Game extends JFrame{ 

    JPanel mainPanel = new JPanel(); 

    BorderLayout layout = new BorderLayout(); 
    //Game game; 
    Snake snake = new Snake(this); 

    public Game(){ 

     super("Snake by Alex 2017"); 
     setSize((int)(Toolkit.getDefaultToolkit().getScreenSize().getWidth()),(int)(Toolkit.getDefaultToolkit().getScreenSize().getHeight())); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setVisible(true); 

     mainPanel.setLayout(null); 
     mainPanel.setSize((int)(Toolkit.getDefaultToolkit().getScreenSize().getWidth()),(int)(Toolkit.getDefaultToolkit().getScreenSize().getHeight())); 
     mainPanel.setBackground(Color.BLACK); 
     add(mainPanel); 
     mainPanel.setVisible(true); 

     start(); 

     addKeyListener(new KeyListener() { 

      @Override 
      public void keyTyped(KeyEvent e) { 
      } 

      @Override 
      public void keyReleased(KeyEvent e) { 
      } 

      @Override 
      public void keyPressed(KeyEvent e) { 
       snake.keyPressed(e); 

      } 
     }); 
     setFocusable(true); 



    } 

    public void paint(Graphics g){ 
     super.paint(g); 
     Graphics2D g2d = (Graphics2D) g; 
     g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
     snake.paint(g2d); 

     //System.out.println("hello"); 

    } 

    Timer timer = new Timer(); 
    TimerTask task = new TimerTask() { 
     public void run() { 
      try { 
       move(); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

     } 
    }; 
    TimerTask update = new TimerTask() { 

     public void run() { 
      repaint(); 

     } 
    }; 
    public void start(){ 
     timer.scheduleAtFixedRate(task, 0, 250); 
     timer.schedule(update, 0, 30); 

    } 

    public void move() throws InterruptedException{ 
     snake.move(); 

    } 

    public static void main(String[] args) throws InterruptedException{ 
     Game game = new Game(); 


    } 

} 

蛇類

import java.awt.Color; 
import java.awt.Graphics2D; 
import java.awt.Rectangle; 
import java.awt.event.KeyEvent; 

import javax.swing.RepaintManager; 

public class Snake { 

    public int x = 60; 
    public int y = 80; 
    public int xa = 0; 
    public int ya = 0; 
    public int speed = 20; 
    private Game game; 

    public Snake(Game game){ 
     this.game = game; 
    } 

    public void move(){ 
     x += xa; 
     y += ya; 
    } 

    public void keyPressed(KeyEvent e){ 
     //RIGHT 
     if(e.getKeyCode() == 39){ 
      xa = speed; 
      ya = 0; 
     } 
     //LEFT 
     if(e.getKeyCode() == 37){ 
      xa = -speed; 
      ya = 0; 
     } 
     //UP 
     if(e.getKeyCode() == 38){ 
      ya = -speed; 
      xa = 0; 
     } 
     //DOWN 
     if(e.getKeyCode() == 40){ 
      ya = speed; 
      xa = 0; 
     } 
     //move(); 
     //game.repaint(); 

    } 
    public Rectangle getBounds(){ 
     return new Rectangle(x, y, 20, 20); 
    } 
    public void paint(Graphics2D g2d){ 
     g2d.setColor(new Color(48, 255, 55)); 
     g2d.fillRect(x, y, 20, 20); 

    } 

} 
+3

您應該使用Swing定時器('javax.swing.Timer')而不是'java.util.Timer'。 Swing計時器設計用於Swing程序並在Swing線程上執行。 https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html – Radiodef

+0

我試過擺動定時器,我仍然無法設置足夠快的延遲以進行持續重繪 – Alex

+0

還有一些其他問題。 Swing可以處理相當高的重繪速度,即使使用被動渲染(例如從定時器調用repaint())也是如此。根據我的經驗,像Snake這樣簡單的2D遊戲可以產生高達200或300FPS的幀速率。 (限制是Swing事件隊列能夠跟上常量事件發佈的速度,以及它是否會合並重復的繪畫事件。) – Radiodef

回答

0

,你所要做的是創建一個循環所有的時間,使你的遊戲,喜歡的主題:

public void run() { 
    while (true) { 
     render(); 
    } 
} 

你的運行方法是正確的,但是你也需要擴展Thread來重新繪製一個重複的線程see this post for multithreading

有關BufferStrategy的更多信息,請參閱Tutorial。 我認爲這是很好的解釋,我用它自己。

+0

不,我一直在嘗試過去的幾天,我無法讓它工作。由於某種原因,當定時器快150毫秒左右時,我無法得到它。 while循環不起作用 – Alex

+0

你並不真正開始你的線程。看到我編輯的帖子 – pfaehlfd