2015-01-17 6 views
1

Я пытался создать цикл игры Java, который отображает что-то простое, но неважно, что я пытаюсь, я не могу заставить его перестать мерцать. Я пробовал решения для поиска в Google, но либо мой google-fu не совсем до нуля, либо я делаю что-то серьезно неправильно.Как вы создаете петлю игры Java без мерцания?

Я размещаю этот код здесь, надеясь, что я просто делаю что-то неправильно, что можно исправить. На данный момент у меня возникает соблазн начать разговор на другом языке, в прошлый раз, когда я использовал его, SFML был приятным. Извинения за ужасный код.

Main.java:

public class Main { 
    public static void main(String[] args) { 
     new GameFrame("Game"); 
    } 
} 

GameFrame.java:

import java.awt.Color; 
import java.awt.GraphicsDevice; 
import java.awt.GraphicsEnvironment; 
import java.awt.Insets; 
import java.awt.Toolkit; 

import javax.swing.JFrame; 

public class GameFrame extends JFrame { 
    protected GraphicsDevice device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); 

    public GameFrame(String title) { 
     super(title); 
     init(); 
    } 

    public void init() { 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 

     // Calculate the size of the window, taking into account the size of toolbars etc. 
     Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(device.getDefaultConfiguration()); 
     setSize(
      (int) ((device.getDefaultConfiguration().getBounds().width - insets.left - insets.right) * 0.8), 
      (int) ((device.getDefaultConfiguration().getBounds().height - insets.top - insets.bottom) * 0.8) 
     ); 

     // Centre and start maximised. 
     setLocationRelativeTo(null); 
     setExtendedState(MAXIMIZED_BOTH); 

     if(false) { 
      // Important otherwise you get an ugly border. 
      super.setVisible(false); 
      setUndecorated(true); 
      device.setFullScreenWindow(this); 
     } else { 
      setUndecorated(false); 
      device.setFullScreenWindow(null); 
      super.setVisible(true); 
     } 

     GamePanel panel = new GamePanel(); 

     panel.setBackground(Color.BLACK); 
     new Thread(panel).start(); 

     add(panel); 
    } 
} 

GamePanel.java:

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Image; 
import java.awt.RenderingHints; 

import javax.swing.JPanel; 

public class GamePanel extends JPanel implements Runnable { 
    protected boolean running = false; 

    protected long lastTime; 

    protected int width = 0; 
    protected int height = 0; 

    protected Image image; 
    protected Graphics2D graphics; 

    protected double x = 0; 
    protected double y = 0; 

    protected void updateState(double delta) { 
     x = x + 0.00001 * delta; 
     y = y + 0.00001 * delta; 
    } 

    public void run() { 
     running = true; 
     lastTime = System.nanoTime(); 

     while(width == 0 || height == 0) { 
      width = getBounds().width; 
      height = getBounds().height; 
     } 

     setDoubleBuffered(true); 

     while(running) { 
      long now   = System.nanoTime(); 
      long updateLength = now - lastTime; 
      double delta  = updateLength/(10^9/60); 

      updateState(delta); 

      paintComponent(getGraphics()); 

      lastTime = System.nanoTime(); 

      try {Thread.sleep((now - lastTime + (10^9/60))/(10^6));} catch (Exception e) {} 
     } 
    } 

    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 

     if(isVisible() && width > 0 && height > 0) { 

      setDoubleBuffered(true); 

      if(image == null) { 
       image = createImage(width, height); 
       graphics = (Graphics2D) image.getGraphics(); 
       graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
      } 

      graphics.setColor(Color.black); 
      graphics.fillRect(0, 0, width, height); 

      graphics.setColor(Color.WHITE); 
      graphics.fillRect(100, 20, 100, 100); 

      graphics.fillOval((int) x, (int) y, 30, 30); 

      g.drawImage(image, 0, 0, this); 
     } 
    } 
} 

ответ

3

ваших фрагментов программ неверны несколькими способами:

  • Качели GUI объекты должны быть сконструированы и обработаны только на event dispatch thread.

  • Не использовать getGraphics(); графический контекст только действительный в paintComponent().

  • JPanel по умолчанию двойной буфер.

  • Использовать экземпляр javax.swing.Timer для ускорения анимации; полный пример показан в этом AnimationTest.

+0

Если я не могу использовать getGraphics(), как бы вы предположили слишком сильное графическое обновление. Насколько мне известно, repaint() просто останавливает обновление. –

+0

@Matt: Вы можете посмотреть на 'paintImmediately()', но я обычно полагаюсь на подходы, показанные здесь [http://stackoverflow.com/a/11835051/230513] и [здесь] (http: /stackoverflow.com/a/3072979/230513). – trashgod

 Смежные вопросы

  • Нет связанных вопросов^_^