2017-06-06 2 views
3

私は現在、ヘビを絶えず再ペイントするのに困っていますが、スネークを作ろうとしています。私はタイマーを使用しています。インターバルを150ミリ秒に設定すると動作しますが、30ミリ秒ほど速く設定しても何も表示されません。 timer 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

'java.util.Timer'の代わりにSwingタイマー(' javax.swing.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(); 
    } 
} 

あなたのrunメソッドは正しいですが、余分なスレッドで何度も何度も再描画するためにスレッドを拡張する必要がありますsee this post for multithreading

BufferStrategy以上の詳細については、Tutorialに従ってください。 私はそれが本当に説明されて良いと思う、私はそれを私の自己を使用しています。

+0

いいえ、私は最後の数日間試してきましたが、私はそれを働かせることはできません。何らかの理由で、タイマーが150ミリ秒ほど速いときにペイントすることができません。 whileループはどちらも動作しません – Alex

+0

あなたは本当にあなたのスレッドを開始しません。私の編集した記事を見る – pfaehlfd

関連する問題