2012-07-02 167 views
0

我知道這個問題上有很多帖子,但沒有真正幫助我解決我的問題。我相當新的android編程和建立我的線程與教程helt,問題是,我的模擬器dosnt超過15 fps和程序應運行在50(FPS初始化爲50)。下面是我的線程代碼:不好的FPS與android SurfaceView

public class MainThread extends Thread { 

private static final String TAG = MainThread.class.getSimpleName(); 

// desired fps 
private final static int MAX_FPS = 50; 
// maximum number of frames to be skipped 
private final static int MAX_FRAME_SKIPS = 5; 
// the frame period 
private final static int FRAME_PERIOD = 1000/MAX_FPS; 

/* Stuff for stats */ 
private DecimalFormat df = new DecimalFormat("0.##"); // 2 dp 
// we'll be reading the stats every second 
private final static int STAT_INTERVAL = 1000; // ms 
// the average will be calculated by storing 
// the last n FPSs 
private final static int FPS_HISTORY_NR = 10; 
// last time the status was stored 
private long lastStatusStore = 0; 
// the status time counter 
private long statusIntervalTimer = 0l; 
// number of frames skipped since the game started 
private long totalFramesSkipped = 0l; 
// number of frames skipped in a store cycle (1 sec) 
private long framesSkippedPerStatCycle = 0l; 

// number of rendered frames in an interval 
private int frameCountPerStatCycle = 0; 
private long totalFrameCount = 0l; 
// the last FPS values 
private double fpsStore[]; 
// the number of times the stat has been read 
private long statsCount = 0; 
// the average FPS since the game started 
private double averageFps = 0.0; 

// Surface holder that can access the physical surface 
private SurfaceHolder surfaceHolder; 
// The actual view that handles inputs 
// and draws to the surface 
private MainGamePanel gamePanel; 

// flag to hold game state 
private boolean running; 

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

public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) { 
    super(); 
    this.surfaceHolder = surfaceHolder; 
    this.gamePanel = gamePanel; 
} 

@Override 
public void run() { 
    Canvas canvas; 
    Log.d(TAG, "Starting game loop"); 
    // initialise timing elements for stat gathering 
    initTimingElements(); 

    long beginTime; // the time when the cycle begun 
    long timeDiff; // the time it took for the cycle to execute 
    int sleepTime; // ms to sleep (<0 if we're behind) 
    int framesSkipped; // number of frames being skipped 

    sleepTime = 0; 

    while (running) { 
     canvas = null; 
     // try locking the canvas for exclusive pixel editing 
     // in the surface 
     try { 
      canvas = this.surfaceHolder.lockCanvas(); 
      synchronized (surfaceHolder) { 
       beginTime = System.currentTimeMillis(); 
       framesSkipped = 0; // resetting the frames skipped 
       // update game state 
       this.gamePanel.update(); 
       // render state to the screen 
       // draws the canvas on the panel 
       this.gamePanel.render(canvas); 
       // calculate how long did the cycle take 
       timeDiff = System.currentTimeMillis() - beginTime; 
       // calculate sleep time 
       sleepTime = (int) (FRAME_PERIOD - timeDiff); 

       if (sleepTime > 0) { 
        // if sleepTime > 0 we're OK 
        try { 
         // send the thread to sleep for a short period 
         // very useful for battery saving 
         Thread.sleep(sleepTime); 
        } catch (InterruptedException e) { 
        } 
       } 

       while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) { 
        // we need to catch up 
        this.gamePanel.update(); // update without rendering 
        sleepTime += FRAME_PERIOD; // add frame period to check 
               // if in next frame 
        framesSkipped++; 
       } 

       if (framesSkipped > 0) { 
        Log.d(TAG, "Skipped:" + framesSkipped); 
       } 
       // for statistics 
       framesSkippedPerStatCycle += framesSkipped; 
       // calling the routine to store the gathered statistics 
       storeStats(); 
      } 
     } finally { 
      // in case of an exception the surface is not left in 
      // an inconsistent state 
      if (canvas != null) { 
       surfaceHolder.unlockCanvasAndPost(canvas); 
      } 
     } // end finally 
    } 
} 

/** 
* The statistics - it is called every cycle, it checks if time since last 
* store is greater than the statistics gathering period (1 sec) and if so 
* it calculates the FPS for the last period and stores it. 
* 
* It tracks the number of frames per period. The number of frames since the 
* start of the period are summed up and the calculation takes part only if 
* the next period and the frame count is reset to 0. 
*/ 
private void storeStats() { 
    frameCountPerStatCycle++; 
    totalFrameCount++; 
    // assuming that the sleep works each call to storeStats 
    // happens at 1000/FPS so we just add it up 
    // statusIntervalTimer += FRAME_PERIOD; 

    // check the actual time 
    statusIntervalTimer += (System.currentTimeMillis() - statusIntervalTimer); 

    if (statusIntervalTimer >= lastStatusStore + STAT_INTERVAL) { 
     // calculate the actual frames pers status check interval 
     double actualFps = (double) (frameCountPerStatCycle/(STAT_INTERVAL/1000)); 

     // stores the latest fps in the array 
     fpsStore[(int) statsCount % FPS_HISTORY_NR] = actualFps; 

     // increase the number of times statistics was calculated 
     statsCount++; 

     double totalFps = 0.0; 
     // sum up the stored fps values 
     for (int i = 0; i < FPS_HISTORY_NR; i++) { 
      totalFps += fpsStore[i]; 
     } 

     // obtain the average 
     if (statsCount < FPS_HISTORY_NR) { 
      // in case of the first 10 triggers 
      averageFps = totalFps/statsCount; 
     } else { 
      averageFps = totalFps/FPS_HISTORY_NR; 
     } 
     // saving the number of total frames skipped 
     totalFramesSkipped += framesSkippedPerStatCycle; 
     // resetting the counters after a status record (1 sec) 
     framesSkippedPerStatCycle = 0; 
     statusIntervalTimer = 0; 
     frameCountPerStatCycle = 0; 

     statusIntervalTimer = System.currentTimeMillis(); 
     lastStatusStore = statusIntervalTimer; 
     // Log.d(TAG, "Average FPS:" + df.format(averageFps)); 
     gamePanel.setAvgFps("FPS: " + df.format(averageFps)); 
    } 
} 

private void initTimingElements() { 
    // initialise timing elements 
    fpsStore = new double[FPS_HISTORY_NR]; 
    for (int i = 0; i < FPS_HISTORY_NR; i++) { 
     fpsStore[i] = 0.0; 
    } 
    Log.d(TAG + ".initTimingElements()", 
      "Timing elements for stats initialised"); 
} 

}

我所有的繪製方法是這樣的:

public void render(Canvas canvas) { 
    canvas.drawColor(Color.BLACK); 
    happy.draw(canvas); 
    // display fps 
    displayFps(canvas, avgFps); 

有一些更新,在那裏藏漢但是那只是爲了讓我的精靈移動。如果any1可以看到問題或有任何提示,請讓我知道。 謝謝! }

+0

您應該在設備上測試它。仿真器可以....好,不好模擬,尤其是在性能比較方面。 – Geobits

+0

仿真器在仿真中不錯...它*是*仿真。它不是一個模擬器。 Geobits是正確的,但你不能依靠模擬器中的性能測試。 – edthethird

+0

謝謝你的快速回答:)我在想同樣的事情,但只是想知道我的g-loop是否有什麼問題,因爲我對這個很新鮮。 –

回答

0

不要依賴您的仿真器進行性能基準測試。雖然模擬器可以檢查應用程序的功能和正確性,但是執行某些操作所需的時間可能會比真實設備多(或更少)。在仿真程序中,特定的繪圖操作似乎更長。我在仿真器上以9-16 fps的速度運行遊戲,而在舊的真實設備上運行50+。

如果您的應用/遊戲在真實設備上仍然運行速度過慢,您可以對您的應用進行配置(例如使用TraceView),以準確查看所有時間都在佔用的內容,並嘗試優化或刪除它(如果可能)。

就像一個額外的提示:如果可能的話,嘗試讓你的surfaceView格式與其上的所有資源相同,並嘗試預先調整你可以預先設置的所有內容(無論是在編譯時還是在應用程序啓動/初始化階段),縮放和轉換都是昂貴的操作來完成每一幀。

0

如果使用Windows,你可以試試BlueStacks。以下是我的一些結果:

***************************************************** 
    ARM Emulator 2.4 GHz Core 2 Duo 

Android Java OpenGL Benchmark 06-Mar-2013 21.17 

      --------- Frames Per Second -------- 
Triangles WireFrame Shaded Shaded+ Textured 

    9000+  2.66  3.97  3.29  1.61 
    18000+  1.48  1.84  1.72  0.88 
    36000+  0.82  0.95  0.87  0.46 

     Screen Pixels 320 Wide 480 High 


***************************************************** 
     BlueStacks Emulator on 3 GHz Phenom 

Android Java OpenGL Benchmark 06-Mar-2013 21.25 

      --------- Frames Per Second -------- 
Triangles WireFrame Shaded Shaded+ Textured 

    9000+  41.72 42.02 32.90 20.72 
    18000+  22.11 22.09 19.28 11.58 
    36000+  11.16 11.14 10.35  5.89 

     Screen Pixels 1024 Wide 600 High 

***************************************************** 
    Samsung EXYNOS 5250 Dual 2.0 GHz Cortex-A15, Android 4.2.2 
      Mali-T604 Quad Core GPU 

Android Java OpenGL Benchmark 09-Aug-2013 09.42 

      --------- Frames Per Second -------- 
Triangles WireFrame Shaded Shaded+ Textured 

    9000+  39.13 41.52 32.19 27.25 
    18000+  22.03 20.73 19.69 16.30 
    36000+  12.24 12.23 10.75  8.68 

     Screen Pixels 1920 Wide 1032 High