Skip to content

Commit

Permalink
Feature: configurable refresh-rate and change default to 60fps
Browse files Browse the repository at this point in the history
Most modern games run on 60 fps, and for good reason. This gives
a much smoother experiences.

As some people have monitors that can do 144Hz or even 240Hz, allow
people to configure the refresh rate. Of course, the higher you
set the value, the more time the game spends on drawing pixels
instead of simulating the game, which has an effect on simulation
speed.

The simulation will still always run at 33.33 fps, and is not
influences by this setting.
  • Loading branch information
TrueBrain committed Feb 17, 2021
1 parent e38153f commit 599cb24
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 27 deletions.
4 changes: 2 additions & 2 deletions src/framerate_gui.cpp
Expand Up @@ -189,7 +189,7 @@ namespace {
PerformanceData(1), // PFE_ACC_GL_AIRCRAFT
PerformanceData(1), // PFE_GL_LANDSCAPE
PerformanceData(1), // PFE_GL_LINKGRAPH
PerformanceData(GL_RATE), // PFE_DRAWING
PerformanceData(1000.0 / 30), // PFE_DRAWING
PerformanceData(1), // PFE_ACC_DRAWWORLD
PerformanceData(60.0), // PFE_VIDEO
PerformanceData(1000.0 * 8192 / 44100), // PFE_SOUND
Expand Down Expand Up @@ -468,7 +468,7 @@ struct FramerateWindow : Window {
this->speed_gameloop.SetRate(gl_rate / _pf_data[PFE_GAMELOOP].expected_rate, 1.0);
if (this->small) return; // in small mode, this is everything needed

this->rate_drawing.SetRate(_pf_data[PFE_DRAWING].GetRate(), _pf_data[PFE_DRAWING].expected_rate);
this->rate_drawing.SetRate(_pf_data[PFE_DRAWING].GetRate(), _settings_client.gui.refresh_rate);

int new_active = 0;
for (PerformanceElement e = PFE_FIRST; e < PFE_MAX; e++) {
Expand Down
1 change: 1 addition & 0 deletions src/settings_type.h
Expand Up @@ -147,6 +147,7 @@ struct GUISettings {
byte starting_colour; ///< default color scheme for the company to start a new game with
bool show_newgrf_name; ///< Show the name of the NewGRF in the build vehicle window
bool auto_remove_signals; ///< automatically remove signals when in the way during rail construction
uint16 refresh_rate; ///< How often we refresh the screen (time between draw-ticks).

uint16 console_backlog_timeout; ///< the minimum amount of time items should be in the console backlog before they will be removed in ~3 seconds granularity.
uint16 console_backlog_length; ///< the minimum amount of items in the console backlog before items will be removed.
Expand Down
9 changes: 9 additions & 0 deletions src/table/settings.ini
Expand Up @@ -3324,6 +3324,15 @@ def = 100
min = 10
max = 65500

[SDTC_VAR]
var = gui.refresh_rate
type = SLE_UINT16
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
def = 60
min = 10
max = 1000
cat = SC_EXPERT

[SDTC_BOOL]
var = sound.news_ticker
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
Expand Down
10 changes: 5 additions & 5 deletions src/video/allegro_v.cpp
Expand Up @@ -485,20 +485,20 @@ void VideoDriver_Allegro::MainLoop()

if (cur_ticks >= next_game_tick || (_fast_forward && !_pause_mode)) {
if (_fast_forward && !_pause_mode) {
next_game_tick = cur_ticks + std::chrono::milliseconds(MILLISECONDS_PER_TICK);
next_game_tick = cur_ticks + this->GetGameInterval();
} else {
next_game_tick += std::chrono::milliseconds(MILLISECONDS_PER_TICK);
next_game_tick += this->GetGameInterval();
/* Avoid next_game_tick getting behind more and more if it cannot keep up. */
if (next_game_tick < cur_ticks - std::chrono::milliseconds(ALLOWED_DRIFT * MILLISECONDS_PER_TICK)) next_game_tick = cur_ticks;
if (next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) next_game_tick = cur_ticks;
}

GameLoop();
}

if (cur_ticks >= next_draw_tick) {
next_draw_tick += std::chrono::milliseconds(MILLISECONDS_PER_TICK);
next_draw_tick += this->GetDrawInterval();
/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
if (next_draw_tick < cur_ticks - std::chrono::microseconds(ALLOWED_DRIFT * MILLISECONDS_PER_TICK)) next_draw_tick = cur_ticks;
if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;

bool old_ctrl_pressed = _ctrl_pressed;

Expand Down
10 changes: 5 additions & 5 deletions src/video/cocoa/cocoa_v.mm
Expand Up @@ -675,20 +675,20 @@ static void ClearWindowBuffer(uint32 *buffer, uint32 pitch, uint32 height)

if (cur_ticks >= next_game_tick || (_fast_forward && !_pause_mode)) {
if (_fast_forward && !_pause_mode) {
next_game_tick = cur_ticks + std::chrono::milliseconds(MILLISECONDS_PER_TICK);
next_game_tick = cur_ticks + this->GetGameInterval();
} else {
next_game_tick += std::chrono::milliseconds(MILLISECONDS_PER_TICK);
next_game_tick += this->GetGameInterval();
/* Avoid next_game_tick getting behind more and more if it cannot keep up. */
if (next_game_tick < cur_ticks - std::chrono::milliseconds(ALLOWED_DRIFT * MILLISECONDS_PER_TICK)) next_game_tick = cur_ticks;
if (next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) next_game_tick = cur_ticks;
}

::GameLoop();
}

if (cur_ticks >= next_draw_tick) {
next_draw_tick += std::chrono::milliseconds(MILLISECONDS_PER_TICK);
next_draw_tick += this->GetDrawInterval();
/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
if (next_draw_tick < cur_ticks - std::chrono::microseconds(ALLOWED_DRIFT * MILLISECONDS_PER_TICK)) next_draw_tick = cur_ticks;
if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;

bool old_ctrl_pressed = _ctrl_pressed;

Expand Down
6 changes: 3 additions & 3 deletions src/video/dedicated_v.cpp
Expand Up @@ -294,11 +294,11 @@ void VideoDriver_Dedicated::MainLoop()

if (cur_ticks >= next_game_tick || _ddc_fastforward) {
if (_ddc_fastforward) {
next_game_tick = cur_ticks + std::chrono::milliseconds(MILLISECONDS_PER_TICK);
next_game_tick = cur_ticks + this->GetGameInterval();
} else {
next_game_tick += std::chrono::milliseconds(MILLISECONDS_PER_TICK);
next_game_tick += this->GetGameInterval();
/* Avoid next_game_tick getting behind more and more if it cannot keep up. */
if (next_game_tick < cur_ticks - std::chrono::milliseconds(ALLOWED_DRIFT * MILLISECONDS_PER_TICK)) next_game_tick = cur_ticks;
if (next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) next_game_tick = cur_ticks;
}

GameLoop();
Expand Down
4 changes: 2 additions & 2 deletions src/video/sdl2_v.cpp
Expand Up @@ -807,9 +807,9 @@ void VideoDriver_SDL::LoopOnce()
}

if (cur_ticks >= next_draw_tick) {
next_draw_tick += std::chrono::milliseconds(MILLISECONDS_PER_TICK);
next_draw_tick += this->GetDrawInterval();
/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
if (next_draw_tick < cur_ticks - std::chrono::microseconds(ALLOWED_DRIFT * MILLISECONDS_PER_TICK)) next_draw_tick = cur_ticks;
if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;

bool old_ctrl_pressed = _ctrl_pressed;

Expand Down
10 changes: 5 additions & 5 deletions src/video/sdl_v.cpp
Expand Up @@ -730,11 +730,11 @@ void VideoDriver_SDL::MainLoop()

if (cur_ticks >= next_game_tick || (_fast_forward && !_pause_mode)) {
if (_fast_forward && !_pause_mode) {
next_game_tick = cur_ticks + std::chrono::milliseconds(MILLISECONDS_PER_TICK);
next_game_tick = cur_ticks + this->GetGameInterval();
} else {
next_game_tick += std::chrono::milliseconds(MILLISECONDS_PER_TICK);
next_game_tick += this->GetGameInterval();
/* Avoid next_game_tick getting behind more and more if it cannot keep up. */
if (next_game_tick < cur_ticks - std::chrono::milliseconds(ALLOWED_DRIFT * MILLISECONDS_PER_TICK)) next_game_tick = cur_ticks;
if (next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) next_game_tick = cur_ticks;
}

/* The gameloop is the part that can run asynchronously. The rest
Expand All @@ -745,9 +745,9 @@ void VideoDriver_SDL::MainLoop()
}

if (cur_ticks >= next_game_tick || (_fast_forward && !_pause_mode)) {
next_draw_tick += std::chrono::milliseconds(MILLISECONDS_PER_TICK);
next_draw_tick += this->GetDrawInterval();
/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
if (next_draw_tick < cur_ticks - std::chrono::microseconds(ALLOWED_DRIFT * MILLISECONDS_PER_TICK)) next_draw_tick = cur_ticks;
if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;

bool old_ctrl_pressed = _ctrl_pressed;

Expand Down
14 changes: 14 additions & 0 deletions src/video/video_driver.hpp
Expand Up @@ -13,7 +13,9 @@
#include "../driver.h"
#include "../core/geometry_type.hpp"
#include "../core/math_func.hpp"
#include "../settings_type.h"
#include "../zoom_type.h"
#include <chrono>
#include <vector>

extern std::string _ini_videodriver;
Expand Down Expand Up @@ -153,6 +155,18 @@ class VideoDriver : public Driver {
_cur_resolution.height = ClampU(res.height * 3 / 4, DEFAULT_WINDOW_HEIGHT, UINT16_MAX / 2);
}
}

std::chrono::steady_clock::duration GetGameInterval()
{
return std::chrono::milliseconds(MILLISECONDS_PER_TICK);
}

std::chrono::steady_clock::duration GetDrawInterval()
{
/* TODO -- If michi_cc' patch lands for startup flag, possibly this can be removed. */
uint8 refresh_rate = _settings_client.gui.refresh_rate != 0 ? _settings_client.gui.refresh_rate : 30;
return std::chrono::microseconds(1000000 / refresh_rate);
}
};

#endif /* VIDEO_VIDEO_DRIVER_HPP */
10 changes: 5 additions & 5 deletions src/video/win32_v.cpp
Expand Up @@ -1207,11 +1207,11 @@ void VideoDriver_Win32::MainLoop()

if (cur_ticks >= next_game_tick || (_fast_forward && !_pause_mode)) {
if (_fast_forward && !_pause_mode) {
next_game_tick = cur_ticks + std::chrono::milliseconds(MILLISECONDS_PER_TICK);
next_game_tick = cur_ticks + this->GetGameInterval();
} else {
next_game_tick += std::chrono::milliseconds(MILLISECONDS_PER_TICK);
next_game_tick += this->GetGameInterval();
/* Avoid next_game_tick getting behind more and more if it cannot keep up. */
if (next_game_tick < cur_ticks - std::chrono::milliseconds(ALLOWED_DRIFT * MILLISECONDS_PER_TICK)) next_game_tick = cur_ticks;
if (next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) next_game_tick = cur_ticks;
}

/* Flush GDI buffer to ensure we don't conflict with the drawing thread. */
Expand All @@ -1225,9 +1225,9 @@ void VideoDriver_Win32::MainLoop()
}

if (cur_ticks >= next_draw_tick) {
next_draw_tick += std::chrono::milliseconds(MILLISECONDS_PER_TICK);
next_draw_tick += this->GetDrawInterval();
/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
if (next_draw_tick < cur_ticks - std::chrono::microseconds(ALLOWED_DRIFT * MILLISECONDS_PER_TICK)) next_draw_tick = cur_ticks;
if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;

bool old_ctrl_pressed = _ctrl_pressed;

Expand Down

0 comments on commit 599cb24

Please sign in to comment.