Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: allow changing the game-speed other than 1x and warp-speed #8693

wants to merge 9 commits into from


Copy link

@TrueBrain TrueBrain commented Feb 18, 2021

#8766 already implements part of this PR that has to do with changing the internals to use _game_speed over _fast_forward.

Motivation / Problem

With #8680 (on which this PR depends) and #7744, fast-forward can easily hit 9999x simulation speeds. This makes fast-forward completely impracticable in most use-cases, as holding down the button for 1 second gives you an extra month of gametime. You miss a decade if you blink, basically.

This PR tries to mitigate that issue by introducing a "Game Speed" window. Incidentally, it also allows the game to run slower.


Initially I tried a dropdown to allow selecting the game-speed (or called fast-forward speed in that branch). It felt really bad to work with. The menu is not really designed for these kind of interactions, but mostly, once you are fast-forwarding, there was no real way to telling at what speed.

So I took another approach most other games I know do: make a window where you can select the game speed. And the last commit in this PR does exactly that (the rest are identical to #8680).
Currently it uses buttons, but this is still a draft. I want to experiment with two more things:

  1. make it a slider (still with discrete values)
  2. also show the current simulation speed

This draft-PR I made purely so others can already see the work, and to allow me to make a Preview to get opinions from others.

TODO list

  • Fix framerate window to colour towards the current setting
  • Test in multiplayer if this really works
  • Add console command to allow any value you desire
  • Name for window: WC_SPEED_TOOLBAR (by frosch)


Checklist for review

Some things are not automated, and forgotten often. This list is a reminder for the reviewers.

  • The bug fix is important enough to be backported? (label: 'backport requested')
  • This PR affects the save game format? (label 'savegame upgrade')
  • This PR affects the GS/AI API? (label 'needs review: Script API')
    • ai_changelog.hpp, gs_changelog.hpp need updating.
    • The compatibility wrappers (compat_*.nut) need updating.
  • This PR affects the NewGRF API? (label 'needs review: NewGRF')
TrueBrain added 8 commits Feb 18, 2021
Adding to _realtime_ticks in a random place is a bit of a hack,
and by using modern C++, we can avoid this hack.
On all OSes we tested the std::chrono::steady_clock is of a high
enough resolution to do millisecond measurements, which is all we

By accident, this fixes a Win32 driver bug, where we would never
hit our targets, as the resolution of the clock was too low to
do accurate millisecond measurements with (it was ~16ms resolution
_realtime_tick was reset every time the diff was calculated. This
means if it would trigger, say, every N.9 milliseconds, it would
after two iterations already drift a millisecond. This adds up
pretty quick.
During fast-forward, the game was drawing as fast as it could. This
means that the fast-forward was limited also by how fast we could
draw, something that people in general don't expect.

To give an extreme case, if you are fully zoomed out on a busy
map, fast-forward would be mostly limited because of the time it
takes to draw the screen.

By decoupling the draw-tick and game-tick, we can keep the pace
of the draw-tick the same while speeding up the game-tick. To use
the extreme case as example again, if you are fully zoomed out
now, the screen only redraws 33.33 times per second, fast-forwarding
or not. This means fast-forward is much more likely to go at the
same speed, no matter what you are looking at.
Before, every next frame was calculated from the current time.
If for some reason the current frame was drifting a bit, the
next would too, and the next more, etc etc. This meant we rarely
hit the targets we would like, like 33.33fps.

Instead, allow video-drivers to drift slightly, and schedule the
next frame based on the time the last should have happened. Only
if the drift gets too much, that deadlines are missed for longer
period of times, schedule the next frame based on the current

This makes the FPS a lot smoother, as sleeps aren't as exact as
you might think.
Sleep for 1ms (which is always (a lot) more than 1ms) is just
randomly guessing and hoping you hit your deadline, give or take.

But given we can calculate when our next frame is happening, we
can just sleep for that exact amount. As these values are often
a bit larger, it is also more likely the OS can schedule us back
in close to our requested target. This means it is more likely we
hit our deadlines, which makes the FPS a lot more stable.
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

The simulation will still always run at 33.33 fps, and is not
influences by this setting.
… that shouldn't be closed yet

The higher your refresh-rate, the more likely this is. Mostly you
notice this when creating a new game or when abandoning a game.

This is a bit of a hack to keep the old behaviour, as before this
patch the game was already freezing your mouse while it was changing
game-mode, and it does this too after this patch. Just now it
freezes too a few frames earlier, to prevent not drawing windows
people still expect to see.
@DorpsGek DorpsGek temporarily deployed to preview-pr-8693 Feb 18, 2021 Inactive
@DorpsGek DorpsGek temporarily deployed to preview-pr-8693 Feb 18, 2021 Inactive
You can now pick 0.25, 0.5, 1, 2, 4, 8 times normal simulation
speed or warp-speed.
Copy link

@nielsmh nielsmh commented Feb 19, 2021

Framerate window should probably show the simulation speed color based on expected, instead of it turning red when you've selected to run at quarter speed.

Copy link
Member Author

@TrueBrain TrueBrain commented Feb 19, 2021

Framerate window should probably show the simulation speed color based on expected, instead of it turning red when you've selected to run at quarter speed.

Absolutely! I had it planned, just hadn't made it into the PR yet .. but it is now in the TODO list, so we will not forget :D

@frosch123 frosch123 marked this pull request as ready for review Feb 20, 2021
@frosch123 frosch123 marked this pull request as draft Feb 20, 2021
Copy link

@frosch123 frosch123 commented Feb 20, 2021

After pressing "FF" once, I cannot raise it anymore :)

Suggestion option 1:
I know you hate Ctrl, but what about: Ctrl+Click opens the new window. Normal click toggles normal speed/previously selected FF speed.

Suggestion option 2:
Many toolbar buttons also have a default action, so a dropdown could select the FF speed. The default action toggles.

Copy link
Member Author

@TrueBrain TrueBrain commented Mar 10, 2021

I keep looking at this, thinking: I think this would be a really good idea.

On the other hand, I also have this huge issue of me thinking: I really do not want to spend time on this :P I cannot get myself motivated to build a custom widget with a slider to show the current setting, but also what the game is currently able to do. And that you can slide it easily, and that is works smooth etc .. I have it all in my head. I just ... cannot get myself to do it.

So for now I am going to close this Pull Request. If anyone else wants to pick it up, please do. I might find the energy to do it myself some day .. just not soon.

@TrueBrain TrueBrain closed this Mar 10, 2021
@TrueBrain TrueBrain deleted the ff-window branch Oct 31, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

4 participants