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