diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/game.cpp | 195 | ||||
| -rw-r--r-- | src/game.h | 4 | ||||
| -rw-r--r-- | src/map.h | 94 | ||||
| -rw-r--r-- | src/renderer.cpp | 4 |
4 files changed, 200 insertions, 97 deletions
| diff --git a/src/game.cpp b/src/game.cpp index 088ab4d..9d557e3 100644 --- a/src/game.cpp +++ b/src/game.cpp | |||
| @@ -20,7 +20,7 @@ Game::Game(std::mt19937& rng, Muxer& muxer, Renderer& renderer) : | |||
| 20 | { | 20 | { |
| 21 | for (int x = -1; x <= 1; x++) | 21 | for (int x = -1; x <= 1; x++) |
| 22 | { | 22 | { |
| 23 | map.at(x,y).tile = Tile::Floor; | 23 | map.tile(x,y) = Tile::Floor; |
| 24 | } | 24 | } |
| 25 | } | 25 | } |
| 26 | 26 | ||
| @@ -35,12 +35,12 @@ Game::Game(std::mt19937& rng, Muxer& muxer, Renderer& renderer) : | |||
| 35 | 35 | ||
| 36 | inline bool isTileSetOrNotLit(const Map& map, int x, int y) | 36 | inline bool isTileSetOrNotLit(const Map& map, int x, int y) |
| 37 | { | 37 | { |
| 38 | return (map.inBounds(x, y) && (map.at(x,y).tile == Tile::Wall || !map.at(x,y).lit)); | 38 | return (map.inBounds(x, y) && (map.tile(x,y) == Tile::Wall || !map.at(x,y).lit)); |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | inline bool isTileSet(const Map& map, int x, int y, Tile val = Tile::Wall) | 41 | inline bool isTileSet(const Map& map, int x, int y, Tile val = Tile::Wall) |
| 42 | { | 42 | { |
| 43 | return (map.inBounds(x, y) && map.at(x,y).tile == val); | 43 | return (map.inBounds(x, y) && map.tile(x,y) == val); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | inline void incrementIfSet(const Game& game, int& count, int x, int y, Tile val = Tile::Wall) | 46 | inline void incrementIfSet(const Game& game, int& count, int x, int y, Tile val = Tile::Wall) |
| @@ -55,6 +55,56 @@ inline int getZoomLevel(const Game& game) { | |||
| 55 | return game.curZoom - INIT_ZOOM; | 55 | return game.curZoom - INIT_ZOOM; |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | inline void tickIndividual(Game& game, std::vector<Tile>& mapDoubleBuffer, int x, int y, bool onlyDark) { | ||
| 59 | if (onlyDark && game.map.at(x,y).lit) | ||
| 60 | { | ||
| 61 | return; | ||
| 62 | } | ||
| 63 | |||
| 64 | if (game.map.tile(x,y) == Tile::Lamp) | ||
| 65 | { | ||
| 66 | return; | ||
| 67 | } | ||
| 68 | |||
| 69 | int count = 0; | ||
| 70 | |||
| 71 | incrementIfSet(game, count, x-1, y-1); | ||
| 72 | incrementIfSet(game, count, x-1, y ); | ||
| 73 | incrementIfSet(game, count, x-1, y+1); | ||
| 74 | incrementIfSet(game, count, x , y-1); | ||
| 75 | incrementIfSet(game, count, x , y ); | ||
| 76 | incrementIfSet(game, count, x , y+1); | ||
| 77 | incrementIfSet(game, count, x+1, y-1); | ||
| 78 | incrementIfSet(game, count, x+1, y ); | ||
| 79 | incrementIfSet(game, count, x+1, y+1); | ||
| 80 | |||
| 81 | int tempIndex = game.map.getTrueX(x) + game.map.getTrueY(y) * game.map.getWidth(); | ||
| 82 | if (count >= 5) | ||
| 83 | { | ||
| 84 | mapDoubleBuffer[tempIndex] = Tile::Wall; | ||
| 85 | } else { | ||
| 86 | mapDoubleBuffer[tempIndex] = Tile::Floor; | ||
| 87 | } | ||
| 88 | |||
| 89 | if (mapDoubleBuffer[tempIndex] != game.map.tile(x,y)) { | ||
| 90 | game.map.at(x,y).dirtyRender = true; | ||
| 91 | game.dirtyRender = true; | ||
| 92 | game.map.markDirtyAround(x,y); | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | void Game::tickDirty(bool onlyDark) { | ||
| 97 | mapDoubleBuffer = map.tiles(); | ||
| 98 | std::vector<coord> dirty = map.getDirty(); | ||
| 99 | map.resetDirty(); | ||
| 100 | |||
| 101 | for (auto [x,y] : dirty) { | ||
| 102 | tickIndividual(*this, mapDoubleBuffer, x, y, onlyDark); | ||
| 103 | } | ||
| 104 | |||
| 105 | std::swap(map.tiles(), mapDoubleBuffer); | ||
| 106 | } | ||
| 107 | |||
| 58 | void Game::tick( | 108 | void Game::tick( |
| 59 | int x1, | 109 | int x1, |
| 60 | int y1, | 110 | int y1, |
| @@ -63,7 +113,8 @@ void Game::tick( | |||
| 63 | bool invert, | 113 | bool invert, |
| 64 | bool onlyDark) | 114 | bool onlyDark) |
| 65 | { | 115 | { |
| 66 | mapDoubleBuffer = map.data(); | 116 | mapDoubleBuffer = map.tiles(); |
| 117 | map.resetDirty(); | ||
| 67 | 118 | ||
| 68 | for (int y = map.getTop(); y < map.getBottom(); y++) | 119 | for (int y = map.getTop(); y < map.getBottom(); y++) |
| 69 | { | 120 | { |
| @@ -74,44 +125,11 @@ void Game::tick( | |||
| 74 | continue; | 125 | continue; |
| 75 | } | 126 | } |
| 76 | 127 | ||
| 77 | if (onlyDark && map.at(x,y).lit) | 128 | tickIndividual(*this, mapDoubleBuffer, x, y, onlyDark); |
| 78 | { | ||
| 79 | continue; | ||
| 80 | } | ||
| 81 | |||
| 82 | if (map.at(x,y).tile == Tile::Lamp) | ||
| 83 | { | ||
| 84 | continue; | ||
| 85 | } | ||
| 86 | |||
| 87 | int count = 0; | ||
| 88 | |||
| 89 | incrementIfSet(*this, count, x-1, y-1); | ||
| 90 | incrementIfSet(*this, count, x-1, y ); | ||
| 91 | incrementIfSet(*this, count, x-1, y+1); | ||
| 92 | incrementIfSet(*this, count, x , y-1); | ||
| 93 | incrementIfSet(*this, count, x , y ); | ||
| 94 | incrementIfSet(*this, count, x , y+1); | ||
| 95 | incrementIfSet(*this, count, x+1, y-1); | ||
| 96 | incrementIfSet(*this, count, x+1, y ); | ||
| 97 | incrementIfSet(*this, count, x+1, y+1); | ||
| 98 | |||
| 99 | int tempIndex = map.getTrueX(x) + map.getTrueY(y) * map.getWidth(); | ||
| 100 | if (count >= 5) | ||
| 101 | { | ||
| 102 | mapDoubleBuffer[tempIndex].tile = Tile::Wall; | ||
| 103 | } else { | ||
| 104 | mapDoubleBuffer[tempIndex].tile = Tile::Floor; | ||
| 105 | } | ||
| 106 | |||
| 107 | if (mapDoubleBuffer[tempIndex].tile != map.at(x,y).tile) { | ||
| 108 | mapDoubleBuffer[tempIndex].dirtyRender = true; | ||
| 109 | dirtyRender = true; | ||
| 110 | } | ||
| 111 | } | 129 | } |
| 112 | } | 130 | } |
| 113 | 131 | ||
| 114 | std::swap(map.data(), mapDoubleBuffer); | 132 | std::swap(map.tiles(), mapDoubleBuffer); |
| 115 | } | 133 | } |
| 116 | 134 | ||
| 117 | void Game::tick(bool onlyDark) | 135 | void Game::tick(bool onlyDark) |
| @@ -127,11 +145,11 @@ void Game::tick(bool onlyDark) | |||
| 127 | 145 | ||
| 128 | bool Game::movePlayer(int x, int y) | 146 | bool Game::movePlayer(int x, int y) |
| 129 | { | 147 | { |
| 130 | if (map.at(x,y).tile == Tile::Floor && !map.at(x,y).sign) | 148 | if (map.tile(x,y) == Tile::Floor && !map.at(x,y).sign) |
| 131 | { | 149 | { |
| 132 | if (map.at(player_x, player_y).tile == Tile::Floor) | 150 | if (map.tile(player_x, player_y) == Tile::Floor) |
| 133 | { | 151 | { |
| 134 | map.at(player_x, player_y).tile = Tile::Dust; | 152 | map.tile(player_x, player_y) = Tile::Dust; |
| 135 | map.at(player_x, player_y).dustLife = 1; | 153 | map.at(player_x, player_y).dustLife = 1; |
| 136 | numDust++; | 154 | numDust++; |
| 137 | } | 155 | } |
| @@ -169,14 +187,15 @@ void Game::recalculateLighting() | |||
| 169 | litSpots = 0; | 187 | litSpots = 0; |
| 170 | dirtyRender = true; | 188 | dirtyRender = true; |
| 171 | 189 | ||
| 172 | for (MapData& md : map.data()) | 190 | for (int y=map.getTop(); y<map.getBottom(); y++) { |
| 173 | { | 191 | for (int x=map.getLeft(); x<map.getRight(); x++) { |
| 174 | md.wasLit = md.lit; | 192 | map.at(x,y).wasLit = map.at(x,y).lit; |
| 175 | md.lit = false; | 193 | map.at(x,y).lit = false; |
| 176 | md.litTiles.clear(); | 194 | map.at(x,y).litTiles.clear(); |
| 177 | 195 | ||
| 178 | if (md.tile == Tile::Wall) { | 196 | if (map.tile(x,y) == Tile::Wall) { |
| 179 | md.dirtyRender = true; | 197 | map.at(x,y).dirtyRender = true; |
| 198 | } | ||
| 180 | } | 199 | } |
| 181 | } | 200 | } |
| 182 | 201 | ||
| @@ -188,7 +207,7 @@ void Game::recalculateLighting() | |||
| 188 | [] (void* data, int x, int y) { | 207 | [] (void* data, int x, int y) { |
| 189 | Game& game = *static_cast<Game*>(data); | 208 | Game& game = *static_cast<Game*>(data); |
| 190 | 209 | ||
| 191 | return game.map.inBounds(x,y) && game.map.at(x,y).tile == Tile::Wall; | 210 | return game.map.inBounds(x,y) && game.map.tile(x,y) == Tile::Wall; |
| 192 | }); | 211 | }); |
| 193 | 212 | ||
| 194 | fov_settings_set_apply_lighting_function( | 213 | fov_settings_set_apply_lighting_function( |
| @@ -223,11 +242,11 @@ void Game::recalculateLighting() | |||
| 223 | { | 242 | { |
| 224 | ls = Source::Player; | 243 | ls = Source::Player; |
| 225 | lightRadius = RADIUS; | 244 | lightRadius = RADIUS; |
| 226 | } else if (map.at(x,y).tile == Tile::Dust) | 245 | } else if (map.tile(x,y) == Tile::Dust) |
| 227 | { | 246 | { |
| 228 | ls = Source::Dust; | 247 | ls = Source::Dust; |
| 229 | lightRadius = 2; | 248 | lightRadius = 2; |
| 230 | } else if (map.at(x,y).tile == Tile::Lamp) | 249 | } else if (map.tile(x,y) == Tile::Lamp) |
| 231 | { | 250 | { |
| 232 | ls = Source::Lamp; | 251 | ls = Source::Lamp; |
| 233 | lightRadius = RADIUS; | 252 | lightRadius = RADIUS; |
| @@ -265,7 +284,7 @@ void Game::recalculateRender() { | |||
| 265 | if (map.at(x,y).dirtyRender) { | 284 | if (map.at(x,y).dirtyRender) { |
| 266 | map.at(x,y).dirtyRender = false; | 285 | map.at(x,y).dirtyRender = false; |
| 267 | 286 | ||
| 268 | if (map.at(x,y).tile == Tile::Floor) { | 287 | if (map.tile(x,y) == Tile::Floor) { |
| 269 | int renderDesc = 0; | 288 | int renderDesc = 0; |
| 270 | if (isTileSetOrNotLit(map, x-1, y-1)) renderDesc |= (1 << 7); | 289 | if (isTileSetOrNotLit(map, x-1, y-1)) renderDesc |= (1 << 7); |
| 271 | if (isTileSetOrNotLit(map, x , y-1)) renderDesc |= (1 << 6); | 290 | if (isTileSetOrNotLit(map, x , y-1)) renderDesc |= (1 << 6); |
| @@ -297,7 +316,7 @@ void Game::recalculateRender() { | |||
| 297 | map.at(x,y).renderId = -1; | 316 | map.at(x,y).renderId = -1; |
| 298 | map.at(x,y).sign = false; | 317 | map.at(x,y).sign = false; |
| 299 | } | 318 | } |
| 300 | } else if (map.at(x,y).tile == Tile::Wall) { | 319 | } else if (map.tile(x,y) == Tile::Wall) { |
| 301 | static bool initWalls = false; | 320 | static bool initWalls = false; |
| 302 | static std::vector<int> wallRenders(256, TilesetIndex(0, 0)); | 321 | static std::vector<int> wallRenders(256, TilesetIndex(0, 0)); |
| 303 | if (!initWalls) { | 322 | if (!initWalls) { |
| @@ -439,12 +458,12 @@ void Game::popLamp(int x, int y, size_t chain) | |||
| 439 | { | 458 | { |
| 440 | muxer.playSoundAtPosition("pop", x, y); | 459 | muxer.playSoundAtPosition("pop", x, y); |
| 441 | 460 | ||
| 442 | if (map.at(x,y).tile == Tile::Lamp) | 461 | if (map.tile(x,y) == Tile::Lamp) |
| 443 | { | 462 | { |
| 444 | numLamps--; | 463 | numLamps--; |
| 445 | } | 464 | } |
| 446 | 465 | ||
| 447 | map.at(x,y).tile = Tile::Dust; | 466 | map.tile(x,y) = Tile::Dust; |
| 448 | map.at(x,y).dustLife = 2; | 467 | map.at(x,y).dustLife = 2; |
| 449 | numDust++; | 468 | numDust++; |
| 450 | dirtyLighting = true; | 469 | dirtyLighting = true; |
| @@ -465,19 +484,19 @@ void Game::processKickup() | |||
| 465 | coord c {x,y}; | 484 | coord c {x,y}; |
| 466 | 485 | ||
| 467 | if (map.inBounds(x,y) && | 486 | if (map.inBounds(x,y) && |
| 468 | (map.at(x,y).tile == Tile::Floor || map.at(x,y).tile == Tile::Lamp) && | 487 | (map.tile(x,y) == Tile::Floor || map.tile(x,y) == Tile::Lamp) && |
| 469 | !kickup.done.count(c)) | 488 | !kickup.done.count(c)) |
| 470 | { | 489 | { |
| 471 | newFront.insert(c); | 490 | newFront.insert(c); |
| 472 | kickup.done.insert(c); | 491 | kickup.done.insert(c); |
| 473 | 492 | ||
| 474 | if (map.at(x,y).tile == Tile::Floor) | 493 | if (map.tile(x,y) == Tile::Floor) |
| 475 | { | 494 | { |
| 476 | map.at(x,y).tile = Tile::Dust; | 495 | map.tile(x,y) = Tile::Dust; |
| 477 | map.at(x,y).dustLife = 2; | 496 | map.at(x,y).dustLife = 2; |
| 478 | numDust++; | 497 | numDust++; |
| 479 | dirtyLighting = true; | 498 | dirtyLighting = true; |
| 480 | } else if (map.at(x,y).tile == Tile::Lamp) | 499 | } else if (map.tile(x,y) == Tile::Lamp) |
| 481 | { | 500 | { |
| 482 | popLamp(x, y, kickup.chain + 1); | 501 | popLamp(x, y, kickup.chain + 1); |
| 483 | } | 502 | } |
| @@ -571,11 +590,11 @@ void Game::setZoom(size_t zoom) | |||
| 571 | } | 590 | } |
| 572 | 591 | ||
| 573 | void Game::performDash() { | 592 | void Game::performDash() { |
| 574 | if (map.at(player_x, player_y).tile == Tile::Floor) { | 593 | if (map.tile(player_x, player_y) == Tile::Floor) { |
| 575 | std::vector<coord> freeSpaces; | 594 | std::vector<coord> freeSpaces; |
| 576 | 595 | ||
| 577 | auto addIfFree = [&] (int x, int y) { | 596 | auto addIfFree = [&] (int x, int y) { |
| 578 | if (map.inBounds(x,y) && map.at(x,y).tile == Tile::Floor) | 597 | if (map.inBounds(x,y) && map.tile(x,y) == Tile::Floor) |
| 579 | { | 598 | { |
| 580 | freeSpaces.emplace_back(x, y); | 599 | freeSpaces.emplace_back(x, y); |
| 581 | } | 600 | } |
| @@ -592,7 +611,7 @@ void Game::performDash() { | |||
| 592 | 611 | ||
| 593 | if (!freeSpaces.empty()) | 612 | if (!freeSpaces.empty()) |
| 594 | { | 613 | { |
| 595 | map.at(player_x, player_y).tile = Tile::Lamp; | 614 | map.tile(player_x, player_y) = Tile::Lamp; |
| 596 | numLamps++; | 615 | numLamps++; |
| 597 | dirtyLighting = true; | 616 | dirtyLighting = true; |
| 598 | kickUpDust(player_x, player_y, 0); | 617 | kickUpDust(player_x, player_y, 0); |
| @@ -725,18 +744,19 @@ void Game::updatePlaying(size_t frameTime) { | |||
| 725 | { | 744 | { |
| 726 | numDust = 0; | 745 | numDust = 0; |
| 727 | 746 | ||
| 728 | for (MapData& md : map.data()) | 747 | for (int y=map.getTop(); y<map.getBottom(); y++) { |
| 729 | { | 748 | for (int x=map.getLeft(); x<map.getRight(); x++) { |
| 730 | if (md.tile == Tile::Dust) | 749 | if (map.tile(x,y) == Tile::Dust) |
| 731 | { | ||
| 732 | md.dustLife--; | ||
| 733 | |||
| 734 | if (md.dustLife <= 0) | ||
| 735 | { | 750 | { |
| 736 | md.tile = Tile::Floor; | 751 | map.at(x,y).dustLife--; |
| 737 | dirtyLighting = true; | 752 | |
| 738 | } else { | 753 | if (map.at(x,y).dustLife <= 0) |
| 739 | numDust++; | 754 | { |
| 755 | map.tile(x,y) = Tile::Floor; | ||
| 756 | dirtyLighting = true; | ||
| 757 | } else { | ||
| 758 | numDust++; | ||
| 759 | } | ||
| 740 | } | 760 | } |
| 741 | } | 761 | } |
| 742 | } | 762 | } |
| @@ -784,7 +804,7 @@ void Game::updatePlaying(size_t frameTime) { | |||
| 784 | { | 804 | { |
| 785 | for (int x = map.getLeft(); x < map.getRight(); x++) | 805 | for (int x = map.getLeft(); x < map.getRight(); x++) |
| 786 | { | 806 | { |
| 787 | if (map.at(x,y).tile == Tile::Lamp) | 807 | if (map.tile(x,y) == Tile::Lamp) |
| 788 | { | 808 | { |
| 789 | lamps.emplace_back(x, y); | 809 | lamps.emplace_back(x, y); |
| 790 | } | 810 | } |
| @@ -874,29 +894,24 @@ void Game::updatePlaying(size_t frameTime) { | |||
| 874 | { | 894 | { |
| 875 | if (!map.at(x,y).lit && map.at(x,y).wasLit) | 895 | if (!map.at(x,y).lit && map.at(x,y).wasLit) |
| 876 | { | 896 | { |
| 897 | Tile oldTile = map.tile(x,y); | ||
| 877 | if (std::bernoulli_distribution(0.5)(rng)) | 898 | if (std::bernoulli_distribution(0.5)(rng)) |
| 878 | { | 899 | { |
| 879 | map.at(x,y).tile = Tile::Wall; | 900 | map.tile(x,y) = Tile::Wall; |
| 880 | } else { | 901 | } else { |
| 881 | map.at(x,y).tile = Tile::Floor; | 902 | map.tile(x,y) = Tile::Floor; |
| 903 | } | ||
| 904 | if (map.tile(x,y) != oldTile) { | ||
| 905 | map.at(x,y).dirtyRender = true; | ||
| 906 | map.markDirtyAround(x,y); | ||
| 882 | } | 907 | } |
| 883 | map.at(x,y).dirtyRender = true; | ||
| 884 | } | 908 | } |
| 885 | } | 909 | } |
| 886 | } | 910 | } |
| 887 | 911 | ||
| 888 | /*int x1 = player_x - curZoom * ZOOM_X_FACTOR / 2 - 1; | 912 | tickDirty(true); |
| 889 | int y1 = player_y - curZoom * ZOOM_Y_FACTOR / 2 - 1; | 913 | tickDirty(true); |
| 890 | int x2 = player_x + curZoom * ZOOM_X_FACTOR / 2 + 2; | 914 | tickDirty(true); |
| 891 | int y2 = player_y + curZoom * ZOOM_Y_FACTOR / 2 + 2;*/ | ||
| 892 | int x1 = player_x - CHUNK_WIDTH / 2 - 1; | ||
| 893 | int y1 = player_y - CHUNK_HEIGHT / 2 - 1; | ||
| 894 | int x2 = player_x + CHUNK_WIDTH / 2 + 2; | ||
| 895 | int y2 = player_y + CHUNK_HEIGHT / 2 + 2; | ||
| 896 | |||
| 897 | tick(x1, y1, x2, y2, false, true); | ||
| 898 | tick(x1, y1, x2, y2, false, true); | ||
| 899 | tick(x1, y1, x2, y2, false, true); | ||
| 900 | 915 | ||
| 901 | // TODO: better zoom algorithm | 916 | // TODO: better zoom algorithm |
| 902 | setZoom(litSpots / 1500 + INIT_ZOOM); | 917 | setZoom(litSpots / 1500 + INIT_ZOOM); |
| diff --git a/src/game.h b/src/game.h index 637a033..c75d43b 100644 --- a/src/game.h +++ b/src/game.h | |||
| @@ -71,7 +71,7 @@ public: | |||
| 71 | bool dirtyRender = true; | 71 | bool dirtyRender = true; |
| 72 | size_t numLamps = 0; | 72 | size_t numLamps = 0; |
| 73 | size_t numDust = 0; | 73 | size_t numDust = 0; |
| 74 | std::vector<MapData> mapDoubleBuffer; | 74 | std::vector<Tile> mapDoubleBuffer; |
| 75 | 75 | ||
| 76 | int player_x = 0; | 76 | int player_x = 0; |
| 77 | int player_y = 0; | 77 | int player_y = 0; |
| @@ -111,6 +111,8 @@ public: | |||
| 111 | 111 | ||
| 112 | private: | 112 | private: |
| 113 | 113 | ||
| 114 | void tickDirty(bool onlyDark); | ||
| 115 | |||
| 114 | void tick( | 116 | void tick( |
| 115 | int x1, | 117 | int x1, |
| 116 | int y1, | 118 | int y1, |
| diff --git a/src/map.h b/src/map.h index de74b14..fe3270c 100644 --- a/src/map.h +++ b/src/map.h | |||
| @@ -25,7 +25,6 @@ enum class Source { | |||
| 25 | }; | 25 | }; |
| 26 | 26 | ||
| 27 | struct MapData { | 27 | struct MapData { |
| 28 | Tile tile = Tile::Floor; | ||
| 29 | bool lit = false; | 28 | bool lit = false; |
| 30 | bool wasLit = false; | 29 | bool wasLit = false; |
| 31 | size_t dustLife = 0; | 30 | size_t dustLife = 0; |
| @@ -39,6 +38,7 @@ struct MapData { | |||
| 39 | }; | 38 | }; |
| 40 | 39 | ||
| 41 | struct Chunk { | 40 | struct Chunk { |
| 41 | std::array<Tile, CHUNK_WIDTH*CHUNK_HEIGHT> tiles; | ||
| 42 | std::array<MapData, CHUNK_WIDTH*CHUNK_HEIGHT> data; | 42 | std::array<MapData, CHUNK_WIDTH*CHUNK_HEIGHT> data; |
| 43 | int litTiles = 0; | 43 | int litTiles = 0; |
| 44 | int x; | 44 | int x; |
| @@ -101,6 +101,16 @@ public: | |||
| 101 | (y < top_ + height_); | 101 | (y < top_ + height_); |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | inline const Tile& tile(int x, int y) const | ||
| 105 | { | ||
| 106 | return loadedTiles_[(x - left_) + width_ * (y - top_)]; | ||
| 107 | } | ||
| 108 | |||
| 109 | inline Tile& tile(int x, int y) | ||
| 110 | { | ||
| 111 | return const_cast<Tile&>(static_cast<const Map&>(*this).tile(x, y)); | ||
| 112 | } | ||
| 113 | |||
| 104 | inline const MapData& at(int x, int y) const | 114 | inline const MapData& at(int x, int y) const |
| 105 | { | 115 | { |
| 106 | return loaded_[(x - left_) + width_ * (y - top_)]; | 116 | return loaded_[(x - left_) + width_ * (y - top_)]; |
| @@ -111,6 +121,16 @@ public: | |||
| 111 | return const_cast<MapData&>(static_cast<const Map&>(*this).at(x, y)); | 121 | return const_cast<MapData&>(static_cast<const Map&>(*this).at(x, y)); |
| 112 | } | 122 | } |
| 113 | 123 | ||
| 124 | inline const std::vector<Tile>& tiles() const | ||
| 125 | { | ||
| 126 | return loadedTiles_; | ||
| 127 | } | ||
| 128 | |||
| 129 | inline std::vector<Tile>& tiles() | ||
| 130 | { | ||
| 131 | return loadedTiles_; | ||
| 132 | } | ||
| 133 | |||
| 114 | inline const std::vector<MapData>& data() const | 134 | inline const std::vector<MapData>& data() const |
| 115 | { | 135 | { |
| 116 | return loaded_; | 136 | return loaded_; |
| @@ -139,6 +159,11 @@ public: | |||
| 139 | int startX = chunkX * CHUNK_WIDTH; | 159 | int startX = chunkX * CHUNK_WIDTH; |
| 140 | int startY = chunkY * CHUNK_HEIGHT; | 160 | int startY = chunkY * CHUNK_HEIGHT; |
| 141 | for (int y=0; y<CHUNK_HEIGHT; y++) { | 161 | for (int y=0; y<CHUNK_HEIGHT; y++) { |
| 162 | std::copy( | ||
| 163 | std::next(std::begin(loadedTiles_), (chunkY*CHUNK_HEIGHT + y)*width_ + chunkX*CHUNK_WIDTH), | ||
| 164 | std::next(std::begin(loadedTiles_), (chunkY*CHUNK_HEIGHT + y)*width_ + (chunkX+1)*CHUNK_WIDTH), | ||
| 165 | std::next(std::begin(chunk.tiles), y*CHUNK_WIDTH)); | ||
| 166 | |||
| 142 | for (int x=0; x<CHUNK_WIDTH; x++) { | 167 | for (int x=0; x<CHUNK_WIDTH; x++) { |
| 143 | chunk.data[x+y*CHUNK_WIDTH] = loaded_[startX+x+(startY+y)*width_]; | 168 | chunk.data[x+y*CHUNK_WIDTH] = loaded_[startX+x+(startY+y)*width_]; |
| 144 | if (chunk.data[x+y*CHUNK_WIDTH].lit) { | 169 | if (chunk.data[x+y*CHUNK_WIDTH].lit) { |
| @@ -169,6 +194,9 @@ public: | |||
| 169 | width_ = chunksHoriz_ * CHUNK_WIDTH; | 194 | width_ = chunksHoriz_ * CHUNK_WIDTH; |
| 170 | height_ = chunksVert_ * CHUNK_HEIGHT; | 195 | height_ = chunksVert_ * CHUNK_HEIGHT; |
| 171 | loaded_ = std::vector<MapData>(width_ * height_); | 196 | loaded_ = std::vector<MapData>(width_ * height_); |
| 197 | loadedTiles_ = std::vector<Tile>(width_ * height_, Tile::Floor); | ||
| 198 | dirtyTiles_.clear(); | ||
| 199 | dirtySet_ = std::vector<bool>(width_ * height_, false); | ||
| 172 | 200 | ||
| 173 | // Load in the requested chunks. | 201 | // Load in the requested chunks. |
| 174 | for (int chunkY = 0; chunkY < chunksVert_; chunkY++) { | 202 | for (int chunkY = 0; chunkY < chunksVert_; chunkY++) { |
| @@ -190,14 +218,16 @@ public: | |||
| 190 | chunk.y = topmostChunk_ + chunkY; | 218 | chunk.y = topmostChunk_ + chunkY; |
| 191 | chunk.litTiles = 0; | 219 | chunk.litTiles = 0; |
| 192 | 220 | ||
| 193 | for (MapData& md : chunk.data) | 221 | for (Tile& tile : chunk.tiles) |
| 194 | { | 222 | { |
| 195 | if (std::bernoulli_distribution(0.5)(rng)) | 223 | if (std::bernoulli_distribution(0.5)(rng)) |
| 196 | { | 224 | { |
| 197 | md.tile = Tile::Wall; | 225 | tile = Tile::Wall; |
| 198 | } else { | 226 | } else { |
| 199 | md.tile = Tile::Floor; | 227 | tile = Tile::Floor; |
| 200 | } | 228 | } |
| 229 | } | ||
| 230 | for (MapData& md : chunk.data) { | ||
| 201 | md.dirtyRender = true; | 231 | md.dirtyRender = true; |
| 202 | } | 232 | } |
| 203 | } | 233 | } |
| @@ -207,6 +237,10 @@ public: | |||
| 207 | 237 | ||
| 208 | for (int y = 0; y < CHUNK_HEIGHT; y++) { | 238 | for (int y = 0; y < CHUNK_HEIGHT; y++) { |
| 209 | std::copy( | 239 | std::copy( |
| 240 | std::next(std::begin(chunk.tiles), y*CHUNK_WIDTH), | ||
| 241 | std::next(std::begin(chunk.tiles), (y+1)*CHUNK_WIDTH), | ||
| 242 | std::next(std::begin(loadedTiles_), (chunkY*CHUNK_HEIGHT + y)*width_ + chunkX*CHUNK_WIDTH)); | ||
| 243 | std::copy( | ||
| 210 | std::next(std::begin(chunk.data), y*CHUNK_WIDTH), | 244 | std::next(std::begin(chunk.data), y*CHUNK_WIDTH), |
| 211 | std::next(std::begin(chunk.data), (y+1)*CHUNK_WIDTH), | 245 | std::next(std::begin(chunk.data), (y+1)*CHUNK_WIDTH), |
| 212 | std::next(std::begin(loaded_), (chunkY*CHUNK_HEIGHT + y)*width_ + chunkX*CHUNK_WIDTH)); | 246 | std::next(std::begin(loaded_), (chunkY*CHUNK_HEIGHT + y)*width_ + chunkX*CHUNK_WIDTH)); |
| @@ -215,7 +249,55 @@ public: | |||
| 215 | unloadedLitTiles_ -= chunk.litTiles; | 249 | unloadedLitTiles_ -= chunk.litTiles; |
| 216 | } | 250 | } |
| 217 | } | 251 | } |
| 252 | } | ||
| 218 | 253 | ||
| 254 | void markDirtyAround(int x, int y) { | ||
| 255 | if (x > left_) { | ||
| 256 | if (y > top_) { | ||
| 257 | markDirty(x-1, y-1); | ||
| 258 | } | ||
| 259 | markDirty(x-1, y ); | ||
| 260 | if (y < top_+height_-1) { | ||
| 261 | markDirty(x-1, y+1); | ||
| 262 | } | ||
| 263 | } | ||
| 264 | |||
| 265 | if (y > top_) { | ||
| 266 | markDirty(x , y-1); | ||
| 267 | } | ||
| 268 | markDirty(x , y ); | ||
| 269 | if (y < top_+height_-1) { | ||
| 270 | markDirty(x , y+1); | ||
| 271 | } | ||
| 272 | |||
| 273 | if (x < left_+width_-1) { | ||
| 274 | if (y > top_) { | ||
| 275 | markDirty(x+1, y-1); | ||
| 276 | } | ||
| 277 | markDirty(x+1, y ); | ||
| 278 | if (y < top_+height_-1) { | ||
| 279 | markDirty(x+1, y+1); | ||
| 280 | } | ||
| 281 | } | ||
| 282 | } | ||
| 283 | |||
| 284 | void markDirty(int x, int y) { | ||
| 285 | size_t index = (x-left_)+(y-top_)*width_; | ||
| 286 | if (!dirtySet_[index]) { | ||
| 287 | dirtySet_[index] = true; | ||
| 288 | dirtyTiles_.emplace_back(x,y); | ||
| 289 | } | ||
| 290 | } | ||
| 291 | |||
| 292 | const std::vector<coord> getDirty() const { | ||
| 293 | return dirtyTiles_; | ||
| 294 | } | ||
| 295 | |||
| 296 | void resetDirty() { | ||
| 297 | for (auto [x,y] : dirtyTiles_) { | ||
| 298 | dirtySet_[(x-left_)+(y-top_)*width_] = false; | ||
| 299 | } | ||
| 300 | dirtyTiles_.clear(); | ||
| 219 | } | 301 | } |
| 220 | 302 | ||
| 221 | private: | 303 | private: |
| @@ -228,6 +310,7 @@ private: | |||
| 228 | int topmostChunk_; | 310 | int topmostChunk_; |
| 229 | int chunksHoriz_; | 311 | int chunksHoriz_; |
| 230 | int chunksVert_; | 312 | int chunksVert_; |
| 313 | std::vector<Tile> loadedTiles_; | ||
| 231 | std::vector<MapData> loaded_; | 314 | std::vector<MapData> loaded_; |
| 232 | 315 | ||
| 233 | std::vector<Chunk> chunks_; | 316 | std::vector<Chunk> chunks_; |
| @@ -235,6 +318,9 @@ private: | |||
| 235 | std::map<int, std::map<int, size_t>> chunkByPos_; // chunkByPos_[X][Y] | 318 | std::map<int, std::map<int, size_t>> chunkByPos_; // chunkByPos_[X][Y] |
| 236 | 319 | ||
| 237 | int unloadedLitTiles_ = 0; | 320 | int unloadedLitTiles_ = 0; |
| 321 | |||
| 322 | std::vector<coord> dirtyTiles_; | ||
| 323 | std::vector<bool> dirtySet_; | ||
| 238 | }; | 324 | }; |
| 239 | 325 | ||
| 240 | #endif /* end of include guard: MAP_H_3AB00D12 */ | 326 | #endif /* end of include guard: MAP_H_3AB00D12 */ |
| diff --git a/src/renderer.cpp b/src/renderer.cpp index c8c1746..9744e70 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp | |||
| @@ -173,7 +173,7 @@ void Renderer::renderGame( | |||
| 173 | 173 | ||
| 174 | if (draw) | 174 | if (draw) |
| 175 | { | 175 | { |
| 176 | if (game.map.at(x,y).tile != Tile::Wall) { | 176 | if (game.map.tile(x,y) != Tile::Wall) { |
| 177 | SDL_Rect tileRect {17 * 16, 15 * 16, 16, 16}; | 177 | SDL_Rect tileRect {17 * 16, 15 * 16, 16, 16}; |
| 178 | SDL_RenderCopy(ren_.get(), tileset_.get(), &tileRect, &rect); | 178 | SDL_RenderCopy(ren_.get(), tileset_.get(), &tileRect, &rect); |
| 179 | 179 | ||
| @@ -192,7 +192,7 @@ void Renderer::renderGame( | |||
| 192 | SDL_RenderCopy(ren_.get(), tileset_.get(), &tileRect, &rect); | 192 | SDL_RenderCopy(ren_.get(), tileset_.get(), &tileRect, &rect); |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | if (game.map.at(x,y).tile == Tile::Lamp) { | 195 | if (game.map.tile(x,y) == Tile::Lamp) { |
| 196 | SDL_RenderCopy(ren_.get(), lamp_.get(), nullptr, &rect); | 196 | SDL_RenderCopy(ren_.get(), lamp_.get(), nullptr, &rect); |
| 197 | } | 197 | } |
| 198 | 198 | ||
