JAVA图形操作中FPS的计算(附带随机生成乱数球体用例)

 FPS:即帧 /秒(frames per second)的缩写,也称为帧速率。是指1秒钟时间里刷新的图片的帧数,也可以理解为图形处理器每秒钟能够刷新几次。如果具体到手机上就是指每秒钟能够 播放(或者录制)多少格画面。同时越高的帧速率可以得到更流畅、更逼真的动画。每秒钟帧数(fps)越多,所显示的动作就会越流畅。 

在绝大多数图形程序中(以游戏类为典型),执行效率都以FPS作为评估标准。

由于目前JAVA方面缺少相关用例,故完成功能如下图(在本机测试中,最大fps设定为500,实际达到FPS效率在IDE中280左右,单独运行380左右,受系统配置等因素影响):

代码如下:JAVA图形操作中FPS的计算(附带随机生成乱数球体用例)(请变更文件后缀为jar)

JAVA图形操作中FPS的计算(附带随机生成乱数球体用例)

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]ceponline@yahoo.com.cn[/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);
        }

}

球体类相关代码:
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]ceponline@yahoo.com.cn[/email] 
* @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]ceponline@yahoo.com.cn[/email]
* @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);
                        }
                });
        }

}

本文转自 cping 51CTO博客,原文链接:http://blog.51cto.com/cping1982/116709
上一篇:Java异常处理和设计


下一篇:Kubernets日志采集配置模式介绍与对比