程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> JAVA圖形操作中FPS的計算

JAVA圖形操作中FPS的計算

編輯:關於JAVA

FPS:即幀 /秒(frames per second)的縮寫,也稱為幀速率。是指1秒鐘時間裡刷新的圖片的幀數,也可以理解為圖形處理器每秒鐘能夠刷新幾次。如果具體到手機上就是指每秒鐘能夠播放(或者錄制)多少格畫面。同時越高的幀速率可以得到更流暢、更逼真的動畫。每秒鐘幀數(fps)越多,所顯示的動作就會越流暢。

在絕大多數圖形程序中(以游戲類為典型),執行效率都以FPS作為評估標准。

由於目前JAVA方面缺少相關用例,故完成功能如下圖(在本機測試中,最大fps設定為500,實際達到FPS效率在IDE中280左右,單獨運行380左右,受系統配置等因素影響):

代碼如下:

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 protected]
* @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);
    }
}

球體類相關代碼:

package org.test;
import java.awt.Color;
import java.awt.Graphics;
/** *//**
* <p>Title: LoonFramework</p>
* <p>Description:</p>
* <p>Copyright: Copyright (c) 2007</p>
* <p>Company: LoonFramework</p>
* @author chenpeng  
* @email:[email protected]
* @version 0.1
*/
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及球體處理用代碼如下:

package org.test;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
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>
* <p>
* Description:以JAVA獲取FPS用演示程序及隨機生成亂數球體。(更優化代碼內置於loonframework-game框架中)
* </p>
* <p>
* Copyright: Copyright (c) 2007
* </p>
* <p>
* Company: LoonFramework
* </p>
*
* @author chenpeng
* @email:[email protected]
* @version 0.1
*/
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() {
        for (int i = 0; i < NUM_BALLS; i++) {
            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);
        // 分別繪制相應球體
        for (int i = 0; i < NUM_BALLS; i++) {
            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);
            }
        });
    }
}

本文出自 “Java究竟怎麼玩” 博客,請務必保留此出處http://cping1982.blog.51cto.com/601635/116709

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved