1 module gfm.sdl2.framecounter; 2 3 import std.string; 4 5 import derelict.sdl2.sdl; 6 7 import gfm.core.queue, 8 gfm.math.statistics, 9 gfm.sdl2.sdl; 10 11 12 /// Utility class which gives time delta between frames, and 13 /// logs some framerate statistics. 14 /// Useful for a variable timestep application. 15 final class FrameCounter 16 { 17 public 18 { 19 /// Creates a FrameCounter, SDL must be initialized. 20 this(SDL2 sdl) 21 { 22 _sdl = sdl; 23 _firstFrame = true; 24 _elapsedTime = 0; 25 _stats = new RingBuffer!ulong(10); 26 } 27 28 /// Marks the beginning of a new frame. 29 /// Returns: Current time difference since last frame, in milliseconds. 30 ulong tickMs() 31 { 32 if (_firstFrame) 33 { 34 _lastTime = SDL_GetTicks(); 35 _firstFrame = false; 36 _stats.pushBack(0); 37 return 0; // no advance for first frame 38 } 39 else 40 { 41 uint now = SDL_GetTicks(); 42 uint delta = now - _lastTime; 43 _elapsedTime += delta; 44 _lastTime = now; 45 _stats.pushBack(delta); 46 return delta; 47 } 48 } 49 50 /// Marks the beginning of a new frame. 51 /// Returns: Current time difference since last frame, in seconds. 52 deprecated alias tick = tickSecs; 53 double tickSecs() 54 { 55 return tickMs() * 0.001; 56 } 57 58 /// Returns: Elapsed time since creation, in milliseconds. 59 ulong elapsedTimeMs() const 60 { 61 return _elapsedTime; 62 } 63 64 /// Returns: Elapsed time since creation, in seconds. 65 double elapsedTime() const 66 { 67 return _elapsedTime * 0.001; 68 } 69 70 /// Returns: Displayable framerate statistics. 71 string getFPSString() 72 { 73 double avg = average(_stats[]); 74 int avgFPS = cast(int)(0.5 + ( avg != 0 ? 1000 / avg : 0 ) ); 75 int avgdt = cast(int)(0.5 + avg); 76 77 return format("FPS: %s dt: avg %sms min %sms max %sms", 78 avgFPS, 79 avgdt, 80 minElement(_stats[]), 81 maxElement(_stats[])); 82 } 83 } 84 85 private 86 { 87 SDL2 _sdl; 88 RingBuffer!ulong _stats; 89 bool _firstFrame; 90 uint _lastTime; 91 ulong _elapsedTime; 92 } 93 } 94