summary refs log tree commit diff stats
path: root/src/map.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/map.h')
-rw-r--r--src/map.h184
1 files changed, 160 insertions, 24 deletions
diff --git a/src/map.h b/src/map.h index 329553c..d28b8d4 100644 --- a/src/map.h +++ b/src/map.h
@@ -3,23 +3,62 @@
3 3
4#include <vector> 4#include <vector>
5#include <algorithm> 5#include <algorithm>
6#include <array>
7#include <list>
8#include <map>
9#include <random>
10#include "consts.h"
6 11
7template <typename T> 12using coord = std::tuple<int, int>;
8class Map {
9public:
10 13
11 Map( 14enum class Tile {
12 int left, 15 Floor,
13 int top, 16 Wall,
14 int width, 17 Dust,
15 int height) : 18 Lamp
16 left_(left), 19};
17 top_(top), 20
18 width_(width), 21enum class Source {
19 height_(height), 22 None,
20 data_(width_*height_) 23 Dust,
21 { 24 Lamp,
25 Player
26};
27
28struct MapData {
29 Tile tile = Tile::Floor;
30 bool lit = false;
31 bool wasLit = false;
32 size_t dustLife = 0;
33 Source lightType = Source::None;
34 int lightRadius = 0;
35 std::set<coord> litTiles;
36 int renderId = -1;
37 bool dirtyRender = true;
38};
39
40struct Chunk {
41 std::array<MapData, CHUNK_WIDTH*CHUNK_HEIGHT> data;
42 int litTiles = 0;
43 int x;
44 int y;
45};
46
47inline void toChunkPos(int x, int y, int& cx, int& cy) {
48 cx = x / CHUNK_WIDTH;
49 cy = y / CHUNK_HEIGHT;
50 if (x < 0) {
51 cx *= -1;
52 cx--;
53 }
54 if (y < 0) {
55 cy *= -1;
56 cy--;
22 } 57 }
58}
59
60class Map {
61public:
23 62
24 inline int getLeft() const 63 inline int getLeft() const
25 { 64 {
@@ -69,27 +108,27 @@ public:
69 (y < top_ + height_); 108 (y < top_ + height_);
70 } 109 }
71 110
72 inline const T& at(int x, int y) const 111 inline const MapData& at(int x, int y) const
73 { 112 {
74 return data_.at((x - left_) + width_ * (y - top_)); 113 return loaded_.at((x - left_) + width_ * (y - top_));
75 } 114 }
76 115
77 inline T& at(int x, int y) 116 inline MapData& at(int x, int y)
78 { 117 {
79 return const_cast<T&>(static_cast<const Map&>(*this).at(x, y)); 118 return const_cast<MapData&>(static_cast<const Map&>(*this).at(x, y));
80 } 119 }
81 120
82 inline const std::vector<T>& data() const 121 inline const std::vector<MapData>& data() const
83 { 122 {
84 return data_; 123 return loaded_;
85 } 124 }
86 125
87 inline std::vector<T>& data() 126 inline std::vector<MapData>& data()
88 { 127 {
89 return data_; 128 return loaded_;
90 } 129 }
91 130
92 void resize(int newLeft, int newTop, int newWidth, int newHeight) 131 /*void resize(int newLeft, int newTop, int newWidth, int newHeight)
93 { 132 {
94 std::vector<T> newData(newWidth * newHeight); 133 std::vector<T> newData(newWidth * newHeight);
95 134
@@ -112,6 +151,96 @@ public:
112 width_ = newWidth; 151 width_ = newWidth;
113 height_ = newHeight; 152 height_ = newHeight;
114 data_.swap(newData); 153 data_.swap(newData);
154 }*/
155
156 void load(int newLeftChunk, int newTopChunk, int newWidthChunks, int newHeightChunks, std::mt19937& rng) {
157 // Flush the currently loaded data as long as there is any (this isn't the first load).
158 if (!loaded_.empty()) {
159 std::vector<size_t> touchedChunks;
160
161 for (int chunkY = 0; chunkY < chunksVert_; chunkY++) {
162 for (int chunkX = 0; chunkX < chunksHoriz_; chunkX++) {
163 size_t chunkIndex = chunkByPos_.at(leftmostChunk_ + chunkX).at(topmostChunk_ + chunkY);
164 touchedChunks.push_back(chunkIndex);
165
166 Chunk& chunk = chunks_.at(chunkIndex);
167 chunk.litTiles = 0;
168
169 int startX = chunkX * CHUNK_WIDTH;
170 int startY = chunkY * CHUNK_HEIGHT;
171 for (int y=0; y<CHUNK_HEIGHT; y++) {
172 for (int x=0; x<CHUNK_WIDTH; x++) {
173 chunk.data[x+y*CHUNK_WIDTH] = loaded_[startX+x+(startY+y)*width_];
174 if (chunk.data[x+y*CHUNK_WIDTH].lit) {
175 chunk.litTiles++;
176 }
177 }
178 }
179 }
180 }
181
182 // Destroy any completely unlit chunks.
183 for (size_t chunkIndex : touchedChunks) {
184 if (chunks_[chunkIndex].litTiles == 0) {
185 chunkByPos_[chunks_[chunkIndex].x].erase(chunks_[chunkIndex].y);
186 freeList_.push_back(chunkIndex);
187 }
188 }
189 }
190
191 leftmostChunk_ = newLeftChunk;
192 topmostChunk_ = newTopChunk;
193 chunksHoriz_ = newWidthChunks;
194 chunksVert_ = newHeightChunks;
195 left_ = newLeftChunk * CHUNK_WIDTH;
196 top_ = newTopChunk * CHUNK_HEIGHT;
197 width_ = chunksHoriz_ * CHUNK_WIDTH;
198 height_ = chunksVert_ * CHUNK_HEIGHT;
199 loaded_ = std::vector<MapData>(width_ * height_);
200
201 // Load in the requested chunks.
202 for (int chunkY = 0; chunkY < chunksVert_; chunkY++) {
203 for (int chunkX = 0; chunkX < chunksHoriz_; chunkX++) {
204 // Instantiate a new chunk if necessary.
205 if (!chunkByPos_[leftmostChunk_ + chunkX].count(topmostChunk_ + chunkY)) {
206 size_t chunkIndex;
207 if (!freeList_.empty()) {
208 chunkIndex = freeList_.front();
209 freeList_.pop_front();
210 } else {
211 chunkIndex = chunks_.size();
212 chunks_.emplace_back();
213 }
214 chunkByPos_[leftmostChunk_ + chunkX][topmostChunk_ + chunkY] = chunkIndex;
215
216 Chunk& chunk = chunks_[chunkIndex];
217 chunk.x = leftmostChunk_ + chunkX;
218 chunk.y = topmostChunk_ + chunkY;
219
220 for (MapData& md : chunk.data)
221 {
222 if (std::bernoulli_distribution(0.5)(rng))
223 {
224 md.tile = Tile::Wall;
225 } else {
226 md.tile = Tile::Floor;
227 }
228 md.dirtyRender = true;
229 }
230 }
231
232 size_t chunkIndex = chunkByPos_[leftmostChunk_ + chunkX][topmostChunk_ + chunkY];
233 Chunk& chunk = chunks_[chunkIndex];
234
235 for (int y = 0; y < CHUNK_HEIGHT; y++) {
236 std::copy(
237 std::next(std::begin(chunk.data), y*CHUNK_WIDTH),
238 std::next(std::begin(chunk.data), (y+1)*CHUNK_WIDTH),
239 std::next(std::begin(loaded_), (chunkY*CHUNK_HEIGHT + y)*width_ + chunkX*CHUNK_WIDTH));
240 }
241 }
242 }
243
115 } 244 }
116 245
117private: 246private:
@@ -120,8 +249,15 @@ private:
120 int top_; 249 int top_;
121 int width_; 250 int width_;
122 int height_; 251 int height_;
252 int leftmostChunk_;
253 int topmostChunk_;
254 int chunksHoriz_;
255 int chunksVert_;
256 std::vector<MapData> loaded_;
123 257
124 std::vector<T> data_; 258 std::vector<Chunk> chunks_;
259 std::list<size_t> freeList_;
260 std::map<int, std::map<int, size_t>> chunkByPos_; // chunkByPos_[X][Y]
125}; 261};
126 262
127#endif /* end of include guard: MAP_H_3AB00D12 */ 263#endif /* end of include guard: MAP_H_3AB00D12 */