diff --git a/src/core/world.cpp b/src/core/world.cpp index 6445d88..c9e598f 100644 --- a/src/core/world.cpp +++ b/src/core/world.cpp @@ -4,6 +4,7 @@ #include "core/roguedefs.h" #include #include +#include #include namespace rogue { @@ -123,23 +124,83 @@ std::unique_ptr WorldGenerator::generate() { assert(this->min_room_size < this->max_room_size && "Room size is required to generate world"); assert(this->world_side_length > 0 && "World size is required to generate world"); assert(this->player.has_value() && "World cannot be generated without a player"); + std::unique_ptr world{new World()}; + Chunk start_room{this->select_start()}; + this->setup_player(world, start_room); + return world; +} + +Chunk WorldGenerator::select_start() const { + Chunk start{0, 0}; + switch(std::rand() % 4) { + case 0: + start.y = this->world_side_length - 1; + case 1: + start.x = std::rand() % this->world_side_length; + break; + case 2: + start.x = this->world_side_length - 1; + case 3: + start.y = std::rand() % this->world_side_length; + break; + } + return start; +} + +void WorldGenerator::generate_world(std::unique_ptr &world, Chunk start) { + world->chunk_size = this->chunk_side_length; + world->shear = this->world_side_length; + world->rooms.resize(this->world_side_length * this->world_side_length); + for(Room &room : world->rooms) { + room = Room{ + .hallway_paths = Directions(0x0), + .chunk_size = this->chunk_side_length, + .rect = { + (this->chunk_side_length - this->max_room_size) / 2, + (this->chunk_side_length - this->max_room_size) / 2, + this->max_room_size, + this->max_room_size + } + }; + } + world->get_room(start).initialized = true; + this->generate_room(world, start); +} + +void WorldGenerator::generate_room(std::unique_ptr &world, Chunk last) { + static const Chunk options[]{ + {last.x + 1, last.y}, + {last.x - 1, last.y}, + {last.x, last.y + 1}, + {last.x, last.y - 1} + }; + static const Directions directions[]{ + EAST, WEST, SOUTH, NORTH + }; + for(size_t i{0}; i < 4; ++i) { + Chunk next{options[i]}; + Room &option{world->get_room(next)}; + if(options[i].x < 0 || options[i].x >= this->world_side_length + || options[i].y < 0 || options[i].y >= this->world_side_length) { + continue; + } else if(option.initialized) { + continue; + } + // register hallway with the last chunk + option.hallway_paths = Directions(option.hallway_paths | directions[i]); + // generate random rect that encloses center of chunk + // add hallway to the new chunk + } +} + +void WorldGenerator::setup_player(std::unique_ptr &world, Chunk spawn_chunk) { world->characters.push_back(player.value()); world->player = &world->characters[0]; world->player->world = world.get(); - world->chunk_size = this->chunk_side_length; - world->shear = this->world_side_length; - world->rooms.reserve(this->world_side_length * this->world_side_length); - world->rooms.push_back(Room { - .hallway_paths = Directions(Directions::NORTH | Directions::EAST), - .chunk_size = this->chunk_side_length, - .rect = { - (this->chunk_side_length - this->max_room_size) / 2, - (this->chunk_side_length - this->max_room_size) / 2, - this->max_room_size, - this->max_room_size - } - }); - return world; + world->player->location = { + (spawn_chunk.x * this->chunk_side_length) + (this->chunk_side_length / 2), + (spawn_chunk.y * this->chunk_side_length) + (this->chunk_side_length / 2), + }; } } diff --git a/src/core/world.h b/src/core/world.h index a9f38d5..1245131 100644 --- a/src/core/world.h +++ b/src/core/world.h @@ -20,6 +20,7 @@ struct Room { // bitmask of hallways Directions hallway_paths{0}; int chunk_size{0}; + bool initialized{false}; // the starting tile and length of the walls SDL_Rect rect{0, 0, 1, 1}; void draw(Tile pivot); @@ -53,6 +54,11 @@ public: WorldGenerator &with_room_size(unsigned min_side_length, unsigned max_side_length); WorldGenerator &with_player(Character character); std::unique_ptr generate(); +private: + Chunk select_start() const; + void generate_world(std::unique_ptr &world, Chunk start); + void generate_room(std::unique_ptr &world, Chunk last); + void setup_player(std::unique_ptr &world, Chunk spawn_chunk); private: std::optional player; int chunk_side_length{0}, world_side_length{0};