feat: start of world generation
This commit is contained in:
parent
a55e08e1cc
commit
1f6be6b92b
|
@ -4,6 +4,7 @@
|
|||
#include "core/roguedefs.h"
|
||||
#include <SDL2/SDL_log.h>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
namespace rogue {
|
||||
|
@ -123,23 +124,83 @@ std::unique_ptr<World> 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> 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> &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> &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> &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),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<World> generate();
|
||||
private:
|
||||
Chunk select_start() const;
|
||||
void generate_world(std::unique_ptr<World> &world, Chunk start);
|
||||
void generate_room(std::unique_ptr<World> &world, Chunk last);
|
||||
void setup_player(std::unique_ptr<World> &world, Chunk spawn_chunk);
|
||||
private:
|
||||
std::optional<Character> player;
|
||||
int chunk_side_length{0}, world_side_length{0};
|
||||
|
|
Loading…
Reference in a new issue