diff options
Diffstat (limited to 'src/game.cpp')
| -rw-r--r-- | src/game.cpp | 195 |
1 files changed, 105 insertions, 90 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); |
