2014-09-27 60 views
0

你能幫助我嗎,我如何計算並在我的動畫中顯示fps? 我只想顯示簡單的矩形(例如)。JAVA簡單的fps動畫(我該如何處理?)

如果我有代碼:

private final FPS = 30; 
private final SIZE = 10; 
private int x = 10; 
private int y = 0; 
private String myFps; 

private void start(){ 
    while(true){ 
     moveRect(); 
     paint(); 
    } 
} 

private void paint(){ 
    g2.drawRect(x, y, SIZE, SIZE); 
    g2.drawString(myFps, 10, 10); 
} 

private void moveRect(){ 
    x++; 
} 

回答

1

這是我很老了簡單的Java圖形+ BufferStrategy中gameloop測試應用程序的copypaste。動畫循環繪製幾個移動矩形和fps計數器。

java命令./lib/test.jar GameLoop2 「全屏=假」 「FPS = 60」 「VSYNC =真正的」

//http://www.javagaming.org/index.php/topic,19971.0.html 
//http://fivedots.coe.psu.ac.th/~ad/jg/ch1/ch1.pdf 

import java.util.*; 

import java.awt.Color; 
import java.awt.Frame; 
import java.awt.Graphics; 
import java.awt.GraphicsConfiguration; 
import java.awt.GraphicsDevice; 
import java.awt.GraphicsEnvironment; 
import java.awt.Toolkit; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 
import java.awt.geom.Rectangle2D; 
import java.awt.image.BufferStrategy; 

import java.awt.DisplayMode; // for full-screen mode 

public class GameLoop2 implements KeyListener { 
    Frame mainFrame; 

    private static final long NANO_IN_MILLI = 1000000L; 

    // num of iterations with a sleep delay of 0ms before 
    // game loop yields to other threads. 
    private static final int NO_DELAYS_PER_YIELD = 16; 

    // max num of renderings that can be skipped in one game loop, 
    // game's internal state is updated but not rendered on screen. 
    private static int MAX_RENDER_SKIPS = 5; 

    private static int TARGET_FPS = 60; 

    //private long prevStatsTime; 
    private long gameStartTime; 
    private long curRenderTime; 
    private long rendersSkipped = 0L; 
    private long period; // period between rendering in nanosecs 

    long fps; 
    long frameCounter; 
    long lastFpsTime; 

    Rectangle2D rect, rect2, rect3; 

    /** 
    * Create a new GameLoop that will use the specified GraphicsDevice. 
    * 
    * @param device 
    */ 
    public GameLoop2(Map<String,String> args, GraphicsDevice device) { 
     try { 
      if (args.containsKey("fps")) 
       TARGET_FPS = Integer.parseInt(args.get("fps")); 


      // Setup the frame 
      GraphicsConfiguration gc = device.getDefaultConfiguration(); 

      mainFrame = new Frame(gc); 
      //mainFrame.setUndecorated(true); 
      mainFrame.setIgnoreRepaint(true); 
      mainFrame.setVisible(true); 
      mainFrame.setSize(640, 480); 
      //mainFrame.setLocationRelativeTo(); 
      mainFrame.setLocation(700,100); 
      mainFrame.createBufferStrategy(2); 
      mainFrame.addKeyListener(this); 

      if ("true".equalsIgnoreCase(args.get("fullscreen"))) { 
       device.setFullScreenWindow(mainFrame); 
       device.setDisplayMode(new DisplayMode(640, 480, 8, DisplayMode.REFRESH_RATE_UNKNOWN)); 
      } 

      final boolean VSYNC = "true".equalsIgnoreCase(args.get("vsync")); 

      // Cache the buffer strategy and create a rectangle to move 
      BufferStrategy bufferStrategy = mainFrame.getBufferStrategy(); 

      rect = new Rectangle2D.Float(0,100, 64,64); 
      rect2 = new Rectangle2D.Float(0,200, 32,32); 
      rect3 = new Rectangle2D.Float(500,300, 128,128); 

      // loop initialization 
      long beforeTime, afterTime, timeDiff, sleepTime; 
      long overSleepTime = 0L; 
      int noDelays = 0; 
      long excess = 0L; 
      gameStartTime = System.nanoTime(); 
      //prevStatsTime = gameStartTime; 
      beforeTime = gameStartTime; 

      period = (1000L*NANO_IN_MILLI)/TARGET_FPS; // rendering FPS (nanosecs/targetFPS) 
      System.out.println("FPS: " + TARGET_FPS + ", vsync=" + VSYNC); 
      System.out.println("FPS period: " + period); 


      // Main loop 
      while(true) { 
       // **2) execute physics 
       updateWorld(0);     

       // **1) execute drawing 
       Graphics g = bufferStrategy.getDrawGraphics(); 
       drawScreen(g); 
       g.dispose(); 

       // Synchronise with the display hardware. Note that on 
       // Windows Vista this method may cause your screen to flash. 
       // If that bothers you, just comment it out. 
       if (VSYNC) Toolkit.getDefaultToolkit().sync(); 

       // Flip the buffer 
       if(!bufferStrategy.contentsLost()) 
        bufferStrategy.show(); 

       afterTime = System.nanoTime(); 
       curRenderTime = afterTime; 
       calculateFramesPerSecond(); 

       timeDiff = afterTime - beforeTime; 
       sleepTime = (period-timeDiff) - overSleepTime; 
       if (sleepTime > 0) { // time left in cycle 
        //System.out.println("sleepTime: " + (sleepTime/NANO_IN_MILLI)); 
        try { 
        Thread.sleep(sleepTime/NANO_IN_MILLI);//nano->ms 
        } catch(InterruptedException ex){} 
        overSleepTime = (System.nanoTime()-afterTime) - sleepTime; 
       } else { // sleepTime <= 0; 
        System.out.println("Rendering too slow"); 
        // this cycle took longer than period 
        excess -= sleepTime; 
        // store excess time value 
        overSleepTime = 0L; 
        if (++noDelays >= NO_DELAYS_PER_YIELD) { 
        Thread.yield(); 
        // give another thread a chance to run 
        noDelays = 0; 
        } 
       } 

       beforeTime = System.nanoTime(); 

       /* If the rendering is taking too long, then 
        update the game state without rendering 
        it, to get the UPS nearer to the 
        required frame rate. */ 
       int skips = 0; 
       while((excess > period) && (skips < MAX_RENDER_SKIPS)) { 
        // update state but don’t render 
        System.out.println("Skip renderFPS, run updateFPS"); 
        excess -= period; 
        updateWorld(0); 
        skips++; 
       } 
       rendersSkipped += skips; 
      } 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } finally { 
      device.setFullScreenWindow(null); 
     } 
    } 

    private void updateWorld(long elapsedTime) { 
     // speed: 150 pixels per second 
     //double xMov = (140f/(NANO_IN_MILLI*1000)) * elapsedTime; 
     double posX = rect.getX() + (140f/TARGET_FPS); 
    if (posX > mainFrame.getWidth()) 
     posX = -rect.getWidth();  
    rect.setRect(posX, rect.getY(), rect.getWidth(), rect.getHeight()); 

     posX = rect2.getX() + (190f/TARGET_FPS); 
    if (posX > mainFrame.getWidth()) 
     posX = -rect2.getWidth(); 
    rect2.setRect(posX, rect2.getY(), rect2.getWidth(), rect2.getHeight());   

     posX = rect3.getX() - (300f/TARGET_FPS); 
    if (posX < -rect3.getWidth()) 
     posX = mainFrame.getWidth(); 
    rect3.setRect(posX, rect3.getY(), rect3.getWidth(), rect3.getHeight());   

    } 

    private void drawScreen(Graphics g) { 
     g.setColor(Color.BLACK); 
     g.fillRect(0, 0, mainFrame.getWidth(), mainFrame.getHeight()); 
     g.setColor(Color.WHITE); 
     g.drawString("FPS: " + fps, 40, 50); 

     g.setColor(Color.RED); 
     g.fillRect((int)rect.getX(), (int)rect.getY(), (int)rect.getWidth(), (int)rect.getHeight()); 

     g.setColor(Color.GREEN); 
     g.fillRect((int)rect2.getX(), (int)rect2.getY(), (int)rect2.getWidth(), (int)rect2.getHeight()); 

     g.setColor(Color.BLUE); 
     g.fillRect((int)rect3.getX(), (int)rect3.getY(), (int)rect3.getWidth(), (int)rect3.getHeight()); 
    } 

    private void calculateFramesPerSecond() { 
     if(curRenderTime - lastFpsTime >= NANO_IN_MILLI*1000) { 
      fps = frameCounter; 
      frameCounter = 0; 
      lastFpsTime = curRenderTime; 
     } 
     frameCounter++; 
    } 

    public void keyPressed(KeyEvent e) { 
     if(e.getKeyCode() == KeyEvent.VK_ESCAPE) { 
      System.exit(0); 
     } 
    } 

    public void keyReleased(KeyEvent e) { } 
    public void keyTyped(KeyEvent e) { } 

    public static void main(String[] args) { 
     try { 
     Map<String,String> mapArgs = parseArguments(args); 

      GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); 
      GraphicsDevice device = env.getDefaultScreenDevice(); 
      new GameLoop2(mapArgs, device); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 


    /** 
    * Parse commandline arguments, each parameter is a name-value pair. 
    * Example: java.exe MyApp "key1=value1" "key2=value2" 
    */ 
    private static Map<String,String> parseArguments(String[] args) { 
     Map<String,String> mapArgs = new HashMap<String,String>(); 

     for(int idx=0; idx < args.length; idx++) { 
      String val = args[idx]; 
      int delimIdx = val.indexOf('='); 
      if (delimIdx < 0) { 
       mapArgs.put(val, null); 
      } else if (delimIdx == 0) { 
       mapArgs.put("", val.substring(1)); 
      } else { 
       mapArgs.put(
        val.substring(0, delimIdx).trim(), 
        val.substring(delimIdx+1) 
       ); 
      } 
     } 

     return mapArgs; 
    } 

} 
+0

謝謝你,如果我想表現出實際的FPS ,我可以在哪裏找到它?在'長時間幀'中;' ? – user3784463 2014-09-27 11:00:04

+0

請參閱drawScreen和calculateFramesPerSecond函數。我每秒更新一次「long fps」變量。它的值在每個渲染步驟的屏幕上繪製。 – Whome 2014-09-27 11:08:19