summary refs log tree commit diff stats
path: root/src/map.h
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 /src/map.h
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.
Diffstat (limited to 'src/map.h')
-rw-r--r--src/map.h94
1 files changed, 90 insertions, 4 deletions
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 */