Fixed up the map generator so that it's placing entities in non-overlapping tiles and adapting the style for the size. It can also deal with maps that have no rooms better and places the stairs better.
This commit is contained in:
parent
5f1a453fb4
commit
4eaf3c35d6
11 changed files with 55 additions and 45 deletions
|
@ -14,21 +14,6 @@
|
|||
{"_type": "Sound", "attack": "pickup", "death": "blank"}
|
||||
]
|
||||
},
|
||||
"SWORD_RUSTY": {
|
||||
"id": "SWORD_RUSTY",
|
||||
"name": "Rusty Junk Sword",
|
||||
"description": "A sword left to rot in a deep hole where it acquired a patina of dirt and tetanus. You aren't sure if it's more deadly for you to hold it or for the people you stab with it.",
|
||||
"inventory_count": 1,
|
||||
"components": [
|
||||
{"_type": "Weapon", "damage": 15},
|
||||
{"_type": "Tile", "display": 7735,
|
||||
"foreground": [24, 120, 189],
|
||||
"background": [24, 120, 189]
|
||||
},
|
||||
{"_type": "Sprite", "name": "cinqueda", "width": 256, "height": 256, "scale": 1.0},
|
||||
{"_type": "Sound", "attack": "pickup", "death": "blank"}
|
||||
]
|
||||
},
|
||||
"BARREL_SMALL": {
|
||||
"id": "BARREL_SMALL",
|
||||
"name": "Small Barrel",
|
||||
|
|
|
@ -15,9 +15,9 @@ Point CameraLOL::plan_move(int dir, bool strafe) {
|
|||
return {size_t(target_x), size_t(target_y)};
|
||||
}
|
||||
|
||||
void CameraLOL::plan_rotate(int dir) {
|
||||
void CameraLOL::plan_rotate(int dir, float amount) {
|
||||
t = 0.0;
|
||||
double angle_dir = std::numbers::pi * 0.25 * dir;
|
||||
double angle_dir = std::numbers::pi * amount * float(dir);
|
||||
|
||||
target_dir_x = rayview.$dir_x * cos(angle_dir) - rayview.$dir_y * sin(angle_dir);
|
||||
target_dir_y = rayview.$dir_x * sin(angle_dir) + rayview.$dir_y * cos(angle_dir);
|
||||
|
|
|
@ -17,7 +17,7 @@ struct CameraLOL {
|
|||
rayview(rv) {}
|
||||
|
||||
Point plan_move(int dir, bool strafe);
|
||||
void plan_rotate(int dir);
|
||||
void plan_rotate(int dir, float amount=0.5f);
|
||||
|
||||
bool play_rotate();
|
||||
bool play_move();
|
||||
|
|
|
@ -60,6 +60,8 @@ constexpr int COMBAT_UI_Y = RAY_VIEW_HEIGHT;
|
|||
constexpr int COMBAT_UI_WIDTH = RAY_VIEW_WIDTH ;
|
||||
constexpr int COMBAT_UI_HEIGHT = SCREEN_HEIGHT - RAY_VIEW_HEIGHT;
|
||||
|
||||
constexpr int INITIAL_MAP_W = 17;
|
||||
constexpr int INITIAL_MAP_H = 15;
|
||||
|
||||
// for the panels/renderer
|
||||
constexpr wchar_t BG_TILE = L'█';
|
||||
|
|
|
@ -152,11 +152,11 @@ namespace gui {
|
|||
try_move(1, true);
|
||||
break;
|
||||
case ROTATE_LEFT:
|
||||
$main_ui.plan_rotate(-1);
|
||||
$main_ui.plan_rotate(-1, 0.5f);
|
||||
state(State::ROTATING);
|
||||
break;
|
||||
case ROTATE_RIGHT:
|
||||
$main_ui.plan_rotate(1);
|
||||
$main_ui.plan_rotate(1, 0.5f);
|
||||
state(State::ROTATING);
|
||||
break;
|
||||
case MAP_OPEN:
|
||||
|
@ -356,7 +356,7 @@ namespace gui {
|
|||
if($map_open) {
|
||||
$map_ui.render($window, $main_ui.$compass_dir);
|
||||
} else {
|
||||
// $mini_map.render($window, $main_ui.$compass_dir);
|
||||
$mini_map.render($window, $main_ui.$compass_dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,10 +77,11 @@ namespace gui {
|
|||
}
|
||||
}
|
||||
|
||||
void MainUI::plan_rotate(int dir) {
|
||||
void MainUI::plan_rotate(int dir, float amount) {
|
||||
// -1 is left, 1 is right
|
||||
$compass_dir = ($compass_dir + dir) % COMPASS.size();
|
||||
$camera.plan_rotate(dir);
|
||||
int extra = (amount == 0.5) * dir;
|
||||
$compass_dir = ($compass_dir + dir + extra) % COMPASS.size();
|
||||
$camera.plan_rotate(dir, amount);
|
||||
}
|
||||
|
||||
Point MainUI::plan_move(int dir, bool strafe) {
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace gui {
|
|||
void debug();
|
||||
void render_debug();
|
||||
|
||||
void plan_rotate(int dir);
|
||||
void plan_rotate(int dir, float amount=0.5f);
|
||||
bool play_rotate();
|
||||
std::optional<Point> play_move();
|
||||
Point plan_move(int dir, bool strafe);
|
||||
|
|
|
@ -17,8 +17,8 @@ LevelManager::LevelManager() {
|
|||
|
||||
LevelScaling LevelManager::scale_level() {
|
||||
return {
|
||||
21,
|
||||
21
|
||||
INITIAL_MAP_W + int($current_level * 2),
|
||||
INITIAL_MAP_H + int($current_level * 2)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
4
maze.cpp
4
maze.cpp
|
@ -95,9 +95,6 @@ namespace maze {
|
|||
}
|
||||
|
||||
void Builder::randomize_rooms() {
|
||||
dbc::check($dead_ends.size() >= 2, "must have at least two possible points to place rooms");
|
||||
|
||||
while($rooms.size() < 2) {
|
||||
// use those dead ends to randomly place rooms
|
||||
for(auto at : $dead_ends) {
|
||||
if(Random::uniform(0,1)) {
|
||||
|
@ -107,7 +104,6 @@ namespace maze {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Builder::init() {
|
||||
matrix::assign($walls, WALL_VALUE);
|
||||
|
|
|
@ -12,21 +12,41 @@ using namespace components;
|
|||
|
||||
void WorldBuilder::generate_map() {
|
||||
maze::Builder maze($map);
|
||||
size_t x_diff = $map.width() / 4;
|
||||
size_t y_diff = $map.height() / 4;
|
||||
|
||||
maze.divide({x_diff, y_diff}, {$map.width() - x_diff, $map.height() - y_diff});
|
||||
maze.hunt_and_kill();
|
||||
maze.randomize_rooms();
|
||||
|
||||
dbc::check($map.$dead_ends.size() > 0, "world builder/maze builder made a map with no dead ends.");
|
||||
if($map.width() > 20) {
|
||||
maze.inner_box(4, 2);
|
||||
}
|
||||
|
||||
maze.hunt_and_kill();
|
||||
|
||||
$map.expand();
|
||||
$map.load_tiles();
|
||||
}
|
||||
|
||||
DinkyECS::Entity WorldBuilder::configure_entity_in_map(DinkyECS::World &world, json &entity_data, Point pos_out) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DinkyECS::Entity WorldBuilder::configure_entity_in_map(DinkyECS::World &world, json &entity_data, Point pos) {
|
||||
bool found = find_open_spot(pos);
|
||||
dbc::check(found, "Failed to find a place for this thing.");
|
||||
|
||||
auto item = world.entity();
|
||||
world.set<Position>(item, {pos_out.x+1, pos_out.y+1});
|
||||
world.set<Position>(item, {pos.x, pos.y});
|
||||
|
||||
if(entity_data["inventory_count"] > 0) {
|
||||
world.set<InventoryItem>(item, {entity_data["inventory_count"], entity_data});
|
||||
|
@ -36,6 +56,8 @@ DinkyECS::Entity WorldBuilder::configure_entity_in_map(DinkyECS::World &world, j
|
|||
components::configure_entity($components, world, item, entity_data["components"]);
|
||||
}
|
||||
|
||||
$collision.insert(pos, item);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
|
@ -97,8 +119,9 @@ void WorldBuilder::randomize_entities(DinkyECS::World &world, GameConfig &config
|
|||
void WorldBuilder::place_stairs(DinkyECS::World& world, GameConfig& config) {
|
||||
auto& device_config = config.devices.json();
|
||||
auto entity_data = device_config["STAIRS_DOWN"];
|
||||
int last_room = $map.room_count() - 1;
|
||||
configure_entity_in_room(world, entity_data, last_room);
|
||||
|
||||
auto at_end = $map.$dead_ends.back();
|
||||
configure_entity_in_map(world, entity_data, at_end);
|
||||
}
|
||||
|
||||
void WorldBuilder::configure_starting_items(DinkyECS::World &world) {
|
||||
|
|
|
@ -3,11 +3,13 @@
|
|||
#include "map.hpp"
|
||||
#include "dinkyecs.hpp"
|
||||
#include "components.hpp"
|
||||
#include "spatialmap.hpp"
|
||||
|
||||
class WorldBuilder {
|
||||
public:
|
||||
Map& $map;
|
||||
components::ComponentMap& $components;
|
||||
SpatialMap $collision;
|
||||
|
||||
WorldBuilder(Map &map, components::ComponentMap& components) :
|
||||
$map(map),
|
||||
|
@ -20,6 +22,7 @@ class WorldBuilder {
|
|||
|
||||
DinkyECS::Entity configure_entity_in_room(DinkyECS::World &world, nlohmann::json &entity_data, int in_room);
|
||||
|
||||
bool find_open_spot(Point& pos_out);
|
||||
void place_entities(DinkyECS::World &world);
|
||||
void generate(DinkyECS::World &world);
|
||||
void randomize_entities(DinkyECS::World &world, components::GameConfig &config);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue