欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android测量每秒帧数Frames Per Second (FPS)的方法

程序员文章站 2023-11-04 13:54:16
本文实例讲述了android测量每秒帧数frames per second (fps)的方法。分享给大家供大家参考。具体如下: mainthread.java:...

本文实例讲述了android测量每秒帧数frames per second (fps)的方法。分享给大家供大家参考。具体如下:

mainthread.java:

package net.obviam.droidz;
import java.text.decimalformat;
import android.graphics.canvas;
import android.util.log;
import android.view.surfaceholder;
/**
 * @author impaler
 *
 * the main thread which contains the game loop. the thread must have access to
 * the surface view and holder to trigger events every game tick.
 */
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++;
  // 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");
 }
}

希望本文所述对大家的java程序设计有所帮助。