Compare commits

..

2 commits

Author SHA1 Message Date
Sara 1f6be6b92b feat: start of world generation 2025-06-04 23:43:09 +02:00
Sara a55e08e1cc feat: added labeled case 2025-06-04 23:42:57 +02:00
3 changed files with 85 additions and 14 deletions

View file

@ -10,6 +10,10 @@ enum Directions : unsigned short {
WEST = 0x8, WEST = 0x8,
}; };
#define casel(M_switch, M_case)\
case M_case:\
M_switch##_case_##M_case
typedef SDL_Point Tile; typedef SDL_Point Tile;
typedef SDL_Point Chunk; typedef SDL_Point Chunk;
typedef unsigned Sprite; typedef unsigned Sprite;

View file

@ -4,6 +4,7 @@
#include "core/roguedefs.h" #include "core/roguedefs.h"
#include <SDL2/SDL_log.h> #include <SDL2/SDL_log.h>
#include <cassert> #include <cassert>
#include <cstdlib>
#include <memory> #include <memory>
namespace rogue { 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->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->world_side_length > 0 && "World size is required to generate world");
assert(this->player.has_value() && "World cannot be generated without a player"); assert(this->player.has_value() && "World cannot be generated without a player");
std::unique_ptr<World> world{new World()}; 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->characters.push_back(player.value());
world->player = &world->characters[0]; world->player = &world->characters[0];
world->player->world = world.get(); world->player->world = world.get();
world->chunk_size = this->chunk_side_length; world->player->location = {
world->shear = this->world_side_length; (spawn_chunk.x * this->chunk_side_length) + (this->chunk_side_length / 2),
world->rooms.reserve(this->world_side_length * this->world_side_length); (spawn_chunk.y * this->chunk_side_length) + (this->chunk_side_length / 2),
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;
} }
} }

View file

@ -20,6 +20,7 @@ struct Room {
// bitmask of hallways // bitmask of hallways
Directions hallway_paths{0}; Directions hallway_paths{0};
int chunk_size{0}; int chunk_size{0};
bool initialized{false};
// the starting tile and length of the walls // the starting tile and length of the walls
SDL_Rect rect{0, 0, 1, 1}; SDL_Rect rect{0, 0, 1, 1};
void draw(Tile pivot); void draw(Tile pivot);
@ -53,6 +54,11 @@ public:
WorldGenerator &with_room_size(unsigned min_side_length, unsigned max_side_length); WorldGenerator &with_room_size(unsigned min_side_length, unsigned max_side_length);
WorldGenerator &with_player(Character character); WorldGenerator &with_player(Character character);
std::unique_ptr<World> generate(); 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: private:
std::optional<Character> player; std::optional<Character> player;
int chunk_side_length{0}, world_side_length{0}; int chunk_side_length{0}, world_side_length{0};