先列舉幾個關于渲染幀率的文章:
1. http://ruinerlee.blog.163.com/blog/static/215611167201292990203/
2. http://blog.codingnow.com/2008/04/fps.html
3. http://blog.csdn.net/strongcoding/article/details/6252313
#include
#include
#pragma comment(lib,"winmm.lib")
int main()
{
DWORD currentTime;
DWORD lastTime = timeGetTime();
DWORD frameCounter = ;
DWORD frameTime = ;
DWORD elapsedTime = ;
while()
{
currentTime = timeGetTime();
frameTime += (currentTime - lastTime);
elapsedTime += (currentTime - lastTime);
lastTime = currentTime;
if(frameTime > ) // 1000/60 ,渲染一次需要的時間
{
frameCounter++;
frameTime -= ; //因為有可能大于16,直接置零會導緻少算
}
if(elapsedTime >= )
{
std::cout << frameCounter << std::endl;
frameCounter = ;
elapsedTime -= ;
}
}
return ;
}
解釋:
渲染幀速率,即每秒渲染的幀數。上面的程式設定固定的幀速率為60,之是以使用frameTime累積時間值,是因為電腦中的程式是CPU切換執行的,而這種切換速度是非常快的,隻有累積的時間大于渲染一幀需要的時間時才會累加frameCounter。elapsedTime 變量是累積程式運作的時間,當程式運作的時間大于或者等于1000ms也就是1s的時候,列印一下FPS。
下面是2個案例:
#include "Timing.h"
#include <SDL/SDL.h>
namespace Tengine {
FpsLimiter::FpsLimiter() {
}
void FpsLimiter::init(float maxFPS) {
setMaxFPS(maxFPS);
}
void FpsLimiter::setMaxFPS(float maxFPS) {
_maxFPS = maxFPS;
}
void FpsLimiter::begin() {
_startTicks = SDL_GetTicks();
}
float FpsLimiter::end() {
calculateFPS();
float frameTicks = SDL_GetTicks() - _startTicks;
// Limit the FPS to the max FPS
if ( / _maxFPS > frameTicks) {
SDL_Delay( / _maxFPS - frameTicks);
}
return _fps;
}
void FpsLimiter::calculateFPS() {
static const int NUM_SAMPLES = ;
static float frameTimes[NUM_SAMPLES];
static int currentFrame = ;
static float prevTicks = SDL_GetTicks();
float currentTicks;
currentTicks = SDL_GetTicks();
_frameTime = currentTicks - prevTicks;
frameTimes[currentFrame % NUM_SAMPLES] = _frameTime;
prevTicks = currentTicks;
int count;
currentFrame++;
if (currentFrame < NUM_SAMPLES)
{
count = currentFrame;
}
else
{
count = NUM_SAMPLES;
}
float frameTimeAverage = ;
for (int i = ; i < count; i++)
{
frameTimeAverage += frameTimes[i];
}
frameTimeAverage /= count;
if (frameTimeAverage > )
{
_fps = / frameTimeAverage;
}
else {
_fps = ;
}
}
}
另一個示例:
package com.base.engine;
import java.io.File;
import java.net.URI;
import java.util.zip.ZipFile;
public class MainComponent {
public static final int WIDTH = ;
public static final int HEIGHT = ;
public static final String TITLE = "3D Engine";
private static final double FRAME_CAP = ;//每秒遊戲重新整理的次數,但是我不可能每秒畫5000次。
private boolean isRunning;
private Game game;
public MainComponent ()
{
isRunning = false;
game = new Game();
}
public void start(){
if(isRunning)
return;
run();
}
public void stop(){
if(!isRunning)
return;
isRunning =false;
}
//要使Game在固定的時間單元内重新整理一次。這樣幀率對遊戲的場景就沒有影響了。如:我要讓我的ball在固定的時間内移動一次,而不管在這固定的時間内實際畫了多少在螢幕上。
private void run(){
isRunning = true;
int frames = ;
long frameCounter = ;
//一幀需要的時間
final double frameTime = / FRAME_CAP;
long lastTime = Time.getTime();
double unprocessedTime = ;
while(isRunning){
boolean render = false;
long startTime = Time.getTime();
long passedTime = startTime - lastTime;
lastTime = startTime;
unprocessedTime += passedTime / (double)Time.SECOND;
frameCounter += passedTime;
while(unprocessedTime > frameTime){
render =true;
unprocessedTime -= frameTime;
if(Window.isCloseRequested())
stop();
Time.setDelta(frameTime);
//TODO: update game
game.input();
game.update();
if(frameCounter >= Time.SECOND){//每秒鐘輸出一次FPS
System.out.println(frames);
frames = ;
frameCounter =;
}
}
if(render){
render();
frames++;
}else{
try {
Thread.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
cleanUp();
}
private void render(){
game.render();
Window.render();
}
private void cleanUp(){
Window.dispose();
}
public static void main(String[] args) {
Window.createWindow(WIDTH, HEIGHT, TITLE);
MainComponent game = new MainComponent();
game.start();
}
}
Time.java
package com.base.engine;
public class Time {
public static final long SECOND = L;
private static double delta;
public static long getTime(){
return System.nanoTime();
}
public static double getDelta(){
return delta;
}
public static void setDelta(double delta){
Time.delta = delta;
}
}