Skip to content

Commit 632ba0e

Browse files
authored
Fix and improve fast-forward (frame skip) (#4989)
1 parent a405ac0 commit 632ba0e

6 files changed

Lines changed: 51 additions & 63 deletions

File tree

src/bflib_datetm.cpp

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ void initial_time_point()
5858
game.process_turn_time = 1.0; // Begin initial turn as soon as possible (like original game)
5959
}
6060

61-
long double get_time_tick_ns()
61+
int64_t get_time_tick_ns()
6262
{
6363
return TimeTickNs;
6464
}
@@ -95,22 +95,6 @@ int get_trigger_time_measurement_fps(struct TriggerTimeMeasurement *trigger)
9595
return cnt;
9696
}
9797

98-
99-
float get_delta_time()
100-
{
101-
// Allow frame skip to work correctly when delta time is enabled
102-
if ( (game.frame_skip != 0) && ((get_gameturn() % game.frame_skip) != 0)) {
103-
return 1.0;
104-
}
105-
long double frame_time_in_nanoseconds = std::chrono::duration_cast<std::chrono::nanoseconds>(TimeNow - delta_time_previous_timepoint).count();
106-
delta_time_previous_timepoint = TimeNow;
107-
float calculated_delta_time = (frame_time_in_nanoseconds/1000000000.0) * turns_per_second;
108-
if (calculated_delta_time > 1.0) { // Fix for when initially loading the map, frametime takes too long. Possibly other circumstances too.
109-
calculated_delta_time = 1.0;
110-
}
111-
return calculated_delta_time;
112-
}
113-
11498
void frametime_set_all_measurements_to_be_displayed()
11599
{
116100
// Display the frametime of the previous frame only, not the current frametime. Drawing "frametime_current" is a bad idea because frametimes are displayed on screen half-way through the rest of the measurements.

src/bflib_datetm.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,10 @@ struct FrametimeMeasurements {
9595

9696
extern int debug_display_frametime;
9797
extern void initial_time_point();
98-
extern long double get_time_tick_ns();
98+
extern int64_t get_time_tick_ns();
9999
extern void frametime_start_measurement(int frametime_kind);
100100
extern void frametime_end_measurement(int frametime_kind);
101101
extern void framerate_measurement_capture(int framerate_kind);
102-
extern float get_delta_time();
103102

104103
extern struct FrametimeMeasurements frametime_measurements;
105104

src/engine_render.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -534,17 +534,17 @@ extern float interpolate_time; // main.cpp
534534

535535
float interpolate(float previous, float current)
536536
{
537-
if (is_feature_on(Ft_DeltaTime) == false || game.frame_skip > 0) {
537+
if (! is_feature_on(Ft_DeltaTime))
538538
return current;
539-
}
539+
540540
return LbLerp(previous, current, interpolate_time);
541541
}
542542

543543
float interpolate_angle(float previous, float current)
544544
{
545-
if (is_feature_on(Ft_DeltaTime) == false || game.frame_skip > 0) {
545+
if (! is_feature_on(Ft_DeltaTime))
546546
return current;
547-
}
547+
548548
return lerp_angle(previous, current, interpolate_time);
549549
}
550550

src/front_input.c

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ struct GuiLayer gui_layer = {GuiLayer_Default};
9898

9999
TbBool first_person_see_item_desc = false;
100100

101+
static TbBool move_camera_this_turn;
102+
101103
long old_mx;
102104
long old_my;
103105

@@ -2143,10 +2145,6 @@ static short get_map_action_inputs(void)
21432145
}
21442146
}
21452147

2146-
// TODO: Might want to initiate this in main() and pass a reference to it
2147-
// rather than using this global variable. But this works.
2148-
int global_frameskipTurn = 0;
2149-
21502148
static void get_isometric_or_front_view_mouse_inputs(struct Packet *pckt,int rotate_pressed,TbBool mods_used)
21512149
{
21522150
// Reserve the scroll wheel for the resurrect and transfer creature specials
@@ -2185,13 +2183,8 @@ static void get_isometric_or_front_view_mouse_inputs(struct Packet *pckt,int rot
21852183
}
21862184
}
21872185
// Only pan the camera as often as normal despite frameskip
2188-
if (game.frame_skip > 0)
2189-
{
2190-
TbBool moveTheCamera = (global_frameskipTurn == 0);
2191-
global_frameskipTurn++;
2192-
if (global_frameskipTurn > game.frame_skip) global_frameskipTurn = 0;
2193-
if (!moveTheCamera) return;
2194-
}
2186+
if (! move_camera_this_turn)
2187+
return;
21952188
// Camera Panning : mouse at window edge scrolling feature
21962189
if (!LbIsMouseActive())
21972190
{
@@ -2255,15 +2248,7 @@ static void get_isometric_view_nonaction_inputs(void)
22552248

22562249
get_isometric_or_front_view_mouse_inputs(packet, rotate_pressed, no_mods);
22572250
// Only update the camera as often as normal despite frameskip
2258-
TbBool moveTheCamera = true;
2259-
if (game.frame_skip > 0)
2260-
{
2261-
moveTheCamera = (global_frameskipTurn == 0);
2262-
global_frameskipTurn++;
2263-
if (global_frameskipTurn > game.frame_skip)
2264-
global_frameskipTurn = 0;
2265-
}
2266-
if (moveTheCamera)
2251+
if (move_camera_this_turn)
22672252
{
22682253
if (rotate_pressed)
22692254
{
@@ -2346,15 +2331,7 @@ static void get_front_view_nonaction_inputs(void)
23462331

23472332
get_isometric_or_front_view_mouse_inputs(pckt,rotate_pressed,no_mods);
23482333
// Only update the camera as often as normal despite frameskip
2349-
TbBool moveTheCamera = true;
2350-
if (game.frame_skip > 0)
2351-
{
2352-
moveTheCamera = (global_frameskipTurn == 0);
2353-
global_frameskipTurn++;
2354-
if (global_frameskipTurn > game.frame_skip)
2355-
global_frameskipTurn = 0;
2356-
}
2357-
if (moveTheCamera)
2334+
if (move_camera_this_turn)
23582335
{
23592336
if (rotate_pressed)
23602337
{
@@ -2870,6 +2847,8 @@ static TbBool active_menu_functions_while_paused(void)
28702847
*/
28712848
static short get_inputs(void)
28722849
{
2850+
move_camera_this_turn = game.frame_skip == 0 || game.play_gameturn % game.frame_skip == 0;
2851+
28732852
if ((game.mode_flags & MFlg_IsDemoMode) != 0)
28742853
{
28752854
SYNCDBG(5,"Starting for demo mode");

src/frontend.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ extern "C" {
9797
#endif
9898

9999
extern long double last_draw_completed_time;
100-
long double get_time_tick_ns();
101100
/******************************************************************************/
102101
TbClockMSec gui_message_timeout = 0;
103102
char gui_message_text[TEXT_BUFFER_LENGTH];

src/main.cpp

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3261,7 +3261,7 @@ short display_should_be_updated_this_turn(void)
32613261
if ( (game.turns_fastforward == 0) && (!game.packet_loading_in_progress) )
32623262
{
32633263
find_frame_rate();
3264-
if ( (game.frame_skip == 0) || ((get_gameturn() % game.frame_skip) == 0))
3264+
if ( is_feature_on(Ft_DeltaTime) || (game.frame_skip == 0) || ((get_gameturn() % game.frame_skip) == 0))
32653265
return true;
32663266
} else
32673267
if ( ((get_gameturn() & 0x3F)==0) ||
@@ -3421,12 +3421,32 @@ static bool use_delta_time()
34213421
return is_feature_on(Ft_DeltaTime) || network_is_active();
34223422
}
34233423

3424+
static void update_frontend_delta_time()
3425+
{
3426+
static int64_t prev = 0;
3427+
const int64_t now = get_time_tick_ns();
3428+
const int64_t ns = now - prev;
3429+
prev = now;
3430+
const long double dt = ns / 1e9L * turns_per_second;
3431+
game.delta_time = min(max(dt, 0.L), 1.L);
3432+
}
3433+
34243434
static void update_gameplay_delta_time()
34253435
{
34263436
if (use_delta_time()) {
3427-
long double process_delta_time = get_delta_time() * multiplayer_clock_adjust;
3428-
time_since_last_draw += process_delta_time;
3429-
game.process_turn_time += process_delta_time;
3437+
static int64_t prev = 0;
3438+
const int64_t now = get_time_tick_ns();
3439+
const int64_t ns = now - prev;
3440+
prev = now;
3441+
3442+
const long double dt = min(max(ns / 1e9L * turns_per_second, 0.L), 1.L);
3443+
3444+
game.process_turn_time += dt * multiplayer_clock_adjust * max(game.frame_skip, 1);
3445+
3446+
// This sets game.delta_time, which is used to pace locally-displayed
3447+
// things (eg. tooltip scroll speed). It should not be affected by
3448+
// multiplayer clock adjustment or frameskip.
3449+
time_since_last_draw += dt;
34303450
} else {
34313451
// Set to 1 so that these variables don't affect anything. (if something is multiplied by 1 it doesn't change)
34323452
time_since_last_draw = 1;
@@ -3437,6 +3457,11 @@ static void update_gameplay_delta_time()
34373457

34383458
static void gameplay_loop_draw()
34393459
{
3460+
update_gameplay_delta_time();
3461+
3462+
if (game.process_turn_time > 1.0 && time_since_last_draw < 1.0)
3463+
do_draw = false;
3464+
34403465
if (is_feature_on(Ft_DeltaTime) && ! network_is_active())
34413466
{
34423467
frametime_start_measurement(Frametime_Sleep);
@@ -3546,8 +3571,8 @@ static void gameplay_loop_logic()
35463571
exchange_packets();
35473572

35483573
update_gameplay_delta_time();
3549-
if (game.process_turn_time > 2.0)
3550-
game.process_turn_time = 2.0;
3574+
if (game.process_turn_time > turns_per_second + 1)
3575+
game.process_turn_time = turns_per_second + 1;
35513576

35523577
// Adjust client time scaling
35533578
if (netstate.my_id != SERVER_ID && network_is_active())
@@ -3619,9 +3644,11 @@ extern "C" void network_yield_waiting_gameplay_packets()
36193644
{
36203645
do_draw = true;
36213646
poll_inputs();
3647+
gameplay_loop_draw();
36223648
update_gameplay_delta_time();
3623-
if (game.process_turn_time <= 1.0 || time_since_last_draw > 1.0)
3624-
gameplay_loop_draw();
3649+
// Reduce game speed during lag spikes.
3650+
if (game.process_turn_time > 2.0)
3651+
game.process_turn_time = 2.0;
36253652
}
36263653

36273654
extern "C" void update_velocity(void);
@@ -3630,7 +3657,7 @@ extern "C" void fronttorture_update(void);
36303657

36313658
extern "C" void network_yield_draw_frontend()
36323659
{
3633-
game.delta_time = get_delta_time();
3660+
update_frontend_delta_time();
36343661
if (frontend_menu_state == FeSt_NETLAND_VIEW) {
36353662
check_mouse_scroll();
36363663
update_velocity();
@@ -3943,7 +3970,7 @@ static TbBool wait_at_frontend(void)
39433970
fade_palette_in = 0;
39443971
} else {
39453972
if (is_feature_on(Ft_DeltaTime) == true && should_use_delta_time_on_menu()) {
3946-
game.delta_time = get_delta_time();
3973+
update_frontend_delta_time();
39473974
} else {
39483975
int32_t frame_time;
39493976
frame_time = max(1, 1000 / turns_per_second);

0 commit comments

Comments
 (0)