From 456122f5f0086ed0dbe1b784266b96e9624aa8e1 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Wed, 6 Jun 2018 16:44:25 -0400 Subject: zooming fixes when zooming out, the view center stays the same (shifted by map edges). when zooming in, the view center becomes the player position at the start of zoom. the boundary of player movement is now also set to the target view area at start of zoom. --- src/game.h | 11 +++++++++-- src/main.cpp | 47 +++++++++++++++++++++++++++++++++++------------ src/renderer.cpp | 41 ++++++++++++++++++++++++++--------------- src/renderer.h | 2 ++ 4 files changed, 72 insertions(+), 29 deletions(-) diff --git a/src/game.h b/src/game.h index 6d8a64f..200b691 100644 --- a/src/game.h +++ b/src/game.h @@ -92,12 +92,19 @@ public: int player_y = 0; bool renderPlayer = true; - int curZoom = INIT_ZOOM; int maxZoom = INIT_ZOOM; + int curZoom = INIT_ZOOM; + int curBoundX = map.getLeft(); + int curBoundY = map.getTop(); + bool zooming = false; - //size_t oldZoom; int zoomProgress = 0; + int zoomLength; + int lastZoomTop; + int lastZoomLeft; + int lastZoomWidth; + int lastZoomHeight; bool firstInput = false; Input lastInput; diff --git a/src/main.cpp b/src/main.cpp index a0085cb..4b13051 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -81,7 +81,11 @@ void tick(Game& game, bool onlyDark = false) bool movePlayer(Game& game, int x, int y) { - if (game.map.inBounds(x, y) && game.map.at(x,y).tile == Tile::Floor) + if (x >= game.curBoundX && + y >= game.curBoundY && + x < game.curBoundX + game.curZoom * ZOOM_X_FACTOR && + y < game.curBoundY + game.curZoom * ZOOM_Y_FACTOR && + game.map.at(x,y).tile == Tile::Floor) { if (game.map.at(game.player_x, game.player_y).tile == Tile::Floor) { @@ -366,11 +370,36 @@ void setZoom(Game& game, size_t zoom) growMap(game, zoom); } - // TODO: don't think this works well with rapid zoom changes - game.zoomProgress += (zoom - game.curZoom) * TILE_WIDTH; - //game.oldZoom = game.curZoom; + std::tie( + game.lastZoomLeft, + game.lastZoomTop, + game.lastZoomWidth, + game.lastZoomHeight) = + Renderer::calculateZoomRect(game); + + game.zoomProgress = 0; + game.zoomLength = + std::abs(static_cast(zoom - game.curZoom)) * TILE_WIDTH; game.curZoom = zoom; game.zooming = true; + + game.curBoundX = game.player_x - zoom * ZOOM_X_FACTOR / 2; + if (game.curBoundX < game.map.getLeft()) + { + game.curBoundX = game.map.getLeft(); + } else if (game.curBoundX + zoom * ZOOM_X_FACTOR >= game.map.getRight()) + { + game.curBoundX = game.map.getRight() - zoom * ZOOM_X_FACTOR; + } + + game.curBoundY = game.player_y - zoom * ZOOM_Y_FACTOR / 2; + if (game.curBoundY < game.map.getTop()) + { + game.curBoundY = game.map.getTop(); + } else if (game.curBoundY + zoom * ZOOM_Y_FACTOR >= game.map.getBottom()) + { + game.curBoundY = game.map.getBottom() - zoom * ZOOM_Y_FACTOR; + } } int main(int, char**) @@ -691,15 +720,9 @@ int main(int, char**) { if (game.zooming) { - if (game.zoomProgress > 0) - { - game.zoomProgress--; - } else if (game.zoomProgress < 0) - { - game.zoomProgress++; - } + game.zoomProgress++; - if (game.zoomProgress == 0) + if (game.zoomProgress == game.zoomLength) { game.zooming = false; } diff --git a/src/renderer.cpp b/src/renderer.cpp index eddd11d..9d3af97 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -288,22 +288,33 @@ void Renderer::render( SDL_SetRenderTarget(ren_.get(), nullptr); - if (!game.zooming) + SDL_Rect zoomRect; + + std::tie(zoomRect.x, zoomRect.y, zoomRect.w, zoomRect.h) = + calculateZoomRect(game); + + SDL_RenderCopy(ren_.get(), canvas.get(), &zoomRect, nullptr); + SDL_RenderPresent(ren_.get()); +} + +std::tuple Renderer::calculateZoomRect(const Game& game) +{ + int x = game.map.getTrueX(game.curBoundX) * TILE_WIDTH; + int y = game.map.getTrueY(game.curBoundY) * TILE_HEIGHT; + int w = game.curZoom * TILE_WIDTH * ZOOM_X_FACTOR; + int h = game.curZoom * TILE_HEIGHT * ZOOM_Y_FACTOR; + + if (game.zooming) { - SDL_RenderCopy(ren_.get(), canvas.get(), nullptr, nullptr); - } else { - // TODO: zooming back in to the player - SDL_Rect zoomRect { - ((game.maxZoom - game.curZoom) * TILE_WIDTH + game.zoomProgress) - * ZOOM_X_FACTOR / 2, - ((game.maxZoom - game.curZoom) * TILE_HEIGHT + game.zoomProgress) - * ZOOM_Y_FACTOR / 2, - (game.curZoom * TILE_WIDTH - game.zoomProgress) * ZOOM_X_FACTOR, - (game.curZoom * TILE_HEIGHT - game.zoomProgress) * ZOOM_Y_FACTOR - }; - - SDL_RenderCopy(ren_.get(), canvas.get(), &zoomRect, nullptr); + double interp = + static_cast(game.zoomProgress) / + static_cast(game.zoomLength); + + x = (x - game.lastZoomLeft) * interp + game.lastZoomLeft; + y = (y - game.lastZoomTop) * interp + game.lastZoomTop; + w = (w - game.lastZoomWidth) * interp + game.lastZoomWidth; + h = (h - game.lastZoomHeight) * interp + game.lastZoomHeight; } - SDL_RenderPresent(ren_.get()); + return {x, y, w, h}; } diff --git a/src/renderer.h b/src/renderer.h index 4aa27bb..a34b231 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -117,6 +117,8 @@ public: const Game& game, bool drawDark = true); + static std::tuple calculateZoomRect(const Game& game); + private: sdl_wrapper sdl_; -- cgit 1.4.1