1 /**
2 Copyright: Copyright (c) 2013-2017 Andrey Penechko.
3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Andrey Penechko.
5 */
6 
7 module anchovy.fpshelper;
8 
9 import core.thread;
10 import anchovy.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 	float updateInterval = 0.5;
22 
23 	/// Stores actual FPS value
24 	float fps = 0;
25 
26 	/// Stores last delta time passed into update()
27 	float deltaTime;
28 
29 	/// Stores amount of updates between
30 	size_t fpsTicks;
31 
32 	/// Accumulates time before reaching update interval
33 	float secondsAccumulator = 0;
34 
35 	bool limitFps = true;
36 
37 	uint maxFps = 60;
38 
39 	/// Delta time value will clamped to meet interval [0;timeLimit].
40 	/// This can prevent from value lags when entering hibernation or resizing the window.
41 	float timeLimit = 1;
42 
43 	void update(float dt)
44 	{
45 		if (dt > timeLimit)
46 		{
47 			dt = timeLimit;
48 		}
49 		deltaTime = dt;
50 
51 		++fpsTicks;
52 		secondsAccumulator += dt;
53 
54 		if (secondsAccumulator >= updateInterval)
55 		{
56 			fps = fpsTicks/secondsAccumulator;
57 			secondsAccumulator -= updateInterval;
58 			fpsTicks = 0;
59 			fpsUpdated.emit(&this);
60 		}
61 	}
62 
63 	void sleepAfterFrame(float frameTime)
64 	{
65 		if (limitFps)
66 		{
67 			uint msecs = cast(uint)((1/cast(float)maxFps - frameTime)*1000);
68 			Thread.sleep(dur!"msecs"(msecs>2? msecs - 1: msecs));
69 		}
70 	}
71 }
72