Android测量每秒帧数Frames Per Second (FPS)的方法
本文实例讲述了Android测量每秒帧数FramesPerSecond(FPS)的方法。分享给大家供大家参考。具体如下:
MainThread.java:
packagenet.obviam.droidz;
importjava.text.DecimalFormat;
importandroid.graphics.Canvas;
importandroid.util.Log;
importandroid.view.SurfaceHolder;
/**
*@authorimpaler
*
*TheMainthreadwhichcontainsthegameloop.Thethreadmusthaveaccessto
*thesurfaceviewandholdertotriggereventseverygametick.
*/
publicclassMainThreadextendsThread{
privatestaticfinalStringTAG=MainThread.class.getSimpleName();
//desiredfps
privatefinalstaticintMAX_FPS=50;
//maximumnumberofframestobeskipped
privatefinalstaticintMAX_FRAME_SKIPS=5;
//theframeperiod
privatefinalstaticintFRAME_PERIOD=1000/MAX_FPS;
//Stuffforstats*/
privateDecimalFormatdf=newDecimalFormat("0.##");//2dp
//we'llbereadingthestatseverysecond
privatefinalstaticintSTAT_INTERVAL=1000;//ms
//theaveragewillbecalculatedbystoring
//thelastnFPSs
privatefinalstaticintFPS_HISTORY_NR=10;
//lasttimethestatuswasstored
privatelonglastStatusStore=0;
//thestatustimecounter
privatelongstatusIntervalTimer=0l;
//numberofframesskippedsincethegamestarted
privatelongtotalFramesSkipped=0l;
//numberofframesskippedinastorecycle(1sec)
privatelongframesSkippedPerStatCycle=0l;
//numberofrenderedframesinaninterval
privateintframeCountPerStatCycle=0;
privatelongtotalFrameCount=0l;
//thelastFPSvalues
privatedoublefpsStore[];
//thenumberoftimesthestathasbeenread
privatelongstatsCount=0;
//theaverageFPSsincethegamestarted
privatedoubleaverageFps=0.0;
//Surfaceholderthatcanaccessthephysicalsurface
privateSurfaceHoldersurfaceHolder;
//Theactualviewthathandlesinputs
//anddrawstothesurface
privateMainGamePanelgamePanel;
//flagtoholdgamestate
privatebooleanrunning;
publicvoidsetRunning(booleanrunning){
this.running=running;
}
publicMainThread(SurfaceHoldersurfaceHolder,MainGamePanelgamePanel){
super();
this.surfaceHolder=surfaceHolder;
this.gamePanel=gamePanel;
}
@Override
publicvoidrun(){
Canvascanvas;
Log.d(TAG,"Startinggameloop");
//initialisetimingelementsforstatgathering
initTimingElements();
longbeginTime;//thetimewhenthecyclebegun
longtimeDiff;//thetimeittookforthecycletoexecute
intsleepTime;//mstosleep(<0ifwe'rebehind)
intframesSkipped;//numberofframesbeingskipped
sleepTime=0;
while(running){
canvas=null;
//trylockingthecanvasforexclusivepixelediting
//inthesurface
try{
canvas=this.surfaceHolder.lockCanvas();
synchronized(surfaceHolder){
beginTime=System.currentTimeMillis();
framesSkipped=0;//resettingtheframesskipped
//updategamestate
this.gamePanel.update();
//renderstatetothescreen
//drawsthecanvasonthepanel
this.gamePanel.render(canvas);
//calculatehowlongdidthecycletake
timeDiff=System.currentTimeMillis()-beginTime;
//calculatesleeptime
sleepTime=(int)(FRAME_PERIOD-timeDiff);
if(sleepTime>0){
//ifsleepTime>0we'reOK
try{
//sendthethreadtosleepforashortperiod
//veryusefulforbatterysaving
Thread.sleep(sleepTime);
}catch(InterruptedExceptione){}
}
while(sleepTime<0&&framesSkipped<MAX_FRAME_SKIPS){
//weneedtocatchup
this.gamePanel.update();//updatewithoutrendering
sleepTime+=FRAME_PERIOD;//addframeperiodtocheckifinnextframe
framesSkipped++;
}
if(framesSkipped>0){
Log.d(TAG,"Skipped:"+framesSkipped);
}
//forstatistics
framesSkippedPerStatCycle+=framesSkipped;
//callingtheroutinetostorethegatheredstatistics
storeStats();
}
}finally{
//incaseofanexceptionthesurfaceisnotleftin
//aninconsistentstate
if(canvas!=null){
surfaceHolder.unlockCanvasAndPost(canvas);
}
}//endfinally
}
}
/**
*Thestatistics-itiscalledeverycycle,itchecksiftimesincelast
*storeisgreaterthanthestatisticsgatheringperiod(1sec)andifso
*itcalculatestheFPSforthelastperiodandstoresit.
*
*Ittracksthenumberofframesperperiod.Thenumberofframessince
*thestartoftheperiodaresummedupandthecalculationtakespart
*onlyifthenextperiodandtheframecountisresetto0.
*/
privatevoidstoreStats(){
frameCountPerStatCycle++;
totalFrameCount++;
//checktheactualtime
statusIntervalTimer+=(System.currentTimeMillis()-statusIntervalTimer);
if(statusIntervalTimer>=lastStatusStore+STAT_INTERVAL){
//calculatetheactualframespersstatuscheckinterval
doubleactualFps=(double)(frameCountPerStatCycle/(STAT_INTERVAL/1000));
//storesthelatestfpsinthearray
fpsStore[(int)statsCount%FPS_HISTORY_NR]=actualFps;
//increasethenumberoftimesstatisticswascalculated
statsCount++;
doubletotalFps=0.0;
//sumupthestoredfpsvalues
for(inti=0;i<FPS_HISTORY_NR;i++){
totalFps+=fpsStore[i];
}
//obtaintheaverage
if(statsCount<FPS_HISTORY_NR){
//incaseofthefirst10triggers
averageFps=totalFps/statsCount;
}else{
averageFps=totalFps/FPS_HISTORY_NR;
}
//savingthenumberoftotalframesskipped
totalFramesSkipped+=framesSkippedPerStatCycle;
//resettingthecountersafterastatusrecord(1sec)
framesSkippedPerStatCycle=0;
statusIntervalTimer=0;
frameCountPerStatCycle=0;
statusIntervalTimer=System.currentTimeMillis();
lastStatusStore=statusIntervalTimer;
//Log.d(TAG,"AverageFPS:"+df.format(averageFps));
gamePanel.setAvgFps("FPS:"+df.format(averageFps));
}
}
privatevoidinitTimingElements(){
//initialisetimingelements
fpsStore=newdouble[FPS_HISTORY_NR];
for(inti=0;i<FPS_HISTORY_NR;i++){
fpsStore[i]=0.0;
}
Log.d(TAG+".initTimingElements()","Timingelementsforstatsinitialised");
}
}
希望本文所述对大家的java程序设计有所帮助。