Skip to content

Commit

Permalink
Refactor panorama again
Browse files Browse the repository at this point in the history
* Always writes rm2k3e compatible pan_x/pan_y.
* Fixes save game compatibility between Player
  and rm2k3e
  • Loading branch information
mateofio committed Dec 21, 2018
1 parent 76b12d9 commit 53654dc
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 39 deletions.
106 changes: 68 additions & 38 deletions src/game_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,20 +372,30 @@ void Game_Map::ScrollRight(int distance) {
int x = map_info.position_x;
AddScreenX(x, distance);
map_info.position_x = x;
if (distance == 0) {
return;
}
// Unused, except compatibility with RPG_RT
auto& pan_x = Main_Data::game_data.screen.pan_x;
const auto pan_limit_x = 20 * SCREEN_TILE_WIDTH;
pan_x = (pan_x - distance + pan_limit_x) % pan_limit_x;

Game_Map::Parallax::ScrollRight(distance);
}

void Game_Map::ScrollDown(int distance) {
int y = map_info.position_y;
AddScreenY(y, distance);
map_info.position_y = y;
if (distance == 0) {
return;
}
// Unused, except compatibility with RPG_RT
auto& pan_y = Main_Data::game_data.screen.pan_y;
const auto pan_limit_y = 10 * SCREEN_TILE_WIDTH;
pan_y = (pan_y + distance + pan_limit_y) % pan_limit_y;

Game_Map::Parallax::ScrollDown(distance);
}

// Add inc to acc, clamping the result into the range [low, high].
Expand Down Expand Up @@ -1472,8 +1482,6 @@ FileRequestAsync* Game_Map::RequestMap(int map_id) {
/////////////

namespace {
int parallax_x;
int parallax_y;
int parallax_width;
int parallax_height;
}
Expand Down Expand Up @@ -1514,47 +1522,71 @@ std::string Game_Map::Parallax::GetName() {
}

int Game_Map::Parallax::GetX() {
return (parallax_x - panorama.pan_x / 2) / TILE_SIZE;
return (-panorama.pan_x / TILE_SIZE) / 2;
}

int Game_Map::Parallax::GetY() {
return (parallax_y - panorama.pan_y / 2) / TILE_SIZE;
return (-panorama.pan_y / TILE_SIZE) / 2;
}

void Game_Map::Parallax::Initialize(int width, int height) {
parallax_width = width;
parallax_height = height;

UpdatePosition(true);
ResetPositionX();
ResetPositionY();
}

void Game_Map::Parallax::UpdatePosition(bool init) {
void Game_Map::Parallax::ResetPositionX() {
Params params = GetParallaxParams();

// RPG_RT bug:
// On loaded save games, RPG_RT will always reset
// parallax_x/y to 0 when the map is looping.
// We don't emulate this.
panorama.pan_x = 0;
if (params.scroll_horz || LoopHorizontal())
panorama.pan_x = map_info.position_x;
else if (GetWidth() > 20 && parallax_width > SCREEN_TARGET_WIDTH)
panorama.pan_x = std::min(map_info.position_x,
(map_info.position_x / (SCREEN_TILE_WIDTH / TILE_SIZE)) * (parallax_width - SCREEN_TARGET_WIDTH) / (GetWidth() - 20)) * 2;
}

void Game_Map::Parallax::ResetPositionY() {
Params params = GetParallaxParams();

panorama.pan_y = 0;
if (params.scroll_vert || Game_Map::LoopVertical())
panorama.pan_y = map_info.position_y;
else if (GetHeight() > 15 && parallax_height > SCREEN_TARGET_HEIGHT)
panorama.pan_y = std::min(map_info.position_y,
(map_info.position_y / (SCREEN_TILE_WIDTH / TILE_SIZE)) * (parallax_height - SCREEN_TARGET_HEIGHT) / (GetHeight() - 15)) * 2;
}

void Game_Map::Parallax::ScrollRight(int distance) {
Params params = GetParallaxParams();
if (params.name.empty()) {
return;
}

if (params.scroll_horz) {
const auto w = parallax_width * TILE_SIZE * 2;
panorama.pan_x = (panorama.pan_x + distance + w) % w;
return;
}

ResetPositionX();
}

if (init || !Game_Map::LoopHorizontal()) {
if (params.scroll_horz || LoopHorizontal())
parallax_x = -map_info.position_x / 2;
else if (GetWidth() > 20 && parallax_width > SCREEN_TARGET_WIDTH)
parallax_x = -std::min(map_info.position_x,
(map_info.position_x / (SCREEN_TILE_WIDTH / TILE_SIZE)) * (parallax_width - SCREEN_TARGET_WIDTH) / (GetWidth() - 20));
else
parallax_x = 0;
void Game_Map::Parallax::ScrollDown(int distance) {
Params params = GetParallaxParams();
if (params.name.empty()) {
return;
}

if (init || !Game_Map::LoopVertical()) {
if (params.scroll_vert || Game_Map::LoopVertical())
parallax_y = -map_info.position_y / 2;
else if (GetHeight() > 15 && parallax_height > SCREEN_TARGET_HEIGHT)
parallax_y = -std::min(map_info.position_y,
(map_info.position_y / (SCREEN_TILE_WIDTH / TILE_SIZE)) * (parallax_height - SCREEN_TARGET_HEIGHT) / (GetHeight() - 15));
else
parallax_y = 0;
if (params.scroll_vert) {
const auto h = parallax_height * TILE_SIZE * 2;
panorama.pan_y = (panorama.pan_y + distance + h) % h;
return;
}

ResetPositionY();
}

void Game_Map::Parallax::Update() {
Expand All @@ -1563,24 +1595,22 @@ void Game_Map::Parallax::Update() {
if (params.name.empty())
return;

UpdatePosition();

auto scroll_amt = [](int speed) {
if (speed > 0) return 1 << (speed - 1);
if (speed < 0) return -(1 << (-speed - 1));
return 0;
return speed < 0 ? (1 << -speed) : -(1 << speed);
};


if (params.scroll_horz && params.scroll_horz_auto) {
if (params.scroll_horz
&& params.scroll_horz_auto
&& params.scroll_horz_speed != 0) {
const auto w = parallax_width * TILE_SIZE * 2;
panorama.pan_x -= scroll_amt(params.scroll_horz_speed) * 2;
panorama.pan_x = (panorama.pan_x + w) % w;
panorama.pan_x = (panorama.pan_x + scroll_amt(params.scroll_horz_speed) + w) % w;
}
if (params.scroll_vert && params.scroll_vert_auto) {

if (params.scroll_vert
&& params.scroll_vert_auto
&& params.scroll_vert_speed != 0) {
const auto h = parallax_height * TILE_SIZE * 2;
panorama.pan_y -= scroll_amt(params.scroll_vert_speed) * 2;
panorama.pan_y = (panorama.pan_y + h) % h;
panorama.pan_y = (panorama.pan_y + scroll_amt(params.scroll_vert_speed) + h) % h;
}
}

Expand Down
6 changes: 5 additions & 1 deletion src/game_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,11 @@ namespace Game_Map {
*
* @param init if true will always reset position, even on looping maps
*/
void UpdatePosition(bool init = false);
void ResetPositionX();
void ResetPositionY();

void ScrollRight(int distance);
void ScrollDown(int distance);

/** Update autoscrolling BG (call every frame). */
void Update();
Expand Down

0 comments on commit 53654dc

Please sign in to comment.