|
|
|
@ -22,22 +22,30 @@ void WorldBuilder::generate_map() { |
|
|
|
|
|
|
|
|
|
maze.hunt_and_kill(); |
|
|
|
|
|
|
|
|
|
$map.expand(); |
|
|
|
|
$map.enclose(); |
|
|
|
|
$map.load_tiles(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool WorldBuilder::find_open_spot(Point& pos_out) { |
|
|
|
|
// NOTE: still spawning near a player but not sure if this is the place
|
|
|
|
|
// to solve that. Idea: Get the player, don't place anything too close.
|
|
|
|
|
for(matrix::rando_rect it{$map.walls(), pos_out.x, pos_out.y, 3}; it.next();) { |
|
|
|
|
Point test{size_t(it.x), size_t(it.y)}; |
|
|
|
|
|
|
|
|
|
if($map.can_move(test) && !$collision.occupied(test)) { |
|
|
|
|
pos_out = test; |
|
|
|
|
return true; |
|
|
|
|
size_t i = 0; |
|
|
|
|
|
|
|
|
|
// horribly bad but I need to place things _somewhere_ so just fan out
|
|
|
|
|
for(i = 2; i < $map.width(); i++) { |
|
|
|
|
// rando_rect starts at the top/left corner not center
|
|
|
|
|
for(matrix::rando_box it{$map.walls(), pos_out.x, pos_out.y, i}; it.next();) { |
|
|
|
|
Point test{size_t(it.x), size_t(it.y)}; |
|
|
|
|
|
|
|
|
|
if($map.can_move(test) && !$collision.occupied(test)) { |
|
|
|
|
pos_out = test; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
matrix::dump("FAIL PLACE!", $map.walls(), pos_out.x, pos_out.y); |
|
|
|
|
|
|
|
|
|
dbc::sentinel(fmt::format("failed to place entity in the entire map?: i={}; width={};", i, $map.width())); |
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -137,17 +145,26 @@ void WorldBuilder::configure_starting_items(DinkyECS::World &world) { |
|
|
|
|
void WorldBuilder::place_entities(DinkyECS::World &world) { |
|
|
|
|
auto &config = world.get_the<GameConfig>(); |
|
|
|
|
// configure a player as a fact of the world
|
|
|
|
|
Position player_pos{0,0}; |
|
|
|
|
|
|
|
|
|
if(world.has_the<Player>()) { |
|
|
|
|
auto& player = world.get_the<Player>(); |
|
|
|
|
Point pos_out; |
|
|
|
|
bool placed = $map.place_entity(0, pos_out); |
|
|
|
|
dbc::check(placed, "failed to randomly place item in room"); |
|
|
|
|
world.set<Position>(player.entity, {pos_out.x+1, pos_out.y+1}); |
|
|
|
|
|
|
|
|
|
// first get a guess from the map
|
|
|
|
|
bool placed = $map.place_entity(0, player_pos.location); |
|
|
|
|
dbc::check(placed, "map.place_entity failed to position player"); |
|
|
|
|
|
|
|
|
|
// then use the collision map to place the player safely
|
|
|
|
|
placed = find_open_spot(player_pos.location); |
|
|
|
|
dbc::check(placed, "WorldBuild.find_open_spot also failed to position player"); |
|
|
|
|
|
|
|
|
|
world.set<Position>(player.entity, player_pos); |
|
|
|
|
} else { |
|
|
|
|
auto player_data = config.enemies["PLAYER_TILE"]; |
|
|
|
|
auto player_ent = configure_entity_in_room(world, player_data, 0); |
|
|
|
|
|
|
|
|
|
player_pos = world.get<Position>(player_ent); |
|
|
|
|
|
|
|
|
|
// configure player in the world
|
|
|
|
|
Player player{player_ent}; |
|
|
|
|
world.set_the<Player>(player); |
|
|
|
@ -158,6 +175,17 @@ void WorldBuilder::place_entities(DinkyECS::World &world) { |
|
|
|
|
world.make_constant(player.entity); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
dbc::check(player_pos.location.x != 0 && player_pos.location.y != 0, |
|
|
|
|
"failed to place the player correctly"); |
|
|
|
|
|
|
|
|
|
// make a dead zone around the player
|
|
|
|
|
auto& player = world.get_the<Player>(); |
|
|
|
|
for(matrix::box it{$map.walls(), player_pos.location.x, player_pos.location.y, 2}; |
|
|
|
|
it.next();) |
|
|
|
|
{ |
|
|
|
|
$collision.insert({it.x, it.y}, player.entity); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
randomize_entities(world, config); |
|
|
|
|
place_stairs(world, config); |
|
|
|
|
} |
|
|
|
|