diff --git a/client/player_character.hpp b/client/player_character.hpp index 1f6bc7a..9dde742 100644 --- a/client/player_character.hpp +++ b/client/player_character.hpp @@ -25,6 +25,7 @@ #include "vector2.hpp" #include "sprite_sheet.hpp" +//TODO: correct the PlayerCharacter class and it's movement system class PlayerCharacter { public: enum class Direction { diff --git a/client/scenes/in_world.cpp b/client/scenes/in_world.cpp index d6cb5a5..936be7d 100644 --- a/client/scenes/in_world.cpp +++ b/client/scenes/in_world.cpp @@ -404,76 +404,34 @@ void InWorld::RequestRegion(int x, int y) { //Utilities //------------------------- -int InWorld::CheckBufferDistance(Region* const region) { - /* TODO: Remove InWorld::CheckBufferDistance(), and replace it with a simpler system - * DOCUMENTATION - * This algorithm is extremely complex and involed, but initial tests show - * that it gives the right answers. The purpose is to determine how far off screen - * a certain region is, so that it can be unloaded when necessary. - * - * If the region is actually onscreen, then there's no reason to run the rest, so - * the algorithm corrects for the camera's location, before checking the bounds of - * the screen. - * - * The next part is tricky. If X or Y is negative, then it is divided by the - * graphical size of the regions, resulting in a usable integer, representing how - * far from the screen it is in "region units". If, however, X or Y is larger than - * 0, than first, the size of the screen is subtracted from that variable, before - * it is then divided by the graphical size of a region. Finally, to compensate for - * the off by one error, 1 is added at the end. - * - * Since only the magnitude of the distance in either direction is needed, this - * method returns the largest absolute value of X or Y. - * - * The final result of this algorithm is an integer representing how far, rounded - * up, a certain region is from the screen's edges in any direction, measured in - * "region units". This algorithm may be flawed, in which case, I recommend simply - * replacing it with a boolean check, to see if the region's distance from the player - * is larger than a certain value. This algorithm lacks the advantages I initially - * expected, so that may be beneficial at some point. - */ - - //locations relative to the camera - int x = region->GetX() - camera.x; - int y = region->GetY() - camera.y; - - //if the region is visible, return -1 - if (x >= -REGION_WIDTH * tileSheet.GetTileW() && x < camera.width && - y >= -REGION_HEIGHT * tileSheet.GetTileH() && y < camera.height) { - return -1; - } - - //prune the screen's area from the algorithm; get the pseudo-indexes - if (x < 0) x /= (REGION_WIDTH * tileSheet.GetTileW()); - if (y < 0) y /= (REGION_HEIGHT * tileSheet.GetTileH()); - if (x > 0) x = (x - camera.width) / (REGION_WIDTH * tileSheet.GetTileW()) + 1; - if (y > 0) y = (y - camera.height) / (REGION_HEIGHT * tileSheet.GetTileH()) + 1; - - //return the pseudo-index with the greatest magnitude - return std::max(abs(x), abs(y)); -} - -//TODO: Revise InWorld::UpdateMap() after InWorld::CheckBufferDistance() +//TODO: convert this into a more generic function?; using parameters for the bounds void InWorld::UpdateMap() { + //these represent the zone of regions that the client needs loaded, including the mandatory buffers (+1/-1) + int xStart = snapToBase(REGION_WIDTH, camera.x/tileSheet.GetTileW()) - REGION_WIDTH; + int xEnd = snapToBase(REGION_WIDTH, (camera.x+camera.width)/tileSheet.GetTileW()) + REGION_WIDTH; + + int yStart = snapToBase(REGION_HEIGHT, camera.y/tileSheet.GetTileH()) - REGION_HEIGHT; + int yEnd = snapToBase(REGION_HEIGHT, (camera.y+camera.height)/tileSheet.GetTileH()) + REGION_HEIGHT; + //prune distant regions for (auto it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); /* EMPTY */) { - if (CheckBufferDistance(*it) > 2) { - regionPager.UnloadRegion((*it)->GetX(), (*it)->GetY()); + //check if the region is outside off this area + if ((*it)->GetX() < xStart || (*it)->GetX() > xEnd || (*it)->GetY() < yStart || (*it)->GetY() > yEnd) { - //reset - it = regionPager.GetContainer()->begin(); + //clunky, but the alternative was time consuming + int tmpX = (*it)->GetX(); + int tmpY = (*it)->GetY(); + ++it; + + regionPager.UnloadRegion(tmpX, tmpY); continue; } ++it; } - //TODO: make the region units official? - int regionUnitX = REGION_WIDTH * tileSheet.GetTileW(); - int regionUnitY = REGION_HEIGHT * tileSheet.GetTileH(); - - //request empty regions, including buffers (-1 & +1 region unit) - for (int i = snapToBase(regionUnitX, camera.x - regionUnitX); i <= snapToBase(regionUnitX, camera.x + camera.width + regionUnitX); i += regionUnitX) { - for (int j = snapToBase(regionUnitY, camera.y - regionUnitY); j <= snapToBase(regionUnitY, camera.y + camera.height + regionUnitY); j += regionUnitY) { + //request empty regions within this zone + for (int i = xStart; i <= xEnd; i += REGION_WIDTH) { + for (int j = yStart; j <= yEnd; j += REGION_HEIGHT) { if (!regionPager.FindRegion(i, j)) { RequestRegion(i, j); } diff --git a/client/scenes/in_world.hpp b/client/scenes/in_world.hpp index 899ee8a..bb0cc5c 100644 --- a/client/scenes/in_world.hpp +++ b/client/scenes/in_world.hpp @@ -86,7 +86,6 @@ protected: void RequestRegion(int x, int y); //utilities - int CheckBufferDistance(Region* const); void UpdateMap(); //globals diff --git a/common/graphics/tile_sheet.cpp b/common/graphics/tile_sheet.cpp index e1b9ea2..bb9a4cb 100644 --- a/common/graphics/tile_sheet.cpp +++ b/common/graphics/tile_sheet.cpp @@ -53,8 +53,8 @@ void TileSheet::DrawRegionTo(SDL_Surface* const dest, Region* const region, int image.SetClipX((tile-1) % XCount * image.GetClipW()); image.SetClipY((tile-1) / XCount * image.GetClipH()); image.DrawTo(dest, - region->GetX() + i * image.GetClipW() - camX, - region->GetY() + j * image.GetClipH() - camY); + (region->GetX() + i) * image.GetClipW() - camX, + (region->GetY() + j) * image.GetClipH() - camY); } } } diff --git a/common/map/region_pager.hpp b/common/map/region_pager.hpp index 9b3b991..95864f0 100644 --- a/common/map/region_pager.hpp +++ b/common/map/region_pager.hpp @@ -109,10 +109,7 @@ public: for (std::list::iterator it = regionList.begin(); it != regionList.end(); /* EMPTY */) { if ((*it)->GetX() == x && (*it)->GetY() == y) { allocator.Unload(*it); - regionList.erase(it); - - //reset the loop, because of reasons - it = regionList.begin(); + it = regionList.erase(it); continue; } ++it;