JAVA图形操作中FPS的计算(附带随机生成乱数球体用例)
FPS:即帧 /秒(frames per second)的缩写,也称为帧速率。是指1秒钟时间里刷新的图片的帧数,也可以理解为图形处理器每秒钟能够刷新几次。如果具体到手机上就是指每秒钟能够 播放(或者录制)多少格画面。同时越高的帧速率可以得到更流畅、更逼真的动画。每秒钟帧数(fps)越多,所显示的动作就会越流畅。
在绝大多数图形程序中(以游戏类为典型),执行效率都以FPS作为评估标准。
由于目前JAVA方面缺少相关用例,故完成功能如下图(在本机测试中,最大fps设定为500,实际达到FPS效率在IDE中280左右,单独运行380左右,受系统配置等因素影响):
代码如下:
(请变更文件后缀为jar)

FPS相关操作代码如下:
packageorg.test;

importjava.text.DecimalFormat;


/***//**
*<p>Title:LoonFramework</p>
*<p>Description:</p>
*<p>Copyright:Copyright(c)2007</p>
*<p>Company:LoonFramework</p>
*@authorchenpeng
*@email:[email protected]
*@version0.1
*/

publicclassFPSListen...{
//设定动画的FPS桢数,此数值越高,动画速度越快。
publicstaticfinalintFPS=500;

//换算为运行周期
publicstaticfinallongPERIOD=(long)(1.0/FPS*1000000000);//单位:ns(纳秒)

//FPS最大间隔时间,换算为1s=10^9ns
publicstaticlongFPS_MAX_INTERVAL=1000000000L;//单位:ns

//实际的FPS数值
privatedoublenowFPS=0.0;

//FPS累计用间距时间
privatelonginterval=0L;//inns
privatelongtime;

//运行桢累计
privatelongframeCount=0;

//格式化小数位数
privateDecimalFormatdf=newDecimalFormat("0.0");

//开启opengl

publicvoidopengl()...{
System.setProperty("sun.java2d.opengl","True");
System.setProperty("sun.java2d.translaccel","True");
}




/***//**
*制造FPS数据
*
*/

publicvoidmakeFPS()...{
frameCount++;
interval+=PERIOD;

//当实际间隔符合时间时。

if(interval>=FPS_MAX_INTERVAL)...{
//nanoTime()返回最准确的可用系统计时器的当前值,以毫微秒为单位
longtimeNow=System.nanoTime();
//获得到目前为止的时间距离
longrealTime=timeNow-time;//单位:ns

//换算为实际的fps数值
nowFPS=((double)frameCount/realTime)*FPS_MAX_INTERVAL;
//变更数值
frameCount=0L;
interval=0L;
time=timeNow;
}
}

publiclonggetFrameCount()...{
returnframeCount;
}

publicvoidsetFrameCount(longframeCount)...{
this.frameCount=frameCount;
}

publiclonggetInterval()...{
returninterval;
}

publicvoidsetInterval(longinterval)...{
this.interval=interval;
}

publicdoublegetNowFPS()...{
returnnowFPS;
}

publicvoidsetNowFPS(doublenowFPS)...{
this.nowFPS=nowFPS;
}

publiclonggetTime()...{
returntime;
}

publicvoidsetTime(longtime)...{
this.time=time;
}

publicStringgetFPS()...{
returndf.format(nowFPS);
}

}

球体类代码如下:
packageorg.test;

importjava.awt.Color;
importjava.awt.Graphics;


/***//**
*<p>Title:LoonFramework</p>
*<p>Description:</p>
*<p>Copyright:Copyright(c)2007</p>
*<p>Company:LoonFramework</p>
*@authorchenpeng
*@email:[email protected]
*@version0.1
*/

publicclassBall...{
privatestaticfinalintSIZE=10;
privateintx,y;
protectedintvx,vy;


publicBall(intx,inty,intvx,intvy)...{
this.x=x;
this.y=y;
this.vx=vx;
this.vy=vy;
}


publicvoidmove()...{
x+=vx;
y+=vy;

if(x<0||x>BallPanel.WIDTH-SIZE)...{
vx=-vx;
}

if(y<0||y>BallPanel.HEIGHT-SIZE)...{
vy=-vy;
}
}


publicvoiddraw(Graphicsg)...{
g.setColor(Color.RED);
g.fillOval(x,y,SIZE,SIZE);
}


}

FPS及球体处理用代码如下:
packageorg.test;

importjava.awt.Color;
importjava.awt.Dimension;
importjava.awt.Frame;
importjava.awt.Graphics;
importjava.awt.Image;
importjava.awt.Panel;
importjava.awt.event.WindowAdapter;
importjava.awt.event.WindowEvent;
importjava.awt.image.BufferedImage;
importjava.util.Random;



/***//**
*<p>
*Title:LoonFramework
*</p>
*<p>
*Description:以JAVA获取FPS用演示程序及随机生成乱数球体。(更优化代码内置于loonframework-game框架中)
*</p>
*<p>
*Copyright:Copyright(c)2007
*</p>
*<p>
*Company:LoonFramework
*</p>
*
*@authorchenpeng
*@email:[email protected]
*@version0.1
*/

publicclassBallPanelextendsPanelimplementsRunnable...{


/***//**
*
*/
privatestaticfinallongserialVersionUID=1L;

publicstaticfinalintWIDTH=360;

publicstaticfinalintHEIGHT=360;

//设定最大球体数量
privatestaticfinalintNUM_BALLS=50;

//定义球体数组
privateBall[]ball;

//运行状态
privatevolatilebooleanrunning=false;

privateThreadgameLoop;

//缓存用图形
privateGraphicsbg;

privateImagescreen=null;

//生成随机数
privateRandomrand;

//fps监听
privateFPSListenfps=null;


publicBallPanel()...{
setPreferredSize(newDimension(WIDTH,HEIGHT));
screen=newBufferedImage(WIDTH,HEIGHT,1);
bg=screen.getGraphics();
fps=newFPSListen();
//fps.opengl();
//以当前毫秒生成随机数
rand=newRandom(System.currentTimeMillis());
ball=newBall[NUM_BALLS];
//初始化球体参数

for(inti=0;i<NUM_BALLS;i++)...{
intx=rand.nextInt(WIDTH);
inty=rand.nextInt(HEIGHT);
intvx=rand.nextInt(10);
intvy=rand.nextInt(10);
ball[i]=newBall(x,y,vx,vy);
}
}

//加入Notify

publicvoidaddNotify()...{
super.addNotify();
//判断循环条件是否成立

if(gameLoop==null||!running)...{
gameLoop=newThread(this);
gameLoop.start();
}
}


/***//**
*进行线程运作。
*/

publicvoidrun()...{
longbeforeTime,afterTime,timeDiff,sleepTime;
longoverSleepTime=0L;
intnoDelays=0;
//获得精确纳秒时间
beforeTime=System.nanoTime();
fps.setTime(beforeTime);
running=true;

while(running)...{
gameUpdate();
repaint();
afterTime=System.nanoTime();
timeDiff=afterTime-beforeTime;
//换算间隔时间
sleepTime=(FPSListen.PERIOD-timeDiff)-overSleepTime;

if(sleepTime>0)...{
//制造延迟

try...{
Thread.sleep(sleepTime/1000000L);//nano->ms

}catch(InterruptedExceptione)...{
}
//获得延迟时间
overSleepTime=(System.nanoTime()-afterTime)-sleepTime;

}else...{
//重新计算
overSleepTime=0L;
//判断noDelays值

if(++noDelays>=16)...{
Thread.yield();//令线程让步
noDelays=0;
}
}

//重新获得beforeTime
beforeTime=System.nanoTime();

//制造FPS结果
fps.makeFPS();
}

}


/***//**
*变更球体轨迹
*
*/

privatevoidgameUpdate()...{

for(inti=0;i<NUM_BALLS;i++)...{
ball[i].move();
}
}


/***//**
*变更图形
*/

publicvoidupdate(Graphicsg)...{
paint(g);
}


/***//**
*显示图形
*/

publicvoidpaint(Graphicsg)...{

//设定背景为白色,并清空图形
bg.setColor(Color.WHITE);
bg.fillRect(0,0,WIDTH,HEIGHT);

//FPS数值显示
bg.setColor(Color.BLUE);
bg.drawString("FPS:"+fps.getFPS(),4,16);

//分别绘制相应球体

for(inti=0;i<NUM_BALLS;i++)...{
ball[i].draw(bg);
}
g.drawImage(screen,0,0,this);
g.dispose();
}


publicstaticvoidmain(String[]args)...{

Framefrm=newFrame();
frm.setTitle("JavaFPS速度测试(由Loonframework框架提供)");
frm.setSize(WIDTH,HEIGHT+20);
frm.setResizable(false);
frm.add(newBallPanel());
frm.setVisible(true);

frm.addWindowListener(newWindowAdapter()...{

publicvoidwindowClosing(WindowEvente)...{
System.exit(0);
}
});
}

}

在绝大多数图形程序中(以游戏类为典型),执行效率都以FPS作为评估标准。
由于目前JAVA方面缺少相关用例,故完成功能如下图(在本机测试中,最大fps设定为500,实际达到FPS效率在IDE中280左右,单独运行380左右,受系统配置等因素影响):
代码如下:
FPS相关操作代码如下:
球体类代码如下:
FPS及球体处理用代码如下: