1 /** 2 Copyright: Copyright (c) 2013-2018 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 7 module voxelman.utils.fpshelper; 8 9 import core.thread; 10 import voxelman.utils.signal; 11 12 /++ 13 + Helper for measuring frames per second and setting static FPS. 14 + Usually needs to be located as field of game class. 15 +/ 16 struct FpsHelper 17 { 18 Signal!(FpsHelper*) fpsUpdated; 19 20 /// fps will be updated each updateInterval seconds 21 double updateInterval = 0.5; 22 23 /// Stores actual FPS value 24 double fps = 0; 25 26 /// Stores update time passed trough update every updateInterval 27 double updateTime = 0; 28 29 /// Stores last delta time passed into update() 30 double deltaTime = 0; 31 32 /// Stores amount of updates between 33 size_t fpsTicks; 34 35 /// Accumulates time before reaching update interval 36 double secondsAccumulator = 0; 37 38 bool limitFps = true; 39 40 uint maxFps = 60; 41 42 /// Delta time value will clamped to meet interval [0;timeLimit]. 43 /// This can prevent from value lags when entering hibernation or resizing the window. 44 double timeLimit = 1; 45 46 void update(double dt, double updateTime) 47 { 48 if (dt > timeLimit) 49 { 50 dt = timeLimit; 51 } 52 deltaTime = dt; 53 54 ++fpsTicks; 55 secondsAccumulator += dt; 56 57 if (secondsAccumulator >= updateInterval) 58 { 59 fps = fpsTicks/secondsAccumulator; 60 this.updateTime = updateTime; 61 secondsAccumulator -= updateInterval; 62 fpsTicks = 0; 63 fpsUpdated.emit(&this); 64 } 65 } 66 67 void sleepAfterFrame(double frameTime) 68 { 69 if (limitFps) 70 { 71 uint msecs = cast(uint)((1/cast(double)maxFps - frameTime)*1000); 72 if (msecs > 0) 73 Thread.sleep(dur!"msecs"(msecs)); 74 } 75 } 76 } 77