#ifndef MAP_H_3AB00D12 #define MAP_H_3AB00D12 #include #include #include #include #include #include #include "consts.h" using coord = std::tuple; enum class Tile { Floor, Wall, Dust, Lamp }; enum class Source { None, Dust, Lamp, Player }; struct MapData { Tile tile = Tile::Floor; bool lit = false; bool wasLit = false; size_t dustLife = 0; Source lightType = Source::None; int lightRadius = 0; std::set litTiles; int renderId = -1; bool dirtyRender = true; }; struct Chunk { std::array data; int litTiles = 0; int x; int y; }; inline void toChunkPos(int x, int y, int& cx, int& cy) { cx = x / CHUNK_WIDTH; cy = y / CHUNK_HEIGHT; if (x < 0) { cx *= -1; cx--; } if (y < 0) { cy *= -1; cy--; } } class Map { public: inline int getLeft() const { return left_; } inline int getRight() const { return left_ + width_; } inline int getTop() const { return top_; } inline int getBottom() const { return top_ + height_; } inline int getWidth() const { return width_; } inline int getHeight() const { return height_; } inline int getTrueX(int x) const { return (x - left_); } inline int getTrueY(int y) const { return (y - top_); } inline bool inBounds(int x, int y) const { return (x >= left_) && (x < left_ + width_) && (y >= top_) && (y < top_ + height_); } inline const MapData& at(int x, int y) const { return loaded_.at((x - left_) + width_ * (y - top_)); } inline MapData& at(int x, int y) { return const_cast(static_cast(*this).at(x, y)); } inline const std::vector& data() const { return loaded_; } inline std::vector& data() { return loaded_; } /*void resize(int newLeft, int newTop, int newWidth, int newHeight) { std::vector newData(newWidth * newHeight); int winTop = std::max(top_, newTop); int winBottom = std::min(top_ + height_, newTop + newHeight); int winLeft = std::max(left_, newLeft); int winRight = std::min(left_ + width_, newLeft + newWidth); for (int y = winTop; y < winBottom; y++) { std::move( std::next(std::begin(data_), (winLeft - left_) + width_ * (y - top_)), std::next(std::begin(data_), (winRight - left_) + width_ * (y - top_)), std::next(std::begin(newData), (winLeft - newLeft) + newWidth * (y - newTop))); } left_ = newLeft; top_ = newTop; width_ = newWidth; height_ = newHeight; data_.swap(newData); }*/ void load(int newLeftChunk, int newTopChunk, int newWidthChunks, int newHeightChunks, std::mt19937& rng) { // Flush the currently loaded data as long as there is any (this isn't the first load). if (!loaded_.empty()) { std::vector touchedChunks; for (int chunkY = 0; chunkY < chunksVert_; chunkY++) { for (int chunkX = 0; chunkX < chunksHoriz_; chunkX++) { size_t chunkIndex = chunkByPos_.at(leftmostChunk_ + chunkX).at(topmostChunk_ + chunkY); touchedChunks.push_back(chunkIndex); Chunk& chunk = chunks_.at(chunkIndex); chunk.litTiles = 0; int startX = chunkX * CHUNK_WIDTH; int startY = chunkY * CHUNK_HEIGHT; for (int y=0; y(width_ * height_); // Load in the requested chunks. for (int chunkY = 0; chunkY < chunksVert_; chunkY++) { for (int chunkX = 0; chunkX < chunksHoriz_; chunkX++) { // Instantiate a new chunk if necessary. if (!chunkByPos_[leftmostChunk_ + chunkX].count(topmostChunk_ + chunkY)) { size_t chunkIndex; if (!freeList_.empty()) { chunkIndex = freeList_.front(); freeList_.pop_front(); } else { chunkIndex = chunks_.size(); chunks_.emplace_back(); } chunkByPos_[leftmostChunk_ + chunkX][topmostChunk_ + chunkY] = chunkIndex; Chunk& chunk = chunks_[chunkIndex]; chunk.x = leftmostChunk_ + chunkX; chunk.y = topmostChunk_ + chunkY; for (MapData& md : chunk.data) { if (std::bernoulli_distribution(0.5)(rng)) { md.tile = Tile::Wall; } else { md.tile = Tile::Floor; } md.dirtyRender = true; } } size_t chunkIndex = chunkByPos_[leftmostChunk_ + chunkX][topmostChunk_ + chunkY]; Chunk& chunk = chunks_[chunkIndex]; for (int y = 0; y < CHUNK_HEIGHT; y++) { std::copy( std::next(std::begin(chunk.data), y*CHUNK_WIDTH), std::next(std::begin(chunk.data), (y+1)*CHUNK_WIDTH), std::next(std::begin(loaded_), (chunkY*CHUNK_HEIGHT + y)*width_ + chunkX*CHUNK_WIDTH)); } } } } private: int left_; int top_; int width_; int height_; int leftmostChunk_; int topmostChunk_; int chunksHoriz_; int chunksVert_; std::vector loaded_; std::vector chunks_; std::list freeList_; std::map> chunkByPos_; // chunkByPos_[X][Y] }; #endif /* end of include guard: MAP_H_3AB00D12 */