summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorStar Rauchenberger <fefferburbia@gmail.com>2022-03-17 15:28:22 -0400
committerStar Rauchenberger <fefferburbia@gmail.com>2022-03-17 15:28:22 -0400
commit5324adfe51f1348fc97fe2ee0ca4e4bbd2a6ad64 (patch)
tree6b3ff32f9ad2764405fd73a70e15c960a076ed00
parente0fd87411eb5368fee47e268ae03d073293e58c3 (diff)
downloadether-5324adfe51f1348fc97fe2ee0ca4e4bbd2a6ad64.tar.gz
ether-5324adfe51f1348fc97fe2ee0ca4e4bbd2a6ad64.tar.bz2
ether-5324adfe51f1348fc97fe2ee0ca4e4bbd2a6ad64.zip
lotta performance improvements
the two main things:

1) When ticking three times after a lighting change, we no longer iterate over the entire map. Instead, we keep a list of the tiles that have changed and the ones adjacent to them, and we iterate over that list.
2) The map tile type is now stored in a separate array from the rest of the tile data. This is because the tile type is the only thing needed for the cellular automata tick, and thus the only thing that we need to actually copy.
-rw-r--r--src/game.cpp195
-rw-r--r--src/game.h4
-rw-r--r--src/map.h94
-rw-r--r--src/renderer.cpp4
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
36inline bool isTileSetOrNotLit(const Map& map, int x, int y) 36inline 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
41inline bool isTileSet(const Map& map, int x, int y, Tile val = Tile::Wall) 41inline 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
46inline void incrementIfSet(const Game& game, int& count, int x, int y, Tile val = Tile::Wall) 46inline 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
58inline 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
96void 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
58void Game::tick( 108void 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
117void Game::tick(bool onlyDark) 135void Game::tick(bool onlyDark)
@@ -127,11 +145,11 @@ void Game::tick(bool onlyDark)
127 145
128bool Game::movePlayer(int x, int y) 146bool 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
573void Game::performDash() { 592void 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
112private: 112private:
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
27struct MapData { 27struct 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
41struct Chunk { 40struct 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
221private: 303private:
@@ -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