├── .travis.yml
├── LICENSE
├── README.md
├── hertz.cc
├── hertz.cpp
└── hertz.hpp
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: cpp
2 | sudo: required
3 |
4 | compiler:
5 | - clang
6 | - gcc
7 |
8 | install:
9 | - wget --quiet -O - https://raw.githubusercontent.com/r-lyeh/depot/master/travis.pre.sh | bash -x
10 |
11 | script:
12 | - wget --quiet -O - https://raw.githubusercontent.com/r-lyeh/depot/master/travis.build.sh | bash -x
13 | # - wget --quiet -O - https://raw.githubusercontent.com/r-lyeh/depot/master/travis.run.sh | bash -x
14 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015 r-lyeh (https://github.com/r-lyeh)
2 |
3 | This software is provided 'as-is', without any express or implied
4 | warranty. In no event will the authors be held liable for any damages
5 | arising from the use of this software.
6 |
7 | Permission is granted to anyone to use this software for any purpose,
8 | including commercial applications, and to alter it and redistribute it
9 | freely, subject to the following restrictions:
10 |
11 | 1. The origin of this software must not be misrepresented; you must not
12 | claim that you wrote the original software. If you use this software
13 | in a product, an acknowledgment in the product documentation would be
14 | appreciated but is not required.
15 | 2. Altered source versions must be plainly marked as such, and must not be
16 | misrepresented as being the original software.
17 | 3. This notice may not be removed or altered from any source distribution.
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Hertz :watch:
2 | ====
3 |
4 | - Hertz is a simple framerate locker (C++11)
5 | - Hertz features auto-frameskip.
6 | - Hertz features dynamic/variable framerate locking.
7 | - Hertz is tiny (~75 LOC), cross-platform, self-contained and header-only.
8 | - Hertz is zlib/libpng licensed.
9 |
10 | ### API
11 | ```c++
12 | double /*fps*/ hertz::lock( 60 /*Hz*/, []{/*logic*/}, []{/*render*/} );
13 | void hertz::unlock(); // quit
14 | ```
15 |
16 | ### Changelog
17 | - v1.0.0 (2015/12/05): Add unlock function
18 | - v1.0.0 (2015/09/19): Initial commit
19 |
--------------------------------------------------------------------------------
/hertz.cc:
--------------------------------------------------------------------------------
1 | #define HERTZ_BUILD_SAMPLE
2 | #include "hertz.hpp"
3 |
--------------------------------------------------------------------------------
/hertz.cpp:
--------------------------------------------------------------------------------
1 | #include "hertz.hpp"
2 |
--------------------------------------------------------------------------------
/hertz.hpp:
--------------------------------------------------------------------------------
1 | // Hertz, simple framerate locker. based on code by /u/concavator (ref: http://goo.gl/Ry50A4)
2 | // - rlyeh. zlib/libpng licensed
3 | //
4 | // features:
5 | // [x] auto-frameskip
6 | // [x] dynamic/variable framerate locking
7 |
8 | #pragma once
9 | #include
10 | #include
11 | #include
12 |
13 | #define HERTZ_VERSION "1.0.1" /* (2015/12/05) Add unlock function
14 | #define HERTZ_VERSION "1.0.0" // (2015/09/19) Initial commit */
15 |
16 | namespace hertz {
17 | // function that locks your logic and render to desired framerate (in HZ).
18 | // returns number of current fps
19 | template
20 | static inline
21 | double lock( signed HZ, FNU &update, FNR &render ) {
22 | // rw vars
23 | static volatile unsigned hz = 60, isGameRunning = 1, maxframeskip = 10;
24 | // ro vars
25 | static volatile unsigned fps = 0;
26 | // private vars
27 | static volatile unsigned timer_counter = 0, loop_counter = 0;
28 | // private threaded timer
29 | static struct install {
30 | install() {
31 | std::thread([&]{
32 | std::chrono::microseconds acc( 0 ), third( 300000 );
33 | while( isGameRunning ) {
34 | // update timer
35 | timer_counter++;
36 | std::chrono::microseconds duration( int(1000000/hz) );
37 | std::this_thread::sleep_for( duration );
38 | // update fps 3 times per second
39 | acc += duration;
40 | if( acc >= third ) {
41 | acc -= acc;
42 | static int before = loop_counter;
43 | fps = int( std::round( (loop_counter - before) * 3.3333333 ) );
44 | before = loop_counter;
45 | }
46 | }
47 | isGameRunning = 1;
48 | }).detach();
49 | }
50 | } timer;
51 |
52 | if( HZ < 0 ) {
53 | isGameRunning = 0;
54 | return 1;
55 | }
56 |
57 | hz = HZ > 0 ? HZ : hz;
58 |
59 | // we got too far ahead, cpu idle wait
60 | while( loop_counter > timer_counter && isGameRunning ) {
61 | std::this_thread::yield();
62 | }
63 |
64 | // max auto frameskip is 10, ie, even if speed is low paint at least one frame every 10
65 | if( timer_counter > loop_counter + 10 ) {
66 | timer_counter = loop_counter;
67 | }
68 |
69 | loop_counter++;
70 |
71 | // only draw if we are fast enough, otherwise skip the frame
72 | update();
73 | if( loop_counter >= timer_counter ) {
74 | render();
75 | }
76 | return fps;
77 | }
78 |
79 | static inline void unlock() {
80 | auto nil = []{};
81 | hertz::lock( -1, nil, nil );
82 | }
83 | }
84 |
85 |
86 | #ifdef HERTZ_BUILD_SAMPLE
87 |
88 | #ifdef _WIN32
89 | #include
90 | #pragma comment(lib, "user32.lib")
91 | #endif
92 |
93 | #include
94 | #include
95 | #include
96 | #include
97 |
98 | int main() {
99 | unsigned HZ = 60, updates = 0, frames = 0, fps = 0;
100 |
101 | auto update = [&]{
102 | updates++;
103 | #ifdef _WIN32
104 | static auto &once = std::cout << "Keys: up, down, escape, space" << std::endl;
105 | if( GetAsyncKeyState(VK_UP) & 0x8000 ) HZ+=(std::min)((std::max)(int(HZ*0.01), 1), 5);
106 | if( GetAsyncKeyState(VK_DOWN) & 0x8000 ) if(HZ > (std::max)(int(HZ*0.01), 1)) HZ-=(std::max)(int(HZ*0.01), 1);
107 | if( GetAsyncKeyState(VK_ESCAPE) & 0x8000 ) exit(0);
108 | if( GetAsyncKeyState(VK_SPACE) & 0x8000 ) Sleep( rand() % 80 );
109 | #endif
110 | };
111 |
112 | auto render = [&]{
113 | frames++;
114 | char bar[] = "\\|/-";
115 | auto current_time = time(NULL);
116 | auto sec = localtime(¤t_time)->tm_sec;
117 |
118 | printf( "(%d/%d) [%c] updates %02ds [%c] frames \r",
119 | fps, HZ, bar[updates%4], sec, bar[frames%4] );
120 | };
121 |
122 | for(;;) {
123 | fps = hertz::lock( HZ, update, render );
124 | }
125 |
126 | hertz::unlock();
127 | }
128 |
129 | #endif
--------------------------------------------------------------------------------