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 | ||