1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-25 15:54:31 +01:00

uncapped FPS: fix viewport chopiness and reset after park load

This commit is contained in:
IntelOrca
2015-07-04 23:51:23 +01:00
parent 69a2d4a775
commit f0bba54e79
6 changed files with 66 additions and 9 deletions

View File

@@ -670,6 +670,7 @@ int game_load_sv6(const char *path)
reset_loaded_objects();
map_update_tile_pointers();
reset_0x69EBE4();
gOpenRCT2ResetFrameSmoothing = true;
return 1;
}

View File

@@ -156,6 +156,13 @@ void window_dispatch_update_all()
RCT2_CALLPROC_EBPSAFE(0x006EE411); // handle_text_input
}
void window_update_all_viewports()
{
for (rct_window *w = g_window_list; w < RCT2_NEW_WINDOW; w++)
if (w->viewport != NULL)
viewport_update_position(w);
}
/**
*
* rct2: 0x006E77A1
@@ -169,10 +176,7 @@ void window_update_all()
return;
gfx_draw_all_dirty_blocks();
for (w = g_window_list; w < RCT2_NEW_WINDOW; w++)
if (w->viewport != NULL)
viewport_update_position(w);
window_update_all_viewports();
// 1000 tick update
RCT2_GLOBAL(0x009DEB7C, sint16) += RCT2_GLOBAL(0x009DE588, sint16);

View File

@@ -459,6 +459,7 @@ extern rct_window* g_window_list;
extern ride_list_item _window_track_list_item;
void window_dispatch_update_all();
void window_update_all_viewports();
void window_update_all();
rct_window *window_create(int x, int y, int width, int height, uint32 *event_handlers, rct_windowclass cls, uint16 flags);
rct_window *window_create_auto_pos(int width, int height, uint32 *event_handlers, rct_windowclass cls, uint16 flags);

View File

@@ -42,6 +42,10 @@ bool gOpenRCT2Headless = false;
bool gOpenRCT2ShowChangelog;
// This needs to be set when a park is loaded. It could also be used to reset other important states, it should then be renamed
// to something more general.
bool gOpenRCT2ResetFrameSmoothing = false;
/** If set, will end the OpenRCT2 game loop. Intentially private to this module so that the flag can not be set back to 0. */
int _finished;
@@ -231,6 +235,21 @@ void openrct2_dispose()
platform_free();
}
/**
* Determines whether its worth tweening a sprite or not when frame smoothing is on.
*/
static bool sprite_should_tween(rct_sprite *sprite)
{
if (sprite->unknown.linked_list_type_offset == SPRITE_LINKEDLIST_OFFSET_VEHICLE)
return true;
if (sprite->unknown.linked_list_type_offset == SPRITE_LINKEDLIST_OFFSET_PEEP)
return true;
if (sprite->unknown.linked_list_type_offset == SPRITE_LINKEDLIST_OFFSET_UNKNOWN)
return true;
return false;
}
/**
* Run the main game loop until the finished flag is set at 40fps (25ms interval).
*/
@@ -250,6 +269,7 @@ static void openrct2_loop()
if (gConfigGeneral.uncap_fps) {
currentTick = SDL_GetTicks();
if (!uncappedinitialized) {
// Reset sprite locations
uncapTick = SDL_GetTicks();
for (uint16 i = 0; i < MAX_SPRITES; i++) {
spritelocations1[i].x = spritelocations2[i].x = g_sprite_list[i].unknown.x;
@@ -258,28 +278,51 @@ static void openrct2_loop()
}
uncappedinitialized = 1;
}
while (uncapTick <= currentTick && currentTick - uncapTick > 25) {
// Get the original position of each sprite
for (uint16 i = 0; i < MAX_SPRITES; i++) {
spritelocations1[i].x = g_sprite_list[i].unknown.x;
spritelocations1[i].y = g_sprite_list[i].unknown.y;
spritelocations1[i].z = g_sprite_list[i].unknown.z;
}
// Update the game so the sprite positions update
rct2_update();
if (gOpenRCT2ResetFrameSmoothing) {
gOpenRCT2ResetFrameSmoothing = false;
continue;
}
// Get the next position of each sprite
for (uint16 i = 0; i < MAX_SPRITES; i++) {
spritelocations2[i].x = g_sprite_list[i].unknown.x;
spritelocations2[i].y = g_sprite_list[i].unknown.y;
spritelocations2[i].z = g_sprite_list[i].unknown.z;
}
uncapTick += 25;
}
// Tween the position of each sprite from the last position to the new position based on the time between the last
// tick and the next tick.
float nudge = 1 - ((float)(currentTick - uncapTick) / 25);
for (uint16 i = 0; i < MAX_SPRITES; i++) {
if (!(g_sprite_list[i].unknown.linked_list_type_offset == SPRITE_LINKEDLIST_OFFSET_VEHICLE || g_sprite_list[i].unknown.linked_list_type_offset == SPRITE_LINKEDLIST_OFFSET_PEEP || g_sprite_list[i].unknown.linked_list_type_offset == SPRITE_LINKEDLIST_OFFSET_UNKNOWN)) {
if (!sprite_should_tween(&g_sprite_list[i]))
continue;
}
sprite_move(spritelocations2[i].x + (sint16)((spritelocations1[i].x - spritelocations2[i].x) * nudge), spritelocations2[i].y + (sint16)((spritelocations1[i].y - spritelocations2[i].y) * nudge), spritelocations2[i].z + (sint16)((spritelocations1[i].z - spritelocations2[i].z) * nudge), &g_sprite_list[i]);
sprite_move(
spritelocations2[i].x + (sint16)((spritelocations1[i].x - spritelocations2[i].x) * nudge),
spritelocations2[i].y + (sint16)((spritelocations1[i].y - spritelocations2[i].y) * nudge),
spritelocations2[i].z + (sint16)((spritelocations1[i].z - spritelocations2[i].z) * nudge),
&g_sprite_list[i]
);
invalidate_sprite(&g_sprite_list[i]);
}
// Viewports need to be updated to reduce chopiness of those which follow sprites
window_update_all_viewports();
platform_process_messages();
rct2_draw();
platform_draw();
@@ -288,10 +331,12 @@ static void openrct2_loop()
fps = 0;
secondTick = SDL_GetTicks();
}
// Restore the real positions of the sprites so they aren't left at the mid-tween positions
for (uint16 i = 0; i < MAX_SPRITES; i++) {
if (!(g_sprite_list[i].unknown.linked_list_type_offset == SPRITE_LINKEDLIST_OFFSET_VEHICLE || g_sprite_list[i].unknown.linked_list_type_offset == SPRITE_LINKEDLIST_OFFSET_PEEP || g_sprite_list[i].unknown.linked_list_type_offset == SPRITE_LINKEDLIST_OFFSET_UNKNOWN)) {
if (!sprite_should_tween(&g_sprite_list[i]))
continue;
}
sprite_move(spritelocations2[i].x, spritelocations2[i].y, spritelocations2[i].z, &g_sprite_list[i]);
}
} else {
@@ -307,7 +352,10 @@ static void openrct2_loop()
lastTick = currentTick;
platform_process_messages();
rct2_update();
gOpenRCT2ResetFrameSmoothing = false;
rct2_draw();
platform_draw();
}

View File

@@ -35,6 +35,7 @@ extern char gOpenRCT2StartupActionPath[512];
extern char gExePath[MAX_PATH];
extern bool gOpenRCT2Headless;
extern bool gOpenRCT2ShowChangelog;
extern bool gOpenRCT2ResetFrameSmoothing;
bool openrct2_initialise();
void openrct2_launch();

View File

@@ -30,6 +30,7 @@
#include "management/research.h"
#include "management/news_item.h"
#include "object.h"
#include "openrct2.h"
#include "peep/staff.h"
#include "platform/platform.h"
#include "ride/ride.h"
@@ -178,6 +179,7 @@ int scenario_load(const char *path)
reset_loaded_objects();
map_update_tile_pointers();
reset_0x69EBE4();
gOpenRCT2ResetFrameSmoothing = true;
return 1;
}