1 /* 2 ******************************************************************************************* 3 * Dgame (a D game framework) - Copyright (c) Randy Schütt 4 * 5 * This software is provided 'as-is', without any express or implied warranty. 6 * In no event will the authors be held liable for any damages arising from 7 * the use of this software. 8 * 9 * Permission is granted to anyone to use this software for any purpose, 10 * including commercial applications, and to alter it and redistribute it 11 * freely, subject to the following restrictions: 12 * 13 * 1. The origin of this software must not be misrepresented; you must not claim 14 * that you wrote the original software. If you use this software in a product, 15 * an acknowledgment in the product documentation would be appreciated but is 16 * not required. 17 * 18 * 2. Altered source versions must be plainly marked as such, and must not be 19 * misrepresented as being the original software. 20 * 21 * 3. This notice may not be removed or altered from any source distribution. 22 ******************************************************************************************* 23 */ 24 module Dgame.System.StopWatch; 25 26 private import derelict.sdl2.functions; 27 28 /** 29 * Convert the Clock milliseconds to seconds 30 */ 31 @nogc 32 float asSeconds(uint n) pure nothrow { 33 return n >= 1000 ? (n / 1000) : 0; 34 } 35 36 /** 37 * Convert the Clock milliseconds to minutes 38 */ 39 @nogc 40 float asMinutes(uint n) pure nothrow { 41 immutable float secs = asSeconds(n); 42 43 return secs >= 60 ? (secs / 60) : 0; 44 } 45 46 /** 47 * Convert the Clock milliseconds to hours 48 */ 49 @nogc 50 uint asHours(uint n) pure nothrow { 51 immutable float mins = asMinutes(n); 52 53 return mins >= 60 ? cast(uint)(mins / 60) : 0; 54 } 55 56 /** 57 * Returns the given seconds in milliseconds 58 * 59 * Example: 60 * ---- 61 * int n = 5.seconds; // n is 5000 because 5 seconds are 5000 milliseconds 62 * ---- 63 * 64 * ---- 65 * StopWatch sw; 66 * sw.wait(5.seconds); 67 * ---- 68 */ 69 @property 70 @nogc 71 uint seconds(uint n) pure nothrow { 72 return n * 1000; 73 } 74 75 /** 76 * Returns the given minutes in milliseconds 77 * 78 * Example: 79 * ---- 80 * int n = 5.minutes; // n is 300_000 because 5 minutes are 300 seconds are 300_000 milliseconds 81 * ---- 82 * 83 * ---- 84 * StopWatch sw; 85 * sw.wait(5.minutes); 86 * ---- 87 */ 88 @property 89 @nogc 90 uint minutes(uint n) pure nothrow { 91 return (n * 60).seconds; 92 } 93 94 /** 95 * The Time struct converts ticks to msecs, seconds, minutes and hours. 96 * 97 * Author: Randy Schuett (rswhite4@googlemail.com) 98 */ 99 struct Time { 100 /** 101 * Milliseconds = Ticks 102 */ 103 uint msecs; 104 /** 105 * Seconds = Milliseconds / 1000 106 */ 107 float seconds; 108 /** 109 * Minutes = Seconds / 60 110 */ 111 float minutes; 112 /** 113 * Hours = Minutes / 60 114 */ 115 uint hours; 116 117 /** 118 * CTor 119 */ 120 @nogc 121 this(uint msecs) pure nothrow { 122 this.msecs = msecs; 123 this.seconds = asSeconds(msecs); 124 this.minutes = asMinutes(msecs); 125 this.hours = asHours(msecs); 126 } 127 128 /** 129 * Calculate the <b>remaining</b> time. 130 */ 131 @nogc 132 static Time remain(Time time) pure nothrow { 133 import std.math : floor; 134 135 immutable float min = time.minutes; 136 immutable float sec = time.seconds; 137 138 time.minutes -= floor(float(time.hours)) * 60; 139 time.minutes = floor(time.minutes); 140 time.seconds -= floor(min) * 60; 141 time.msecs -= cast(uint)(floor(sec) * 1000); 142 143 return time; 144 } 145 } 146 147 unittest { 148 Time time = Time(65_000); 149 150 assert(time.msecs == 65_000); 151 assert(time.seconds == 65); 152 assert(time.minutes >= 1.08f && time.minutes <= 1.09f); 153 154 time = Time.remain(time); 155 156 assert(time.msecs == 0f); 157 assert(time.seconds == 5f); 158 assert(time.minutes == 1f); 159 } 160 161 /** 162 * This class handles timer functions and 163 * the window class use these class to calculate the current fps. 164 * 165 * Author: Randy Schuett (rswhite4@googlemail.com) 166 */ 167 struct StopWatch { 168 private: 169 uint _startTime; 170 uint _numFrames; 171 uint _currentFps; 172 173 public: 174 /** 175 * Reset the clock time 176 */ 177 @nogc 178 void reset() nothrow { 179 _startTime = SDL_GetTicks(); 180 } 181 182 /** 183 * Returns the elapsed Time since the last reset. 184 */ 185 @nogc 186 Time getElapsedTime() const nothrow { 187 return Time(this.getElapsedTicks()); 188 } 189 190 /** 191 * Returns only the milliseconds since the last reset. 192 */ 193 @nogc 194 uint getElapsedTicks() const nothrow { 195 return SDL_GetTicks() - _startTime; 196 } 197 198 /** 199 * Returns the current framerate per seconds. 200 * If frame_ms is not null, the average ms per frame is stored there 201 */ 202 @nogc 203 uint getCurrentFPS(uint* frame_ms = null) nothrow { 204 immutable uint elapsed_ticks = this.getElapsedTicks(); 205 206 if (frame_ms) 207 *frame_ms = elapsed_ticks / _numFrames; 208 209 if (elapsed_ticks >= 1000) { 210 _currentFps = _numFrames; 211 _numFrames = 0; 212 this.reset(); 213 } 214 215 _numFrames++; 216 217 return _currentFps; 218 } 219 220 /** 221 * Returns the milliseconds since the application was started. 222 */ 223 @nogc 224 static uint getTicks() nothrow { 225 return SDL_GetTicks(); 226 } 227 228 /** 229 * Returns the Time since the application was started. 230 */ 231 @nogc 232 static Time getTime() nothrow { 233 return Time(StopWatch.getTicks()); 234 } 235 236 /** 237 * Wait for msecs milliseconds, which means that the application freeze for this time. 238 */ 239 @nogc 240 static void wait(uint msecs) nothrow { 241 SDL_Delay(msecs); 242 } 243 }