Fix #996, #2254, #2589, #2875: Viewport scrolling getting stuck or shaking

Shaking while at the edge of the map has been completely eliminated. In
order to do this, comparison with tile height was also removed which
fixed a few outlier cases.

The main cause was viewport axis were only being set if it's respective
isometric axis was at the boundary, instead of either isometric axis.
Viewport no longer gets stuck which was related to the shaking in the
end. (#2875)

Refactored viewport_update_position. I moved
viewport_set_underground_flag above the bounds checking function since
it had no relation to it. (#996, #2589)

Scrolling on the map edge with arrow keys or mouse edge will now go the
same speed in both directions. (#2254)

Added changelog entry.
This commit is contained in:
Robert Jordan 2017-11-08 11:43:50 -05:00 committed by Michael Steenbeek
parent 27e3703fec
commit 4c3065619e
5 changed files with 112 additions and 61 deletions

View File

@ -22,7 +22,9 @@
- Feature: Allow using object files from RCT Classic.
- Feature: Title sequences now testable in-game.
- Fix: [#816] In the map window, there are more peeps flickering than there are selected (original bug).
- Fix: [#996, #2589, #2875] Viewport scrolling no longer shakes or gets stuck.
- Fix: [#1833, #4937, #6138] 'Too low!' warning when building rides and shops on the lowest land level (original bug).
- Fix: [#2254] Edge scrolling horizontally now has the same speed as vertical edge scrolling.
- Fix: [#6199] Inverted Hairpin Coaster vehicle tab is not centred.
- Fix: [#4991] Inverted helices can be built on the Lay Down RC, but are not drawn.
- Fix: [#5417] Hacked Crooked House tracked rides do not dispatch vehicles.

View File

@ -101,17 +101,7 @@ static void game_handle_key_scroll()
const uint8 * keysState = context_get_keys_state();
get_keyboard_map_scroll(keysState, &scrollX, &scrollY);
// Scroll viewport
if (scrollX != 0)
{
mainWindow->saved_view_x += scrollX * (12 << mainWindow->viewport->zoom);
input_set_flag(INPUT_FLAG_VIEWPORT_SCROLLING, true);
}
if (scrollY != 0)
{
mainWindow->saved_view_y += scrollY * (12 << mainWindow->viewport->zoom);
input_set_flag(INPUT_FLAG_VIEWPORT_SCROLLING, true);
}
input_scroll_viewport(scrollX, scrollY);
}
static sint32 input_scancode_to_rct_keycode(sint32 sdl_key)

View File

@ -1508,15 +1508,7 @@ void game_handle_edge_scroll()
else if (cursorState->y >= context_get_height() - 1)
scrollY = 1;
// Scroll viewport
if (scrollX != 0) {
mainWindow->saved_view_x += scrollX * (12 << mainWindow->viewport->zoom);
_inputFlags |= INPUT_FLAG_VIEWPORT_SCROLLING;
}
if (scrollY != 0) {
mainWindow->saved_view_y += scrollY * (12 << mainWindow->viewport->zoom);
_inputFlags |= INPUT_FLAG_VIEWPORT_SCROLLING;
}
input_scroll_viewport(scrollX, scrollY);
}
void input_set_flag(INPUT_FLAGS flag, bool on)
@ -1562,3 +1554,62 @@ bool input_test_place_object_modifier(PLACE_OBJECT_MODIFIER modifier)
{
return gInputPlaceObjectModifier & modifier;
}
void input_scroll_viewport(sint32 scrollX, sint32 scrollY)
{
rct_window * mainWindow = window_get_main();
rct_viewport * viewport = mainWindow->viewport;
sint32 dx = scrollX * (12 << viewport->zoom);
sint32 dy = scrollY * (12 << viewport->zoom);
if (scrollX != 0)
{
// Speed up scrolling horizontally when at the edge of the map
// so that the speed is consistent with vertical edge scrolling.
sint32 x = mainWindow->saved_view_x + viewport->view_width / 2 + dx;
sint32 y = mainWindow->saved_view_y + viewport->view_height / 2;
sint32 y_dy = mainWindow->saved_view_y + viewport->view_height / 2 + dy;
LocationXY16 mapCoord, mapCoord_dy;
mapCoord = viewport_coord_to_map_coord(x, y, 0);
mapCoord_dy = viewport_coord_to_map_coord(x, y_dy, 0);
// Check if we're crossing the boundary
// Clamp to the map minimum value
sint32 at_map_edge = 0;
sint32 at_map_edge_dy = 0;
if (mapCoord.x < MAP_MINIMUM_X_Y || mapCoord.y < MAP_MINIMUM_X_Y)
{
at_map_edge = 1;
}
if (mapCoord_dy.x < MAP_MINIMUM_X_Y || mapCoord_dy.y < MAP_MINIMUM_X_Y)
{
at_map_edge_dy = 1;
}
// Clamp to the map maximum value (scenario specific)
if (mapCoord.x > gMapSizeMinus2 || mapCoord.y > gMapSizeMinus2)
{
at_map_edge = 1;
}
if (mapCoord_dy.x > gMapSizeMinus2 || mapCoord_dy.y > gMapSizeMinus2)
{
at_map_edge_dy = 1;
}
// If we crossed the boundary, multiply the distance by 2
if (at_map_edge && at_map_edge_dy)
{
dx *= 2;
}
mainWindow->saved_view_x += dx;
_inputFlags |= INPUT_FLAG_VIEWPORT_SCROLLING;
}
if (scrollY != 0)
{
mainWindow->saved_view_y += dy;
_inputFlags |= INPUT_FLAG_VIEWPORT_SCROLLING;
}
}

View File

@ -119,6 +119,8 @@ void reset_tooltip_not_shown();
void input_reset_place_obj_modifier();
void input_scroll_viewport(sint32 scrollX, sint32 scrollY);
#ifdef __cplusplus
}
#endif

View File

@ -510,73 +510,76 @@ static void viewport_set_underground_flag(sint32 underground, rct_window* window
*
* rct2: 0x006E7A3A
*/
void viewport_update_position(rct_window *window)
void viewport_update_position(rct_window * window)
{
window_event_resize_call(window);
rct_viewport* viewport = window->viewport;
if (!viewport)return;
rct_viewport * viewport = window->viewport;
if (!viewport) return;
if (window->viewport_target_sprite != SPRITE_INDEX_NULL) {
if (window->viewport_target_sprite != SPRITE_INDEX_NULL)
{
viewport_update_sprite_follow(window);
return;
}
sint16 x = viewport->view_width / 2 + window->saved_view_x;
sint16 y = viewport->view_height / 2 + window->saved_view_y;
sint16 z;
viewport_adjust_for_map_height(&x, &y, &z);
viewport_set_underground_flag(0, window, viewport);
//Clamp to the map minimum value
sint32 at_map_edge_x = 0;
if (x < MAP_MINIMUM_X_Y){
x = MAP_MINIMUM_X_Y;
at_map_edge_x = 1;
sint16 x = window->saved_view_x + viewport->view_width / 2;
sint16 y = window->saved_view_y + viewport->view_height / 2;
LocationXY16 mapCoord;
mapCoord = viewport_coord_to_map_coord(x, y, 0);
// Clamp to the map minimum value
sint32 at_map_edge = 0;
if (mapCoord.x < MAP_MINIMUM_X_Y)
{
mapCoord.x = MAP_MINIMUM_X_Y;
at_map_edge = 1;
}
sint32 at_map_edge_y = 0;
if (y < MAP_MINIMUM_X_Y){
y = MAP_MINIMUM_X_Y;
at_map_edge_y = 1;
if (mapCoord.y < MAP_MINIMUM_X_Y)
{
mapCoord.y = MAP_MINIMUM_X_Y;
at_map_edge = 1;
}
//Clamp to the map maximum value (scenario specific)
if (x > gMapSizeMinus2){
x = gMapSizeMinus2;
at_map_edge_x = 1;
// Clamp to the map maximum value (scenario specific)
if (mapCoord.x > gMapSizeMinus2)
{
mapCoord.x = gMapSizeMinus2;
at_map_edge = 1;
}
if (y > gMapSizeMinus2){
y = gMapSizeMinus2;
at_map_edge_y = 1;
if (mapCoord.y > gMapSizeMinus2)
{
mapCoord.y = gMapSizeMinus2;
at_map_edge = 1;
}
if (at_map_edge_x || at_map_edge_y) {
// The &0xFFFF is to prevent the sign extension messing the
// function up.
sint32 zz = tile_element_height(x & 0xFFFF, y & 0xFFFF);
if (at_map_edge)
{
sint32 _2d_x, _2d_y;
centre_2d_coordinates(x, y, zz, &_2d_x, &_2d_y, viewport);
centre_2d_coordinates(mapCoord.x, mapCoord.y, 0, &_2d_x, &_2d_y, viewport);
if (at_map_edge_x)
window->saved_view_x = _2d_x;
if (at_map_edge_y)
window->saved_view_y = _2d_y;
window->saved_view_x = _2d_x;
window->saved_view_y = _2d_y;
}
x = window->saved_view_x;
y = window->saved_view_y;
if (window->flags & WF_SCROLLING_TO_LOCATION){
if (window->flags & WF_SCROLLING_TO_LOCATION)
{
// Moves the viewport if focusing in on an item
uint8 flags = 0;
x -= viewport->view_x;
if (x < 0){
if (x < 0)
{
x = -x;
flags |= 1;
}
y -= viewport->view_y;
if (y < 0){
if (y < 0)
{
y = -y;
flags |= 2;
}
@ -584,13 +587,16 @@ void viewport_update_position(rct_window *window)
y = (y + 7) / 8;
//If we are at the final zoom position
if (!x && !y){
if (!x && !y)
{
window->flags &= ~WF_SCROLLING_TO_LOCATION;
}
if (flags & 1){
if (flags & 1)
{
x = -x;
}
if (flags & 2){
if (flags & 2)
{
y = -y;
}
x += viewport->view_x;