FPS:即幀 /秒(frames per second)的縮寫,也稱為幀速率。是指1秒鐘時間裡重新整理的圖檔的幀數,也可以了解為圖形處理器每秒鐘能夠重新整理幾次。如果具體到手機上就是指每秒鐘能夠 播放(或者錄制)多少格畫面。同時越高的幀速率可以得到更流暢、更逼真的動畫。每秒鐘幀數(fps)越多,所顯示的動作就會越流暢。
在絕大多數圖形程式中(以遊戲類為典型),執行效率都以FPS作為評估标準。
由于目前JAVA方面缺少相關用例,故完成功能如下圖(在本機測試中,最大fps設定為500,實際達到FPS效率在IDE中280左右,單獨運作380左右,受系統配置等因素影響):
代碼如下:(請變更檔案字尾為jar)
FPS部分相關源碼:
package org.test;
import java.text.DecimalFormat;
/**
* <p>Title: LoonFramework</p>
* <p>Description:</p>
* <p>Copyright: Copyright (c) 2007</p>
* <p>Company: LoonFramework</p>
* @author chenpeng
* @email:[email][email protected][/email]
* @version 0.1
*/
public class FPSListen {
//設定動畫的FPS桢數,此數值越高,動畫速度越快。
public static final int FPS = 500;
// 換算為運作周期
public static final long PERIOD = (long) (1.0 / FPS * 1000000000); // 機關: ns(納秒)
// FPS最大間隔時間,換算為1s = 10^9ns
public static long FPS_MAX_INTERVAL = 1000000000L; // 機關: ns
// 實際的FPS數值
private double nowFPS = 0.0;
// FPS累計用間距時間
private long interval = 0L; // in ns
private long time;
//運作桢累計
private long frameCount = 0;
//格式化小數位數
private DecimalFormat df = new DecimalFormat("0.0");
//開啟opengl
public void opengl(){
System.setProperty("sun.java2d.opengl", "True");
System.setProperty("sun.java2d.translaccel", "True");
}
/** *//**
* 制造FPS資料
*
*/
public void makeFPS() {
frameCount++;
interval += PERIOD;
//當實際間隔符合時間時。
if (interval >= FPS_MAX_INTERVAL) {
//nanoTime()傳回最準确的可用系統計時器的目前值,以毫微秒為機關
long timeNow = System.nanoTime();
// 獲得到目前為止的時間距離
long realTime = timeNow - time; // 機關: ns
//換算為實際的fps數值
nowFPS = ((double) frameCount / realTime) * FPS_MAX_INTERVAL;
//變更數值
frameCount = 0L;
interval = 0L;
time = timeNow;
}
public long getFrameCount() {
return frameCount;
public void setFrameCount(long frameCount) {
this.frameCount = frameCount;
public long getInterval() {
return interval;
public void setInterval(long interval) {
this.interval = interval;
public double getNowFPS() {
return nowFPS;
public void setNowFPS(double nowFPS) {
this.nowFPS = nowFPS;
public long getTime() {
return time;
public void setTime(long time) {
this.time = time;
public String getFPS(){
return df.format(nowFPS);
}
球體類相關代碼:
import java.awt.Color;
import java.awt.Graphics;
/** *//**
public class Ball {
private static final int SIZE = 10;
private int x, y;
protected int vx, vy;
public Ball(int x, int y, int vx, int vy) {
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
public void move() {
x += vx;
y += vy;
if (x < 0 || x > BallPanel.WIDTH - SIZE) {
vx = -vx;
}
if (y < 0 || y > BallPanel.HEIGHT - SIZE) {
vy = -vy;
public void draw(Graphics g) {
g.setColor(Color.RED);
g.fillOval(x, y, SIZE, SIZE);
FPS及球體處理用代碼如下:
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Image;
import java.awt.Panel;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.util.Random;
* <p>
* Title: LoonFramework
* </p>
* Description:以JAVA擷取FPS用示範程式及随機生成亂數球體。(更優化代碼内置于loonframework-game架構中)
* Copyright: Copyright (c) 2007
* Company: LoonFramework
*
* @author chenpeng
* @email:[email][email protected][/email]
public class BallPanel extends Panel implements Runnable {
private static final long serialVersionUID = 1L;
public static final int WIDTH = 360;
public static final int HEIGHT = 360;
// 設定最大球體數量
private static final int NUM_BALLS = 50;
// 定義球體數組
private Ball[] ball;
// 運作狀态
private volatile boolean running = false;
private Thread gameLoop;
// 緩存用圖形
private Graphics bg;
private Image screen = null;
// 生成随機數
private Random rand;
// fps監聽
private FPSListen fps = null;
public BallPanel() {
setPreferredSize(new Dimension(WIDTH, HEIGHT));
screen = new BufferedImage(WIDTH, HEIGHT, 1);
bg = screen.getGraphics();
fps = new FPSListen();
//fps.opengl();
// 以目前毫秒生成随機數
rand = new Random(System.currentTimeMillis());
ball = new Ball[NUM_BALLS];
// 初始化球體參數
for (int i = 0; i < NUM_BALLS; i++) {
int x = rand.nextInt(WIDTH);
int y = rand.nextInt(HEIGHT);
int vx = rand.nextInt(10);
int vy = rand.nextInt(10);
ball[i] = new Ball(x, y, vx, vy);
// 加入Notify
public void addNotify() {
super.addNotify();
// 判斷循環條件是否成立
if (gameLoop == null || !running) {
gameLoop = new Thread(this);
gameLoop.start();
* 進行線程運作。
public void run() {
long beforeTime, afterTime, timeDiff, sleepTime;
long overSleepTime = 0L;
int noDelays = 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 (InterruptedException e) {
}
// 獲得延遲時間
overSleepTime = (System.nanoTime() - afterTime) - sleepTime;
} else {
// 重新計算
overSleepTime = 0L;
// 判斷noDelays值
if (++noDelays >= 16) {
Thread.yield(); // 令線程讓步
noDelays = 0;
// 重新獲得beforeTime
beforeTime = System.nanoTime();
// 制造FPS結果
fps.makeFPS();
* 變更球體軌迹
private void gameUpdate() {
ball[i].move();
* 變更圖形
public void update(Graphics g) {
paint(g);
* 顯示圖形
public void paint(Graphics g) {
// 設定背景為白色,并清空圖形
bg.setColor(Color.WHITE);
bg.fillRect(0, 0, WIDTH, HEIGHT);
// FPS數值顯示
bg.setColor(Color.BLUE);
bg.drawString("FPS: " + fps.getFPS(), 4, 16);
// 分别繪制相應球體
ball[i].draw(bg);
g.drawImage(screen, 0, 0, this);
g.dispose();
public static void main(String[] args) {
Frame frm = new Frame();
frm.setTitle("Java FPS速度測試(由Loonframework架構提供)");
frm.setSize(WIDTH, HEIGHT+20);
frm.setResizable(false);
frm.add(new BallPanel());
frm.setVisible(true);
frm.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
});
本文轉自 cping 51CTO部落格,原文連結:http://blog.51cto.com/cping1982/116709