From 7cd515fcfa1a5aac5605fcc63381033563fbf5d7 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Mon, 14 Mar 2022 14:11:05 -0400 Subject: map is now "infinite" using chunks that dynamically load like in diamond&pearl game is also slow as shit now --- src/map.h | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 160 insertions(+), 24 deletions(-) (limited to 'src/map.h') 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 @@ #include #include +#include +#include +#include +#include +#include "consts.h" -template -class Map { -public: +using coord = std::tuple; - Map( - int left, - int top, - int width, - int height) : - left_(left), - top_(top), - width_(width), - height_(height), - data_(width_*height_) - { +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 { @@ -69,27 +108,27 @@ public: (y < top_ + height_); } - inline const T& at(int x, int y) const + inline const MapData& at(int x, int y) const { - return data_.at((x - left_) + width_ * (y - top_)); + return loaded_.at((x - left_) + width_ * (y - top_)); } - inline T& at(int x, int y) + inline MapData& at(int x, int y) { - return const_cast(static_cast(*this).at(x, y)); + return const_cast(static_cast(*this).at(x, y)); } - inline const std::vector& data() const + inline const std::vector& data() const { - return data_; + return loaded_; } - inline std::vector& data() + inline std::vector& data() { - return data_; + return loaded_; } - void resize(int newLeft, int newTop, int newWidth, int newHeight) + /*void resize(int newLeft, int newTop, int newWidth, int newHeight) { std::vector newData(newWidth * newHeight); @@ -112,6 +151,96 @@ public: 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: @@ -120,8 +249,15 @@ private: int top_; int width_; int height_; + int leftmostChunk_; + int topmostChunk_; + int chunksHoriz_; + int chunksVert_; + std::vector loaded_; - std::vector data_; + std::vector chunks_; + std::list freeList_; + std::map> chunkByPos_; // chunkByPos_[X][Y] }; #endif /* end of include guard: MAP_H_3AB00D12 */ -- cgit 1.4.1