2017-06-06 61 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