2013-11-17 5 views
1

Я делаю простые 2D игры. У меня есть игровой цикл, и в игровом цикле у меня есть метод . Я делаю все, добавляя 1 к xPos всякий раз, когда он зацикливается. Это означает, что если у вас медленный fps, тогда все идет медленным движением, и если у вас высокий уровень fps, все перемещается очень быстро.Как сделать тактовую частоту кадров?

Это мой код:

long fpsTimer; 
    int frames; 
    public void run(){ 
     running = true; 
     fpsTimer = System.nanoTime(); 

     while(running){ 
      render(); 
      update(); 

      try{ 
       Thread.sleep(6); 
      }catch(InterruptedException e){} 
      frames++; 

      if(System.nanoTime() >= fpsTimer+1000000000){ 
       System.out.println(frames+" fps"); 
       frames = 0; 
       fpsTimer = System.nanoTime(); 
      } 
     } 
    } 

Все Код

import java.awt.*; 
    import java.awt.image.*; 
    import javax.swing.JFrame; 
    import java.awt.event.*; 

    public class Game extends Canvas implements Runnable{ 
     public static final int WIDTH = 800; 
     public static final int HEIGHT = 300; 
     public JFrame f; 
     private String title = "Untitled Test"; 
     private Image image; 
     private Sprite player; 

     public Game(){ 
      player = new Sprite(100, 100); 
      setPreferredSize(new Dimension(WIDTH, HEIGHT)); 
      setMaximumSize(new Dimension(WIDTH, HEIGHT)); 
      setMinimumSize(new Dimension(WIDTH, HEIGHT)); 

      addKeyListener(new KeyAdapter(){ 
       public void keyPressed(KeyEvent e){ 
        player.keyPressed(e.getKeyCode()); 
       } 

       public void keyReleased(KeyEvent e){ 
        player.keyReleased(e.getKeyCode()); 
       } 
      }); 
     } 

     public static void main(String[] args){ 
      Game g = new Game(); 
      g.f = new JFrame(g.title); 
      g.f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      g.f.add(g); 
      g.f.setResizable(false); 
      g.f.pack(); 
      g.f.setLocationRelativeTo(null); 
      Thread gameLoop = new Thread(g); 
      gameLoop.start(); 
      g.f.setVisible(true); 
     } 

     private void render(){ 
      BufferStrategy bs = getBufferStrategy(); 
      if(bs==null){ 
       createBufferStrategy(3); 
       return; 
      } 

      image = createImage(WIDTH, HEIGHT); 
      Graphics g = image.getGraphics(); 

      player.draw(g); 

      g.dispose(); 
      Graphics bsg = bs.getDrawGraphics(); 
      bsg.drawImage(image, 0, 0, WIDTH, HEIGHT, null); 
      bsg.dispose(); 
      bs.show(); 
     } 

     private void update(){ 
      player.move(); 
     } 

     long fpsTime; 
     int frames; 

     public void run(){ 
      fpsTime = System.nanoTime(); 

      while(true){ 

       render(); 
       update(); 

       try{ 
        Thread.sleep(6); 
       }catch(InterruptedException e){} 

       frames++; 
       if(System.nanoTime() >= fpsTime+1000000000){ 
        System.out.println(frames+" fps"); 
        frames = 0; 
        fpsTime = System.nanoTime(); 
       } 
      } 
     } 
    } 
+0

так что вопрос здесь? –

+0

@GV, я думаю, вопрос заключается в следующем: «Как сделать тактировку кадров согласованной?» –

+0

Swing, AWT для графического интерфейса? –

ответ

2

Прежде всего вы не должны иметь постоянное время сна. Вместо этого значение должно динамически вычисляться. Возможно, его проще использовать Timer#scheduleAtFixedRate(...), потому что это уже позаботится об этом для вас.

Тогда, 6 мс на итерацию кажется слишком меньше. 60 кадров в секунду идеально (если у вас всего 30, это тоже нормально), поэтому достаточно 16 мс (или около 32 для 30 кадров в секунду). (Обратите внимание, что частота обновления вашего экрана - это верхний предел - он должен быть около 60 Гц - больше не имеет смысла).

В-третьих, подумайте о динамическом вычислении ходов ваших объектов. Вместо того, чтобы иметь постоянную дельту, которую вы добавляете к координатам, вам лучше иметь какую-то «функцию перемещения», которая вычисляет координаты на основе текущего времени.

Предположим, вы хотите переместить объект вдоль оси x с постоянной скоростью pps пикселей в секунду. Функция для х координат этого объекта будет затем:

x(t) := x0 + (t - t0) * pps/1000 

(t это время, которое прошло с момента начала в мс, x0 это начальные координаты х объекта, когда он появился первым, t0 является время, в которое появился объект, pps - количество пикселей, которое объект должен перемещать в секунду).

Это делает ваши объекты движущимися с одинаковой скоростью - независимо от того, какая частота кадров у вас есть.

Обратите внимание, что этот подход становится более сложным, если ваши объекты должны реагировать на ввод пользователя или другие события (например, столкновения и т. Д.).

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