2012-07-31 58 views
2

創建遊戲循環我跟着this excellent tutorial。但是我認爲下一個顯示FPS的教程有點不確定,所以我試着單飛。我對我製作的trackFps()方法有信心;它在計算幀之間的時間差之後被調用,在每次運行時測量預測的FPS,將這些預測的FPS值存儲在ArrayList中,然後每秒一次加上那些預測的FPS併除以所添加的值的數量以得到平均FPS 。如何計算我的空遊戲中的FPS?

當我通過它與它的功能精細調試器中運行,但是當我通過它運行正常,我得到以下異常:

FATAL EXCEPTION: Thread-11 
java.lang.IndexOutOfBoundsException: Invalid index 26, size is 6 
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:257) 
at java.util.ArrayList.get(ArrayList.java:311) 
at biz.hireholly.engine.GameLoop.trackFps(GameLoop.java:120) 
at biz.hireholly.engine.GameLoop.run(GameLoop.java:73) 

這是很說明和發生在這條線fps += fpsStore.get(fpsTrackCount-1);。但是我看不到fpsTrackCount變量的變化可能高達26,它應該只與存儲在ArrayListfpsStore中的變量的數量一樣高。

有人會看我的GameLoop班,特別是底部的trackFps()方法嗎?我會提供整個事情。它有很多評論,但沒有太多的東西,對於你們中的一些人應該非常熟悉。

GameLoop(包含在底部計算的FPS trackFps()法):

package biz.hireholly.engine; 

import android.graphics.Canvas; 
import android.view.SurfaceHolder; 
import java.util.ArrayList; 


/** 
* The GameLoop is a thread that will ensure updating and drawing is done at set intervals. 
* The thread will sleep when it has updated/rendered quicker than needed to reach the desired fps. 
* The loop is designed to skip drawing if the update/draw cycle is taking to long, up to a MAX_FRAME_SKIPS. 
* The Canvas object is created and managed to some extent in the game loop, 
* this is so that we can prevent multiple objects trying to draw to it simultaneously. 
* Note that the gameloop has a reference to the gameview and vice versa. 
*/ 

public class GameLoop extends Thread { 

    private static final String TAG = GameLoop.class.getSimpleName(); 
    //desired frames per second 
    private final static int MAX_FPS = 30; 
    //maximum number of drawn frames to be skipped if drawing took too long last cycle 
    private final static int MAX_FRAME_SKIPS = 5; 
    //ideal time taken to update & draw 
    private final static int CYCLE_PERIOD = 1000/MAX_FPS; 

    private SurfaceHolder surfaceHolder; 
    //the gameview actually handles inputs and draws to the surface 
    private GameView gameview; 

    private boolean running; 
    private long beginTime = 0; // time when cycle began 
    private long timeDifference = 0; // time it took for the cycle to execute 
    private int sleepTime = 0; // milliseconds to sleep (<0 if drawing behind schedule) 
    private int framesSkipped = 0; // number of render frames skipped 

    private double lastFps = 0; //The last FPS tracked, the number displayed onscreen 
    private int fpsTrackCount = 1; // number we'll divide the fpsSTore by to get average 
    private ArrayList<Double> fpsStore = new ArrayList<Double>(); //For the previous fps values 
    private long lastTimeFpsCalculated = System.currentTimeMillis(); //used in trackFps 

    public GameLoop(SurfaceHolder holder, GameView gameview) { 
     super(); 
     this.surfaceHolder = holder; 
     this.gameview = gameview; 
    } 

    public void setRunning(boolean running) { 
     this.running = running;  
    } 
    @Override 
    public void run(){ 

     Canvas c; 

     while (running) { 
      c = null; 
      //try locking canvas, so only we can edit pixels on surface 
      try{ 
       c = this.surfaceHolder.lockCanvas(); 
       //sync so nothing else can modify while were using it 
       synchronized (surfaceHolder){ 

        beginTime = System.currentTimeMillis(); 
        framesSkipped = 0; //reset frame skips 

        this.gameview.update(); 
        this.gameview.draw(c); 

        //calculate how long cycle took 
        timeDifference = System.currentTimeMillis() - beginTime; 
        //good time to trackFps? 
        trackFps(); 

        //calculate potential sleep time 
        sleepTime = (int)(CYCLE_PERIOD - timeDifference); 

        //sleep for remaining cycle 
        if (sleepTime >0){ 
         try{ 
          Thread.sleep(sleepTime); //saves battery! :) 
         } catch (InterruptedException e){} 
        } 
        //if sleepTime negative then we're running behind 
        while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS){ 
         //update without rendering to catch up 
         this.gameview.update(); 
         //skip as many frame renders as needed to get back into 
         //positive sleepTime and continue as normal 
         sleepTime += CYCLE_PERIOD; 
         framesSkipped++; 
        } 

       } 

      } finally{ 
       //finally executes regardless of exception, 
       //so surface is not left in an inconsistent state 
       if (c != null){ 
        surfaceHolder.unlockCanvasAndPost(c); 
       } 
      } 
     } 

    } 

    /* Calculates the average fps every second */ 
    private void trackFps(){ 
     long currentTime = System.currentTimeMillis(); 

     if(timeDifference != 0){ 
      fpsStore.add((double)(1000/timeDifference)); 
     } 
     //If a second has past since last time average was calculated, 
     // it's time to calculate a new average fps to display 
     if ((currentTime - 1000) > lastTimeFpsCalculated){ 
      int fps = 0; 
      int toDivideBy = fpsTrackCount; 
      while ((fpsStore != null) && (fpsTrackCount > 0)){ 
       fps += fpsStore.get(fpsTrackCount-1); 
       fpsTrackCount--; 
      } 
      lastFps = fps/toDivideBy; 
      lastTimeFpsCalculated = System.currentTimeMillis(); 
      fpsTrackCount = 1; 
      fpsStore.clear(); 
     } 
     else{ 
     fpsTrackCount++; 
     } 
    } 
    /* So That it can be drawn in the gameview */ 
    public String getFps() { 
     return String.valueOf(lastFps); 
    } 

} 
+0

我沒有看到你的TextDrawable電話,您可以張貼在您使用它來繪製的FPS值的代碼?啊,找到它了。 – Shark 2012-07-31 11:32:31

+0

對不起,那是在我上傳到Pastebin的GameView上,因爲我不想讓我的問題混亂。 – Holly 2012-07-31 11:51:02

回答

-4

我覺得這個代碼應該爲你工作

cputhrottle=(int) System.currentTimeMillis(); 
cputhrottle = (int)System.currentTimeMillis() - cputhrottle;cputhrottle=33-cputhrottle; 

其30幀每秒將是有益給你

+1

對不起,但這個答案需要一些更多的解釋,雖然它相關,我不知道它真的在回答我的問題。 – Holly 2012-07-31 11:25:18

2

好的,讓我們先看看...

java.lang.IndexOutOfBoundsException: Invalid index 26, size is 6 
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:257) 
at java.util.ArrayList.get(ArrayList.java:311) 
at biz.hireholly.engine.GameLoop.trackFps(GameLoop.java:120) 

在trackFPS所以某處的get()是荒謬出界...

private void trackFps() 
{ 
    long currentTime = System.currentTimeMillis(); 

    if(timeDifference != 0) 
    { 
     fpsStore.add((double)(1000/timeDifference)); 
    } 
    //If a second has past since last time average was calculated, 
    // it's time to calculate a new average fps to display 
    if ((currentTime - 1000) > lastTimeFpsCalculated) 
    { 
     int fps = 0; 
     int toDivideBy = fpsTrackCount; 
     while ((fpsStore != null || !fpsStore.isEmpty()) && (fpsTrackCount > 0) && (fpsTrackCount < fpsStore.getCount())) 
     { 
      //synchronized(this) { 
      fps += fpsStore.get(fpsTrackCount-1); 
      fpsStore.remove(fpsTrackCount-1); //otherwise we'll get stuck because of getCount condition 
      fpsTrackCount--; 
      //} 
     } 
     lastFps = fps/toDivideBy; 
     lastTimeFpsCalculated = System.currentTimeMillis(); 
     //fpsTrackCount = 1; 
     //fpsStore.clear(); 
     Log.d("trackFPS()", "fpsTrackCount = "+fpsTrackCount+"\tfpsStore.size() = "+fpsStore.size()+"\t"+fpsStore.toString()); 
    } 
    else 
     fpsTrackCount++; 
} 

給這個旋轉。如果它表現不佳,請嘗試取消註釋同步塊。

至於你的其他問題,有關TextDrawable,我看看你的GameView ...

這裏就是我在SurfaceChanged()foudn

fps = new TextDrawable(); 
    fps.setText("HELLO"); 

現在,爲什麼不你將它移動到SurfaceCreated()?也許你會得到很多的surfaceChanged()回調,但沒有意識到它,因爲你沒有Logcat調用? :)它是唯一可以從我所看到的TextDrawable實例化的地方。

+0

非常感謝您花時間!首先這是日誌的結果,不是真的我想要它打印http://i.imgur.com/D2sG7.jpg。我認爲'fpsTrackCount = 1'這一行應該仍然可以保留。當我通過日誌輸出沒有更好的評論時,它只顯示fpsTrackCount爲1,而fpsStore仍然有數字500和1000在上面的圖片中。關於將初始化位移動到SurfaceCreated的好處,但我恐怕仍然在屏幕上看到重疊數字的模糊,所以我不確定這是什麼原因。感謝您的幫助! – Holly 2012-07-31 11:48:29

+0

也.getCount()沒有被識別,我認爲它應該是.size()? – Holly 2012-07-31 11:49:46

+0

yes :) size()...至於TextDrawable,可能是這樣的... canvas.drawColor(Color.TRANSPARENT,PorterDuff.Mode.CLEAR); 我已經稍微編輯。 – Shark 2012-07-31 11:54:04

1

您還可以使用android play store中的應用程序來測量FPS。最近發佈的一款非常不錯的應用是GameBench。它不僅捕捉FPS,還捕捉截圖,以便您瞭解FPS掉落時發生了什麼。它也提供了CPU使用率以及某些設備的GPU使用率。我相信你會發現它很有用。

Link是this