diff options
| author | Star Rauchenberger <fefferburbia@gmail.com> | 2022-03-14 14:11:05 -0400 |
|---|---|---|
| committer | Star Rauchenberger <fefferburbia@gmail.com> | 2022-03-14 14:11:05 -0400 |
| commit | 7cd515fcfa1a5aac5605fcc63381033563fbf5d7 (patch) | |
| tree | 2a375db2fe6c1476a111c1f3e83e50fd2b68124e | |
| parent | 042da1570181dc80ee76860582f6a3c97641c14a (diff) | |
| download | ether-7cd515fcfa1a5aac5605fcc63381033563fbf5d7.tar.gz ether-7cd515fcfa1a5aac5605fcc63381033563fbf5d7.tar.bz2 ether-7cd515fcfa1a5aac5605fcc63381033563fbf5d7.zip | |
map is now "infinite" using chunks that dynamically load like in diamond&pearl
game is also slow as shit now
| -rw-r--r-- | src/consts.h | 4 | ||||
| -rw-r--r-- | src/game.cpp | 123 | ||||
| -rw-r--r-- | src/game.h | 40 | ||||
| -rw-r--r-- | src/main.cpp | 2 | ||||
| -rw-r--r-- | src/map.h | 184 | ||||
| -rw-r--r-- | src/renderer.cpp | 83 |
6 files changed, 256 insertions, 180 deletions
| diff --git a/src/consts.h b/src/consts.h index 141838b..78312c0 100644 --- a/src/consts.h +++ b/src/consts.h | |||
| @@ -5,9 +5,11 @@ constexpr int GAME_WIDTH = 1280;//640*2; | |||
| 5 | constexpr int GAME_HEIGHT = 720;//480*2; | 5 | constexpr int GAME_HEIGHT = 720;//480*2; |
| 6 | constexpr int TILE_WIDTH = 8*2; | 6 | constexpr int TILE_WIDTH = 8*2; |
| 7 | constexpr int TILE_HEIGHT = TILE_WIDTH; | 7 | constexpr int TILE_HEIGHT = TILE_WIDTH; |
| 8 | constexpr int INIT_ZOOM = 5; | 8 | constexpr int INIT_ZOOM = 2; |
| 9 | constexpr int ZOOM_X_FACTOR = 16; | 9 | constexpr int ZOOM_X_FACTOR = 16; |
| 10 | constexpr int ZOOM_Y_FACTOR = 9; | 10 | constexpr int ZOOM_Y_FACTOR = 9; |
| 11 | constexpr int CHUNK_WIDTH = 80; | ||
| 12 | constexpr int CHUNK_HEIGHT = 80; | ||
| 11 | constexpr int RADIUS = 8; | 13 | constexpr int RADIUS = 8; |
| 12 | constexpr int NUM_TITLES = 1; | 14 | constexpr int NUM_TITLES = 1; |
| 13 | 15 | ||
| diff --git a/src/game.cpp b/src/game.cpp index a7c94db..62e755b 100644 --- a/src/game.cpp +++ b/src/game.cpp | |||
| @@ -8,25 +8,11 @@ | |||
| 8 | 8 | ||
| 9 | Game::Game(std::mt19937& rng, Muxer& muxer) : | 9 | Game::Game(std::mt19937& rng, Muxer& muxer) : |
| 10 | rng(rng), | 10 | rng(rng), |
| 11 | muxer(muxer), | 11 | muxer(muxer) |
| 12 | map( | ||
| 13 | -INIT_ZOOM * ZOOM_X_FACTOR / 2, | ||
| 14 | -INIT_ZOOM * ZOOM_Y_FACTOR / 2, | ||
| 15 | INIT_ZOOM * ZOOM_X_FACTOR, | ||
| 16 | INIT_ZOOM * ZOOM_Y_FACTOR) | ||
| 17 | { | 12 | { |
| 18 | losePopLampTimer.accumulate(losePopLampTimer.getDt()); | 13 | losePopLampTimer.accumulate(losePopLampTimer.getDt()); |
| 19 | 14 | ||
| 20 | for (MapData& md : map.data()) | 15 | loadMap(); |
| 21 | { | ||
| 22 | if (std::bernoulli_distribution(0.5)(rng)) | ||
| 23 | { | ||
| 24 | md.tile = Tile::Wall; | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | tick(); | ||
| 29 | tick(); | ||
| 30 | 16 | ||
| 31 | for (int y = -1; y <= 1; y++) | 17 | for (int y = -1; y <= 1; y++) |
| 32 | { | 18 | { |
| @@ -39,12 +25,12 @@ Game::Game(std::mt19937& rng, Muxer& muxer) : | |||
| 39 | tick(); | 25 | tick(); |
| 40 | } | 26 | } |
| 41 | 27 | ||
| 42 | inline bool isTileSetOrNotLit(const Map<MapData>& map, int x, int y) | 28 | inline bool isTileSetOrNotLit(const Map& map, int x, int y) |
| 43 | { | 29 | { |
| 44 | return (map.inBounds(x, y) && (map.at(x,y).tile == Tile::Wall || !map.at(x,y).lit)); | 30 | return (map.inBounds(x, y) && (map.at(x,y).tile == Tile::Wall || !map.at(x,y).lit)); |
| 45 | } | 31 | } |
| 46 | 32 | ||
| 47 | inline bool isTileSet(const Map<MapData>& map, int x, int y, Tile val = Tile::Wall) | 33 | inline bool isTileSet(const Map& map, int x, int y, Tile val = Tile::Wall) |
| 48 | { | 34 | { |
| 49 | return (map.inBounds(x, y) && map.at(x,y).tile == val); | 35 | return (map.inBounds(x, y) && map.at(x,y).tile == val); |
| 50 | } | 36 | } |
| @@ -69,7 +55,7 @@ void Game::tick( | |||
| 69 | bool invert, | 55 | bool invert, |
| 70 | bool onlyDark) | 56 | bool onlyDark) |
| 71 | { | 57 | { |
| 72 | Map<MapData> temp(map); | 58 | std::vector<MapData> temp(map.data()); |
| 73 | 59 | ||
| 74 | for (int y = map.getTop(); y < map.getBottom(); y++) | 60 | for (int y = map.getTop(); y < map.getBottom(); y++) |
| 75 | { | 61 | { |
| @@ -102,21 +88,22 @@ void Game::tick( | |||
| 102 | incrementIfSet(*this, count, x+1, y ); | 88 | incrementIfSet(*this, count, x+1, y ); |
| 103 | incrementIfSet(*this, count, x+1, y+1); | 89 | incrementIfSet(*this, count, x+1, y+1); |
| 104 | 90 | ||
| 91 | int tempIndex = map.getTrueX(x) + map.getTrueY(y) * map.getWidth(); | ||
| 105 | if (count >= 5) | 92 | if (count >= 5) |
| 106 | { | 93 | { |
| 107 | temp.at(x,y).tile = Tile::Wall; | 94 | temp[tempIndex].tile = Tile::Wall; |
| 108 | } else { | 95 | } else { |
| 109 | temp.at(x,y).tile = Tile::Floor; | 96 | temp[tempIndex].tile = Tile::Floor; |
| 110 | } | 97 | } |
| 111 | 98 | ||
| 112 | if (temp.at(x,y).tile != map.at(x,y).tile) { | 99 | if (temp[tempIndex].tile != map.at(x,y).tile) { |
| 113 | temp.at(x,y).dirtyRender = true; | 100 | temp[tempIndex].dirtyRender = true; |
| 114 | dirtyRender = true; | 101 | dirtyRender = true; |
| 115 | } | 102 | } |
| 116 | } | 103 | } |
| 117 | } | 104 | } |
| 118 | 105 | ||
| 119 | map = std::move(temp); | 106 | map.data() = std::move(temp); |
| 120 | } | 107 | } |
| 121 | 108 | ||
| 122 | void Game::tick(bool onlyDark) | 109 | void Game::tick(bool onlyDark) |
| @@ -132,10 +119,10 @@ void Game::tick(bool onlyDark) | |||
| 132 | 119 | ||
| 133 | bool Game::movePlayer(int x, int y) | 120 | bool Game::movePlayer(int x, int y) |
| 134 | { | 121 | { |
| 135 | if (x >= curBoundX && | 122 | if (/*x >= curBoundX && |
| 136 | y >= curBoundY && | 123 | y >= curBoundY && |
| 137 | x < curBoundX + curZoom * ZOOM_X_FACTOR && | 124 | x < curBoundX + curZoom * ZOOM_X_FACTOR && |
| 138 | y < curBoundY + curZoom * ZOOM_Y_FACTOR && | 125 | y < curBoundY + curZoom * ZOOM_Y_FACTOR &&*/ |
| 139 | map.at(x,y).tile == Tile::Floor) | 126 | map.at(x,y).tile == Tile::Floor) |
| 140 | { | 127 | { |
| 141 | if (map.at(player_x, player_y).tile == Tile::Floor) | 128 | if (map.at(player_x, player_y).tile == Tile::Floor) |
| @@ -154,6 +141,13 @@ bool Game::movePlayer(int x, int y) | |||
| 154 | moveProgress.start(66); | 141 | moveProgress.start(66); |
| 155 | dirtyLighting = true; | 142 | dirtyLighting = true; |
| 156 | 143 | ||
| 144 | int chunkX, chunkY, old_chunkX, old_chunkY; | ||
| 145 | toChunkPos(player_x, player_y, chunkX, chunkY); | ||
| 146 | toChunkPos(player_oldx, player_oldy, old_chunkX, old_chunkY); | ||
| 147 | if ((chunkX != old_chunkX) || (chunkY != old_chunkY)) { | ||
| 148 | loadMap(); | ||
| 149 | } | ||
| 150 | |||
| 157 | return true; | 151 | return true; |
| 158 | } else { | 152 | } else { |
| 159 | if (!alreadyBumped) { | 153 | if (!alreadyBumped) { |
| @@ -501,39 +495,25 @@ void Game::processKickup() | |||
| 501 | }); | 495 | }); |
| 502 | } | 496 | } |
| 503 | 497 | ||
| 504 | void Game::growMap(size_t zoom) | 498 | void Game::loadMap() { |
| 505 | { | 499 | int newChunksHoriz = std::ceil(static_cast<double>(curZoom) * ZOOM_X_FACTOR / CHUNK_WIDTH) + 4; |
| 506 | int ol = map.getLeft(); | 500 | int newChunksVert = std::ceil(static_cast<double>(curZoom) * ZOOM_Y_FACTOR / CHUNK_HEIGHT) + 4; |
| 507 | int ot = map.getTop(); | 501 | int curPlayerChunkX, curPlayerChunkY; |
| 508 | int ow = map.getWidth(); | 502 | toChunkPos(player_x, player_y, curPlayerChunkX, curPlayerChunkY); |
| 509 | int oh = map.getHeight(); | ||
| 510 | 503 | ||
| 511 | map.resize( | 504 | map.load( |
| 512 | -zoom * ZOOM_X_FACTOR / 2, | 505 | curPlayerChunkX - newChunksHoriz / 2, |
| 513 | -zoom * ZOOM_Y_FACTOR / 2, | 506 | curPlayerChunkY - newChunksVert / 2, |
| 514 | zoom * ZOOM_X_FACTOR, | 507 | newChunksHoriz, |
| 515 | zoom * ZOOM_Y_FACTOR); | 508 | newChunksVert, |
| 509 | rng); | ||
| 516 | 510 | ||
| 517 | maxZoom = zoom; | 511 | tick(); |
| 518 | 512 | tick(); | |
| 519 | for (int y = map.getTop(); y < map.getBottom(); y++) | 513 | tick(); |
| 520 | { | ||
| 521 | for (int x = map.getLeft(); x < map.getRight(); x++) | ||
| 522 | { | ||
| 523 | if (!(x >= ol && x < (ol + ow) && y >= ot && y < (ot + oh))) | ||
| 524 | { | ||
| 525 | if (std::bernoulli_distribution(0.5)(rng)) | ||
| 526 | { | ||
| 527 | map.at(x,y).tile = Tile::Wall; | ||
| 528 | } | ||
| 529 | } | ||
| 530 | } | ||
| 531 | } | ||
| 532 | 514 | ||
| 533 | for (int i = 0; i < 3; i++) | 515 | dirtyLighting = true; |
| 534 | { | 516 | dirtyRender = true; |
| 535 | tick(ol, ot, ol + ow, ot + oh, true); | ||
| 536 | } | ||
| 537 | } | 517 | } |
| 538 | 518 | ||
| 539 | void Game::setZoom(size_t zoom) | 519 | void Game::setZoom(size_t zoom) |
| @@ -543,40 +523,11 @@ void Game::setZoom(size_t zoom) | |||
| 543 | return; | 523 | return; |
| 544 | } | 524 | } |
| 545 | 525 | ||
| 546 | if (zoom > maxZoom) | ||
| 547 | { | ||
| 548 | growMap(zoom); | ||
| 549 | } | ||
| 550 | |||
| 551 | std::tie( | ||
| 552 | lastZoomLeft, | ||
| 553 | lastZoomTop, | ||
| 554 | lastZoomWidth, | ||
| 555 | lastZoomHeight) = | ||
| 556 | Renderer::calculateZoomRect(*this); | ||
| 557 | |||
| 558 | zoomProgress = 0; | 526 | zoomProgress = 0; |
| 559 | zoomLength = std::abs(static_cast<long>(zoom - curZoom)) * TILE_WIDTH; | 527 | zoomLength = std::abs(static_cast<long>(zoom - curZoom)) * TILE_WIDTH; |
| 560 | curZoom = zoom; | 528 | curZoom = zoom; |
| 561 | zooming = true; | 529 | zooming = true; |
| 562 | 530 | loadMap(); | |
| 563 | curBoundX = player_x - zoom * ZOOM_X_FACTOR / 2; | ||
| 564 | if (curBoundX < map.getLeft()) | ||
| 565 | { | ||
| 566 | curBoundX = map.getLeft(); | ||
| 567 | } else if (curBoundX + zoom * ZOOM_X_FACTOR >= map.getRight()) | ||
| 568 | { | ||
| 569 | curBoundX = map.getRight() - zoom * ZOOM_X_FACTOR; | ||
| 570 | } | ||
| 571 | |||
| 572 | curBoundY = player_y - zoom * ZOOM_Y_FACTOR / 2; | ||
| 573 | if (curBoundY < map.getTop()) | ||
| 574 | { | ||
| 575 | curBoundY = map.getTop(); | ||
| 576 | } else if (curBoundY + zoom * ZOOM_Y_FACTOR >= map.getBottom()) | ||
| 577 | { | ||
| 578 | curBoundY = map.getBottom() - zoom * ZOOM_Y_FACTOR; | ||
| 579 | } | ||
| 580 | 531 | ||
| 581 | int zoomLevel = getZoomLevel(*this); | 532 | int zoomLevel = getZoomLevel(*this); |
| 582 | if (zoomLevel == 0) { | 533 | if (zoomLevel == 0) { |
| diff --git a/src/game.h b/src/game.h index 446680a..40ace3d 100644 --- a/src/game.h +++ b/src/game.h | |||
| @@ -16,20 +16,6 @@ constexpr int TilesetIndex(int x, int y) { | |||
| 16 | return x + y * 24; | 16 | return x + y * 24; |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | enum class Tile { | ||
| 20 | Floor, | ||
| 21 | Wall, | ||
| 22 | Dust, | ||
| 23 | Lamp | ||
| 24 | }; | ||
| 25 | |||
| 26 | enum class Source { | ||
| 27 | None, | ||
| 28 | Dust, | ||
| 29 | Lamp, | ||
| 30 | Player | ||
| 31 | }; | ||
| 32 | |||
| 33 | enum class LoseState { | 19 | enum class LoseState { |
| 34 | None, | 20 | None, |
| 35 | PoppingLamps, | 21 | PoppingLamps, |
| @@ -52,8 +38,6 @@ struct Input { | |||
| 52 | } | 38 | } |
| 53 | }; | 39 | }; |
| 54 | 40 | ||
| 55 | using coord = std::tuple<int, int>; | ||
| 56 | |||
| 57 | struct Kickup { | 41 | struct Kickup { |
| 58 | int x; | 42 | int x; |
| 59 | int y; | 43 | int y; |
| @@ -64,18 +48,6 @@ struct Kickup { | |||
| 64 | std::set<coord> front; | 48 | std::set<coord> front; |
| 65 | }; | 49 | }; |
| 66 | 50 | ||
| 67 | struct MapData { | ||
| 68 | Tile tile = Tile::Floor; | ||
| 69 | bool lit = false; | ||
| 70 | bool wasLit = false; | ||
| 71 | size_t dustLife = 0; | ||
| 72 | Source lightType = Source::None; | ||
| 73 | int lightRadius = 0; | ||
| 74 | std::set<coord> litTiles; | ||
| 75 | int renderId = -1; | ||
| 76 | bool dirtyRender = true; | ||
| 77 | }; | ||
| 78 | |||
| 79 | class Game { | 51 | class Game { |
| 80 | public: | 52 | public: |
| 81 | 53 | ||
| @@ -89,7 +61,7 @@ public: | |||
| 89 | bool quit = false; | 61 | bool quit = false; |
| 90 | LoseState losing = LoseState::None; | 62 | LoseState losing = LoseState::None; |
| 91 | 63 | ||
| 92 | Map<MapData> map; | 64 | Map map; |
| 93 | std::list<Kickup> kickups; | 65 | std::list<Kickup> kickups; |
| 94 | int litSpots = 0; | 66 | int litSpots = 0; |
| 95 | bool dirtyLighting = true; | 67 | bool dirtyLighting = true; |
| @@ -105,18 +77,10 @@ public: | |||
| 105 | Animation playerAnim {"../res/player_anim.txt"}; | 77 | Animation playerAnim {"../res/player_anim.txt"}; |
| 106 | 78 | ||
| 107 | int maxZoom = INIT_ZOOM; | 79 | int maxZoom = INIT_ZOOM; |
| 108 | |||
| 109 | int curZoom = INIT_ZOOM; | 80 | int curZoom = INIT_ZOOM; |
| 110 | int curBoundX = map.getLeft(); | ||
| 111 | int curBoundY = map.getTop(); | ||
| 112 | |||
| 113 | bool zooming = false; | 81 | bool zooming = false; |
| 114 | int zoomProgress = 0; | 82 | int zoomProgress = 0; |
| 115 | int zoomLength; | 83 | int zoomLength; |
| 116 | int lastZoomTop; | ||
| 117 | int lastZoomLeft; | ||
| 118 | int lastZoomWidth; | ||
| 119 | int lastZoomHeight; | ||
| 120 | 84 | ||
| 121 | Input keystate; | 85 | Input keystate; |
| 122 | bool firstInput = false; | 86 | bool firstInput = false; |
| @@ -159,7 +123,7 @@ private: | |||
| 159 | 123 | ||
| 160 | void processKickup(); | 124 | void processKickup(); |
| 161 | 125 | ||
| 162 | void growMap(size_t zoom); | 126 | void loadMap(); |
| 163 | 127 | ||
| 164 | void setZoom(size_t zoom); | 128 | void setZoom(size_t zoom); |
| 165 | 129 | ||
| diff --git a/src/main.cpp b/src/main.cpp index 4ae11d6..0d14986 100644 --- a/src/main.cpp +++ b/src/main.cpp | |||
| @@ -23,7 +23,7 @@ int main(int, char**) | |||
| 23 | 23 | ||
| 24 | Game game(rng, muxer); | 24 | Game game(rng, muxer); |
| 25 | 25 | ||
| 26 | constexpr int titleFadeLen = 3000; | 26 | constexpr int titleFadeLen = 2000; |
| 27 | bool doneTitles = false; | 27 | bool doneTitles = false; |
| 28 | int titleNum = 0; | 28 | int titleNum = 0; |
| 29 | TitleState titleState = TitleState::FadeIn; | 29 | TitleState titleState = TitleState::FadeIn; |
| diff --git a/src/map.h b/src/map.h index 329553c..d28b8d4 100644 --- a/src/map.h +++ b/src/map.h | |||
| @@ -3,23 +3,62 @@ | |||
| 3 | 3 | ||
| 4 | #include <vector> | 4 | #include <vector> |
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <array> | ||
| 7 | #include <list> | ||
| 8 | #include <map> | ||
| 9 | #include <random> | ||
| 10 | #include "consts.h" | ||
| 6 | 11 | ||
| 7 | template <typename T> | 12 | using coord = std::tuple<int, int>; |
| 8 | class Map { | ||
| 9 | public: | ||
| 10 | 13 | ||
| 11 | Map( | 14 | enum class Tile { |
| 12 | int left, | 15 | Floor, |
| 13 | int top, | 16 | Wall, |
| 14 | int width, | 17 | Dust, |
| 15 | int height) : | 18 | Lamp |
| 16 | left_(left), | 19 | }; |
| 17 | top_(top), | 20 | |
| 18 | width_(width), | 21 | enum class Source { |
| 19 | height_(height), | 22 | None, |
| 20 | data_(width_*height_) | 23 | Dust, |
| 21 | { | 24 | Lamp, |
| 25 | Player | ||
| 26 | }; | ||
| 27 | |||
| 28 | struct MapData { | ||
| 29 | Tile tile = Tile::Floor; | ||
| 30 | bool lit = false; | ||
| 31 | bool wasLit = false; | ||
| 32 | size_t dustLife = 0; | ||
| 33 | Source lightType = Source::None; | ||
| 34 | int lightRadius = 0; | ||
| 35 | std::set<coord> litTiles; | ||
| 36 | int renderId = -1; | ||
| 37 | bool dirtyRender = true; | ||
| 38 | }; | ||
| 39 | |||
| 40 | struct Chunk { | ||
| 41 | std::array<MapData, CHUNK_WIDTH*CHUNK_HEIGHT> data; | ||
| 42 | int litTiles = 0; | ||
| 43 | int x; | ||
| 44 | int y; | ||
| 45 | }; | ||
| 46 | |||
| 47 | inline void toChunkPos(int x, int y, int& cx, int& cy) { | ||
| 48 | cx = x / CHUNK_WIDTH; | ||
| 49 | cy = y / CHUNK_HEIGHT; | ||
| 50 | if (x < 0) { | ||
| 51 | cx *= -1; | ||
| 52 | cx--; | ||
| 53 | } | ||
| 54 | if (y < 0) { | ||
| 55 | cy *= -1; | ||
| 56 | cy--; | ||
| 22 | } | 57 | } |
| 58 | } | ||
| 59 | |||
| 60 | class Map { | ||
| 61 | public: | ||
| 23 | 62 | ||
| 24 | inline int getLeft() const | 63 | inline int getLeft() const |
| 25 | { | 64 | { |
| @@ -69,27 +108,27 @@ public: | |||
| 69 | (y < top_ + height_); | 108 | (y < top_ + height_); |
| 70 | } | 109 | } |
| 71 | 110 | ||
| 72 | inline const T& at(int x, int y) const | 111 | inline const MapData& at(int x, int y) const |
| 73 | { | 112 | { |
| 74 | return data_.at((x - left_) + width_ * (y - top_)); | 113 | return loaded_.at((x - left_) + width_ * (y - top_)); |
| 75 | } | 114 | } |
| 76 | 115 | ||
| 77 | inline T& at(int x, int y) | 116 | inline MapData& at(int x, int y) |
| 78 | { | 117 | { |
| 79 | return const_cast<T&>(static_cast<const Map&>(*this).at(x, y)); | 118 | return const_cast<MapData&>(static_cast<const Map&>(*this).at(x, y)); |
| 80 | } | 119 | } |
| 81 | 120 | ||
| 82 | inline const std::vector<T>& data() const | 121 | inline const std::vector<MapData>& data() const |
| 83 | { | 122 | { |
| 84 | return data_; | 123 | return loaded_; |
| 85 | } | 124 | } |
| 86 | 125 | ||
| 87 | inline std::vector<T>& data() | 126 | inline std::vector<MapData>& data() |
| 88 | { | 127 | { |
| 89 | return data_; | 128 | return loaded_; |
| 90 | } | 129 | } |
| 91 | 130 | ||
| 92 | void resize(int newLeft, int newTop, int newWidth, int newHeight) | 131 | /*void resize(int newLeft, int newTop, int newWidth, int newHeight) |
| 93 | { | 132 | { |
| 94 | std::vector<T> newData(newWidth * newHeight); | 133 | std::vector<T> newData(newWidth * newHeight); |
| 95 | 134 | ||
| @@ -112,6 +151,96 @@ public: | |||
| 112 | width_ = newWidth; | 151 | width_ = newWidth; |
| 113 | height_ = newHeight; | 152 | height_ = newHeight; |
| 114 | data_.swap(newData); | 153 | data_.swap(newData); |
| 154 | }*/ | ||
| 155 | |||
| 156 | void load(int newLeftChunk, int newTopChunk, int newWidthChunks, int newHeightChunks, std::mt19937& rng) { | ||
| 157 | // Flush the currently loaded data as long as there is any (this isn't the first load). | ||
| 158 | if (!loaded_.empty()) { | ||
| 159 | std::vector<size_t> touchedChunks; | ||
| 160 | |||
| 161 | for (int chunkY = 0; chunkY < chunksVert_; chunkY++) { | ||
| 162 | for (int chunkX = 0; chunkX < chunksHoriz_; chunkX++) { | ||
| 163 | size_t chunkIndex = chunkByPos_.at(leftmostChunk_ + chunkX).at(topmostChunk_ + chunkY); | ||
| 164 | touchedChunks.push_back(chunkIndex); | ||
| 165 | |||
| 166 | Chunk& chunk = chunks_.at(chunkIndex); | ||
| 167 | chunk.litTiles = 0; | ||
| 168 | |||
| 169 | int startX = chunkX * CHUNK_WIDTH; | ||
| 170 | int startY = chunkY * CHUNK_HEIGHT; | ||
| 171 | for (int y=0; y<CHUNK_HEIGHT; y++) { | ||
| 172 | for (int x=0; x<CHUNK_WIDTH; x++) { | ||
| 173 | chunk.data[x+y*CHUNK_WIDTH] = loaded_[startX+x+(startY+y)*width_]; | ||
| 174 | if (chunk.data[x+y*CHUNK_WIDTH].lit) { | ||
| 175 | chunk.litTiles++; | ||
| 176 | } | ||
| 177 | } | ||
| 178 | } | ||
| 179 | } | ||
| 180 | } | ||
| 181 | |||
| 182 | // Destroy any completely unlit chunks. | ||
| 183 | for (size_t chunkIndex : touchedChunks) { | ||
| 184 | if (chunks_[chunkIndex].litTiles == 0) { | ||
| 185 | chunkByPos_[chunks_[chunkIndex].x].erase(chunks_[chunkIndex].y); | ||
| 186 | freeList_.push_back(chunkIndex); | ||
| 187 | } | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
| 191 | leftmostChunk_ = newLeftChunk; | ||
| 192 | topmostChunk_ = newTopChunk; | ||
| 193 | chunksHoriz_ = newWidthChunks; | ||
| 194 | chunksVert_ = newHeightChunks; | ||
| 195 | left_ = newLeftChunk * CHUNK_WIDTH; | ||
| 196 | top_ = newTopChunk * CHUNK_HEIGHT; | ||
| 197 | width_ = chunksHoriz_ * CHUNK_WIDTH; | ||
| 198 | height_ = chunksVert_ * CHUNK_HEIGHT; | ||
| 199 | loaded_ = std::vector<MapData>(width_ * height_); | ||
| 200 | |||
| 201 | // Load in the requested chunks. | ||
| 202 | for (int chunkY = 0; chunkY < chunksVert_; chunkY++) { | ||
| 203 | for (int chunkX = 0; chunkX < chunksHoriz_; chunkX++) { | ||
| 204 | // Instantiate a new chunk if necessary. | ||
| 205 | if (!chunkByPos_[leftmostChunk_ + chunkX].count(topmostChunk_ + chunkY)) { | ||
| 206 | size_t chunkIndex; | ||
| 207 | if (!freeList_.empty()) { | ||
| 208 | chunkIndex = freeList_.front(); | ||
| 209 | freeList_.pop_front(); | ||
| 210 | } else { | ||
| 211 | chunkIndex = chunks_.size(); | ||
| 212 | chunks_.emplace_back(); | ||
| 213 | } | ||
| 214 | chunkByPos_[leftmostChunk_ + chunkX][topmostChunk_ + chunkY] = chunkIndex; | ||
| 215 | |||
| 216 | Chunk& chunk = chunks_[chunkIndex]; | ||
| 217 | chunk.x = leftmostChunk_ + chunkX; | ||
| 218 | chunk.y = topmostChunk_ + chunkY; | ||
| 219 | |||
| 220 | for (MapData& md : chunk.data) | ||
| 221 | { | ||
| 222 | if (std::bernoulli_distribution(0.5)(rng)) | ||
| 223 | { | ||
| 224 | md.tile = Tile::Wall; | ||
| 225 | } else { | ||
| 226 | md.tile = Tile::Floor; | ||
| 227 | } | ||
| 228 | md.dirtyRender = true; | ||
| 229 | } | ||
| 230 | } | ||
| 231 | |||
| 232 | size_t chunkIndex = chunkByPos_[leftmostChunk_ + chunkX][topmostChunk_ + chunkY]; | ||
| 233 | Chunk& chunk = chunks_[chunkIndex]; | ||
| 234 | |||
| 235 | for (int y = 0; y < CHUNK_HEIGHT; y++) { | ||
| 236 | std::copy( | ||
| 237 | std::next(std::begin(chunk.data), y*CHUNK_WIDTH), | ||
| 238 | std::next(std::begin(chunk.data), (y+1)*CHUNK_WIDTH), | ||
| 239 | std::next(std::begin(loaded_), (chunkY*CHUNK_HEIGHT + y)*width_ + chunkX*CHUNK_WIDTH)); | ||
| 240 | } | ||
| 241 | } | ||
| 242 | } | ||
| 243 | |||
| 115 | } | 244 | } |
| 116 | 245 | ||
| 117 | private: | 246 | private: |
| @@ -120,8 +249,15 @@ private: | |||
| 120 | int top_; | 249 | int top_; |
| 121 | int width_; | 250 | int width_; |
| 122 | int height_; | 251 | int height_; |
| 252 | int leftmostChunk_; | ||
| 253 | int topmostChunk_; | ||
| 254 | int chunksHoriz_; | ||
| 255 | int chunksVert_; | ||
| 256 | std::vector<MapData> loaded_; | ||
| 123 | 257 | ||
| 124 | std::vector<T> data_; | 258 | std::vector<Chunk> chunks_; |
| 259 | std::list<size_t> freeList_; | ||
| 260 | std::map<int, std::map<int, size_t>> chunkByPos_; // chunkByPos_[X][Y] | ||
| 125 | }; | 261 | }; |
| 126 | 262 | ||
| 127 | #endif /* end of include guard: MAP_H_3AB00D12 */ | 263 | #endif /* end of include guard: MAP_H_3AB00D12 */ |
| diff --git a/src/renderer.cpp b/src/renderer.cpp index 9ef8bb9..1f51e0a 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp | |||
| @@ -12,7 +12,7 @@ Renderer::Renderer() | |||
| 12 | GAME_HEIGHT, | 12 | GAME_HEIGHT, |
| 13 | SDL_WINDOW_SHOWN)); | 13 | SDL_WINDOW_SHOWN)); |
| 14 | 14 | ||
| 15 | SDL_SetWindowFullscreen(win_.get(), SDL_WINDOW_FULLSCREEN_DESKTOP); | 15 | //SDL_SetWindowFullscreen(win_.get(), SDL_WINDOW_FULLSCREEN_DESKTOP); |
| 16 | 16 | ||
| 17 | if (!win_) | 17 | if (!win_) |
| 18 | { | 18 | { |
| @@ -115,13 +115,16 @@ void Renderer::renderGame( | |||
| 115 | const Game& game, | 115 | const Game& game, |
| 116 | bool drawDark) | 116 | bool drawDark) |
| 117 | { | 117 | { |
| 118 | int windowTileWidth = game.curZoom * ZOOM_X_FACTOR + 2; | ||
| 119 | int windowTileHeight = game.curZoom * ZOOM_Y_FACTOR + 2; | ||
| 120 | |||
| 118 | texture_ptr canvas( | 121 | texture_ptr canvas( |
| 119 | SDL_CreateTexture( | 122 | SDL_CreateTexture( |
| 120 | ren_.get(), | 123 | ren_.get(), |
| 121 | SDL_PIXELFORMAT_RGBA8888, | 124 | SDL_PIXELFORMAT_RGBA8888, |
| 122 | SDL_TEXTUREACCESS_TARGET, | 125 | SDL_TEXTUREACCESS_TARGET, |
| 123 | TILE_WIDTH * game.map.getWidth(), | 126 | windowTileWidth * TILE_WIDTH, |
| 124 | TILE_HEIGHT * game.map.getHeight())); | 127 | windowTileHeight * TILE_HEIGHT)); |
| 125 | 128 | ||
| 126 | if (!canvas) | 129 | if (!canvas) |
| 127 | { | 130 | { |
| @@ -133,15 +136,17 @@ void Renderer::renderGame( | |||
| 133 | SDL_SetRenderDrawColor(ren_.get(), rand() % 255, rand() % 255, rand() % 255, 255); | 136 | SDL_SetRenderDrawColor(ren_.get(), rand() % 255, rand() % 255, rand() % 255, 255); |
| 134 | SDL_RenderClear(ren_.get()); | 137 | SDL_RenderClear(ren_.get()); |
| 135 | 138 | ||
| 136 | for (int y = game.map.getTop(); y < game.map.getBottom(); y++) | 139 | int leftmost = game.player_x - game.curZoom * ZOOM_X_FACTOR / 2 - 1; |
| 140 | int topmost = game.player_y - game.curZoom * ZOOM_Y_FACTOR / 2 - 1; | ||
| 141 | for (int y = topmost; y < topmost + windowTileHeight; y++) | ||
| 137 | { | 142 | { |
| 138 | for (int x = game.map.getLeft(); x < game.map.getRight(); x++) | 143 | for (int x = leftmost; x < leftmost + windowTileWidth; x++) |
| 139 | { | 144 | { |
| 140 | bool draw = true; | 145 | bool draw = true; |
| 141 | bool drawColour = false; | 146 | bool drawColour = false; |
| 142 | SDL_Rect rect { | 147 | SDL_Rect rect { |
| 143 | game.map.getTrueX(x) * TILE_WIDTH, | 148 | (x - leftmost) * TILE_WIDTH, |
| 144 | game.map.getTrueY(y) * TILE_HEIGHT, | 149 | (y - topmost) * TILE_HEIGHT, |
| 145 | TILE_WIDTH, | 150 | TILE_WIDTH, |
| 146 | TILE_HEIGHT}; | 151 | TILE_HEIGHT}; |
| 147 | 152 | ||
| @@ -190,14 +195,14 @@ void Renderer::renderGame( | |||
| 190 | 195 | ||
| 191 | if (game.renderPlayer) { | 196 | if (game.renderPlayer) { |
| 192 | SDL_Rect rect { | 197 | SDL_Rect rect { |
| 193 | game.map.getTrueX(game.player_x) * TILE_WIDTH, | 198 | (game.player_x - leftmost) * TILE_WIDTH, |
| 194 | game.map.getTrueY(game.player_y) * TILE_HEIGHT, | 199 | (game.player_y - topmost) * TILE_HEIGHT, |
| 195 | TILE_WIDTH, | 200 | TILE_WIDTH, |
| 196 | TILE_HEIGHT}; | 201 | TILE_HEIGHT}; |
| 197 | 202 | ||
| 198 | if (game.moving) { | 203 | if (game.moving) { |
| 199 | rect.x = game.moveProgress.getProgress(game.map.getTrueX(game.player_oldx) * TILE_WIDTH, rect.x); | 204 | rect.x = game.moveProgress.getProgress((game.player_oldx - leftmost) * TILE_WIDTH, rect.x); |
| 200 | rect.y = game.moveProgress.getProgress(game.map.getTrueY(game.player_oldy) * TILE_HEIGHT, rect.y); | 205 | rect.y = game.moveProgress.getProgress((game.player_oldy - topmost) * TILE_HEIGHT, rect.y); |
| 201 | } | 206 | } |
| 202 | 207 | ||
| 203 | SDL_RenderCopy(ren_.get(), playerSheet_.get(), &game.playerAnim.getRenderRect(), &rect); | 208 | SDL_RenderCopy(ren_.get(), playerSheet_.get(), &game.playerAnim.getRenderRect(), &rect); |
| @@ -208,8 +213,8 @@ void Renderer::renderGame( | |||
| 208 | ren_.get(), | 213 | ren_.get(), |
| 209 | SDL_PIXELFORMAT_RGBA8888, | 214 | SDL_PIXELFORMAT_RGBA8888, |
| 210 | SDL_TEXTUREACCESS_TARGET, | 215 | SDL_TEXTUREACCESS_TARGET, |
| 211 | TILE_WIDTH * game.map.getWidth(), | 216 | windowTileWidth * TILE_WIDTH, |
| 212 | TILE_HEIGHT * game.map.getHeight())); | 217 | windowTileHeight * TILE_HEIGHT)); |
| 213 | 218 | ||
| 214 | if (!mask) | 219 | if (!mask) |
| 215 | { | 220 | { |
| @@ -220,9 +225,9 @@ void Renderer::renderGame( | |||
| 220 | SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, 0); | 225 | SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, 0); |
| 221 | SDL_RenderClear(ren_.get()); | 226 | SDL_RenderClear(ren_.get()); |
| 222 | 227 | ||
| 223 | for (int y = game.map.getTop(); y < game.map.getBottom(); y++) | 228 | for (int y = topmost; y < topmost + windowTileHeight; y++) |
| 224 | { | 229 | { |
| 225 | for (int x = game.map.getLeft(); x < game.map.getRight(); x++) | 230 | for (int x = leftmost; x < leftmost + windowTileWidth; x++) |
| 226 | { | 231 | { |
| 227 | if (game.map.at(x,y).lightType != Source::None) | 232 | if (game.map.at(x,y).lightType != Source::None) |
| 228 | { | 233 | { |
| @@ -231,8 +236,8 @@ void Renderer::renderGame( | |||
| 231 | ren_.get(), | 236 | ren_.get(), |
| 232 | SDL_PIXELFORMAT_RGBA8888, | 237 | SDL_PIXELFORMAT_RGBA8888, |
| 233 | SDL_TEXTUREACCESS_TARGET, | 238 | SDL_TEXTUREACCESS_TARGET, |
| 234 | TILE_WIDTH * game.map.getWidth(), | 239 | windowTileWidth * TILE_WIDTH, |
| 235 | TILE_HEIGHT * game.map.getHeight())); | 240 | windowTileHeight * TILE_HEIGHT)); |
| 236 | 241 | ||
| 237 | if (!sourceMask) | 242 | if (!sourceMask) |
| 238 | { | 243 | { |
| @@ -244,11 +249,11 @@ void Renderer::renderGame( | |||
| 244 | SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, 0); | 249 | SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, 0); |
| 245 | SDL_RenderClear(ren_.get()); | 250 | SDL_RenderClear(ren_.get()); |
| 246 | 251 | ||
| 247 | int posToUseX = game.map.getTrueX(x); | 252 | int posToUseX = x - leftmost; |
| 248 | int posToUseY = game.map.getTrueY(y); | 253 | int posToUseY = y - topmost; |
| 249 | if (game.map.at(x,y).lightType == Source::Player && game.moving) { | 254 | if (game.map.at(x,y).lightType == Source::Player && game.moving) { |
| 250 | posToUseX = game.moveProgress.getProgress(game.map.getTrueX(game.player_oldx), posToUseX); | 255 | posToUseX = game.moveProgress.getProgress((game.player_oldx) - leftmost, posToUseX); |
| 251 | posToUseY = game.moveProgress.getProgress(game.map.getTrueY(game.player_oldy), posToUseY); | 256 | posToUseY = game.moveProgress.getProgress((game.player_oldy) - topmost, posToUseY); |
| 252 | } | 257 | } |
| 253 | 258 | ||
| 254 | int fadeX = posToUseX - game.map.at(x,y).lightRadius; | 259 | int fadeX = posToUseX - game.map.at(x,y).lightRadius; |
| @@ -283,8 +288,8 @@ void Renderer::renderGame( | |||
| 283 | if (!game.map.at(x,y).litTiles.count({sx, sy})) | 288 | if (!game.map.at(x,y).litTiles.count({sx, sy})) |
| 284 | { | 289 | { |
| 285 | SDL_Rect rect { | 290 | SDL_Rect rect { |
| 286 | game.map.getTrueX(sx) * TILE_WIDTH, | 291 | (sx - leftmost) * TILE_WIDTH, |
| 287 | game.map.getTrueY(sy) * TILE_HEIGHT, | 292 | (sy - topmost) * TILE_HEIGHT, |
| 288 | TILE_WIDTH, | 293 | TILE_WIDTH, |
| 289 | TILE_HEIGHT}; | 294 | TILE_HEIGHT}; |
| 290 | 295 | ||
| @@ -306,10 +311,28 @@ void Renderer::renderGame( | |||
| 306 | 311 | ||
| 307 | SDL_SetRenderTarget(ren_.get(), nullptr); | 312 | SDL_SetRenderTarget(ren_.get(), nullptr); |
| 308 | 313 | ||
| 309 | SDL_Rect zoomRect; | 314 | // TODO: this is just moving interp. we also need zoom |
| 315 | SDL_Rect zoomRect { | ||
| 316 | TILE_WIDTH, TILE_HEIGHT, (windowTileWidth - 2) * TILE_WIDTH, (windowTileHeight - 2) * TILE_HEIGHT | ||
| 317 | }; | ||
| 318 | |||
| 319 | if (game.moving) { | ||
| 320 | double interp = | ||
| 321 | static_cast<double>(game.zoomProgress) / | ||
| 322 | static_cast<double>(game.zoomLength); | ||
| 323 | |||
| 324 | if (game.player_x > game.player_oldx) { | ||
| 325 | zoomRect.x = game.moveProgress.getProgress(0, TILE_WIDTH); | ||
| 326 | } else if (game.player_x < game.player_oldx) { | ||
| 327 | zoomRect.x = game.moveProgress.getProgress(2*TILE_WIDTH, TILE_WIDTH); | ||
| 328 | } | ||
| 310 | 329 | ||
| 311 | std::tie(zoomRect.x, zoomRect.y, zoomRect.w, zoomRect.h) = | 330 | if (game.player_y > game.player_oldy) { |
| 312 | calculateZoomRect(game); | 331 | zoomRect.y = game.moveProgress.getProgress(0, TILE_HEIGHT); |
| 332 | } else if (game.player_y < game.player_oldy) { | ||
| 333 | zoomRect.y = game.moveProgress.getProgress(TILE_HEIGHT*2, TILE_HEIGHT); | ||
| 334 | } | ||
| 335 | } | ||
| 313 | 336 | ||
| 314 | SDL_RenderCopy(ren_.get(), canvas.get(), &zoomRect, nullptr); | 337 | SDL_RenderCopy(ren_.get(), canvas.get(), &zoomRect, nullptr); |
| 315 | SDL_RenderPresent(ren_.get()); | 338 | SDL_RenderPresent(ren_.get()); |
| @@ -358,12 +381,12 @@ void Renderer::renderTitle(int num, double fade) { | |||
| 358 | 381 | ||
| 359 | std::tuple<int, int, int, int> Renderer::calculateZoomRect(const Game& game) | 382 | std::tuple<int, int, int, int> Renderer::calculateZoomRect(const Game& game) |
| 360 | { | 383 | { |
| 361 | int x = game.map.getTrueX(game.curBoundX) * TILE_WIDTH; | ||
| 362 | int y = game.map.getTrueY(game.curBoundY) * TILE_HEIGHT; | ||
| 363 | int w = game.curZoom * TILE_WIDTH * ZOOM_X_FACTOR; | 384 | int w = game.curZoom * TILE_WIDTH * ZOOM_X_FACTOR; |
| 364 | int h = game.curZoom * TILE_HEIGHT * ZOOM_Y_FACTOR; | 385 | int h = game.curZoom * TILE_HEIGHT * ZOOM_Y_FACTOR; |
| 386 | int x = (game.map.getTrueX(game.player_x) * TILE_WIDTH) - (w / 2); | ||
| 387 | int y = (game.map.getTrueY(game.player_y) * TILE_HEIGHT) - (h / 2); | ||
| 365 | 388 | ||
| 366 | if (game.zooming) | 389 | /*if (game.zooming) |
| 367 | { | 390 | { |
| 368 | double interp = | 391 | double interp = |
| 369 | static_cast<double>(game.zoomProgress) / | 392 | static_cast<double>(game.zoomProgress) / |
| @@ -373,7 +396,7 @@ std::tuple<int, int, int, int> Renderer::calculateZoomRect(const Game& game) | |||
| 373 | y = (y - game.lastZoomTop) * interp + game.lastZoomTop; | 396 | y = (y - game.lastZoomTop) * interp + game.lastZoomTop; |
| 374 | w = (w - game.lastZoomWidth) * interp + game.lastZoomWidth; | 397 | w = (w - game.lastZoomWidth) * interp + game.lastZoomWidth; |
| 375 | h = (h - game.lastZoomHeight) * interp + game.lastZoomHeight; | 398 | h = (h - game.lastZoomHeight) * interp + game.lastZoomHeight; |
| 376 | } | 399 | }*/ |
| 377 | 400 | ||
| 378 | return {x, y, w, h}; | 401 | return {x, y, w, h}; |
| 379 | } | 402 | } |
