Skip to content
Open
14 changes: 2 additions & 12 deletions src/game_interpreter_control_variables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,21 +190,11 @@ int ControlVariables::Event(int op, int event_id, const Game_BaseInterpreterCont
break;
case 4: {
// Screen X
if (Player::game_config.fake_resolution.Get()) {
int pan_delta = (Game_Player::GetDefaultPanX() - lcf::rpg::SavePartyLocation::kPanXDefault) / TILE_SIZE;
return character->GetScreenX() - pan_delta;
} else {
return character->GetScreenX();
}
return character->GetScreenX();
}
case 5: {
// Screen Y
if (Player::game_config.fake_resolution.Get()) {
int pan_delta = (Game_Player::GetDefaultPanY() - lcf::rpg::SavePartyLocation::kPanYDefault) / TILE_SIZE;
return character->GetScreenY() - pan_delta;
} else {
return character->GetScreenY();
}
return character->GetScreenY();
}
case 6:
// Event ID
Expand Down
30 changes: 27 additions & 3 deletions src/game_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1724,6 +1724,14 @@ void Game_Map::SetPositionX(int x, bool reset_panorama) {
const int map_width = GetTilesX() * SCREEN_TILE_SIZE;
if (LoopHorizontal()) {
x = Utils::PositiveModulo(x, map_width);

// If the map is too small to fit in the screen, add an offset corresponding to the black border's size
if (Player::game_config.fake_resolution.Get()) {
int map_width_in_pixels = Game_Map::GetTilesX() * TILE_SIZE;
if (map_width_in_pixels < Player::screen_width) {
x += ((Player::screen_width - map_width_in_pixels) / 2 / TILE_SIZE) * SCREEN_TILE_SIZE;
}
}
} else {
// Do not use std::clamp here. When the map is smaller than the screen the
// upper bound is smaller than the lower bound making the function fail.
Expand All @@ -1748,6 +1756,14 @@ void Game_Map::SetPositionY(int y, bool reset_panorama) {
const int map_height = GetTilesY() * SCREEN_TILE_SIZE;
if (LoopVertical()) {
y = Utils::PositiveModulo(y, map_height);

// If the map is too small to fit in the screen, add an offset corresponding to the black border's size
if (Player::game_config.fake_resolution.Get()) {
int map_height_in_pixels = Game_Map::GetTilesY() * TILE_SIZE;
if (map_height_in_pixels < Player::screen_height) {
y += ((Player::screen_height - map_height_in_pixels) / 2 / TILE_SIZE) * SCREEN_TILE_SIZE;
}
}
} else {
// Do not use std::clamp here. When the map is smaller than the screen the
// upper bound is smaller than the lower bound making the function fail.
Expand Down Expand Up @@ -2145,9 +2161,13 @@ void Game_Map::Parallax::ResetPositionX() {
parallax_fake_x = false;

if (!params.scroll_horz && !LoopHorizontal()) {
// What is the width of the panorama to display on screen?
int pan_screen_width = Player::screen_width;
if (Player::game_config.fake_resolution.Get()) {
pan_screen_width = SCREEN_TARGET_WIDTH;
if (Player::game_config.fake_resolution.Get()) {
int map_width = Game_Map::GetTilesX() * TILE_SIZE;
if (map_width < pan_screen_width) {
pan_screen_width = map_width;
}
}

int tiles_per_screen = pan_screen_width / TILE_SIZE;
Expand Down Expand Up @@ -2183,9 +2203,13 @@ void Game_Map::Parallax::ResetPositionY() {
parallax_fake_y = false;

if (!params.scroll_vert && !Game_Map::LoopVertical()) {
// What is the height of the panorama to display on screen?
int pan_screen_height = Player::screen_height;
if (Player::game_config.fake_resolution.Get()) {
pan_screen_height = SCREEN_TARGET_HEIGHT;
int map_height = Game_Map::GetTilesY() * TILE_SIZE;
if (map_height < pan_screen_height) {
pan_screen_height = map_height;
}
}

int tiles_per_screen = pan_screen_height / TILE_SIZE;
Expand Down
30 changes: 24 additions & 6 deletions src/game_player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,15 +191,33 @@ void Game_Player::UpdateScroll(int amount, bool was_jumping) {
return;
}

auto dx = (GetX() * SCREEN_TILE_SIZE) - Game_Map::GetPositionX() - GetPanX();
auto dy = (GetY() * SCREEN_TILE_SIZE) - Game_Map::GetPositionY() - GetPanY();
const auto map_width = Game_Map::GetTilesX() * SCREEN_TILE_SIZE;
const auto map_height = Game_Map::GetTilesY() * SCREEN_TILE_SIZE;

// When using FakeResolution mode, if the map is too small to fit the screen
// we need to calculate the black border offset, in case of a looping map for example
int screen_offset_x = 0;
if (Player::game_config.fake_resolution.Get()) {
int map_width_in_pixels = Game_Map::GetTilesX() * TILE_SIZE;
if (map_width_in_pixels < Player::screen_width) {
screen_offset_x = ((Player::screen_width - map_width_in_pixels) / 2 / TILE_SIZE) * SCREEN_TILE_SIZE;
}
}
int screen_offset_y = 0;
if (Player::game_config.fake_resolution.Get()) {
int map_height_in_pixels = Game_Map::GetTilesY() * TILE_SIZE;
if (map_height_in_pixels < Player::screen_height) {
screen_offset_y = ((Player::screen_height - map_height_in_pixels) / 2 / TILE_SIZE) * SCREEN_TILE_SIZE;
}
}

const auto w = Game_Map::GetTilesX() * SCREEN_TILE_SIZE;
const auto h = Game_Map::GetTilesY() * SCREEN_TILE_SIZE;
auto dx = (GetX() * SCREEN_TILE_SIZE) - Game_Map::GetPositionX() - GetPanX() + screen_offset_x;
auto dy = (GetY() * SCREEN_TILE_SIZE) - Game_Map::GetPositionY() - GetPanY() + screen_offset_y;

dx = Utils::PositiveModulo(dx + w / 2, w) - w / 2;
dy = Utils::PositiveModulo(dy + h / 2, h) - h / 2;
dx = Utils::PositiveModulo(dx + map_width / 2, map_width) - map_width / 2;
dy = Utils::PositiveModulo(dy + map_height / 2, map_height) - map_height / 2;

// If sx or sy equals zero, no scrolling is needed in the corresponding direction
const auto sx = Utils::Signum(dx);
const auto sy = Utils::Signum(dy);

Expand Down
23 changes: 21 additions & 2 deletions src/sprite_picture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "game_windows.h"
#include "player.h"
#include "bitmap.h"
#include "game_map.h"

Sprite_Picture::Sprite_Picture(int pic_id, Drawable::Flags flags)
: Sprite(flags),
Expand Down Expand Up @@ -106,8 +107,26 @@ void Sprite_Picture::Draw(Bitmap& dst) {
}

if (Player::game_config.fake_resolution.Get()) {
SetX(x + Player::menu_offset_x);
SetY(y + Player::menu_offset_y);
if (data.fixed_to_map) {
// If the picture scrolls with the map, apply the black border if the map is too small
int offset_x = 0;
int map_width = Game_Map::GetTilesX() * TILE_SIZE;
if (map_width < Player::screen_width) {
offset_x += (Player::screen_width - map_width) / 2;
}
SetX(x + offset_x);

int offset_y = 0;
int map_height = Game_Map::GetTilesY() * TILE_SIZE;
if (map_height < Player::screen_height) {
offset_y += (Player::screen_height - map_height) / 2;
}
SetY(y + offset_y);
} else {
// If the picture doesn't scroll with the map, simulate the 340x240 screen
SetX(x + Player::menu_offset_x);
SetY(y + Player::menu_offset_y);
}
} else {
SetX(x);
SetY(y);
Expand Down
12 changes: 8 additions & 4 deletions src/spriteset_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,12 +326,16 @@ void Spriteset_Map::CalculateMapRenderOffset() {

void Spriteset_Map::CalculatePanoramaRenderOffset() {
// Resolution hack for Panorama
// If the map is too small to fit in the screen, add an offset corresponding to the black border's size
if (Player::game_config.fake_resolution.Get()) {
if (Game_Map::Parallax::FakeXPosition()) {
panorama->SetRenderOx((Player::screen_width - SCREEN_TARGET_WIDTH) / 2);
int map_width_in_pixels = Game_Map::GetTilesX() * TILE_SIZE;
if (map_width_in_pixels < Player::screen_width) {
panorama->SetRenderOx((Player::screen_width - map_width_in_pixels) / 2);
}
if (Game_Map::Parallax::FakeYPosition()) {
panorama->SetRenderOy((Player::screen_height - SCREEN_TARGET_HEIGHT) / 2);

int map_height_in_pixels = Game_Map::GetTilesY() * TILE_SIZE;
if (map_height_in_pixels < Player::screen_height) {
panorama->SetRenderOy((Player::screen_height - map_height_in_pixels) / 2);
}
}
}
Loading