BROKEN: Big refactoring happening, so it compiles but game does not run and the tests fail.
This commit is contained in:
parent
96efc990c1
commit
9e91c71125
25 changed files with 128 additions and 526 deletions
|
@ -9,8 +9,8 @@
|
|||
"inventory_count": 0,
|
||||
"randomized": false,
|
||||
"components": [
|
||||
{"type": "Tile", "config": {"chr": "\u2ac5"}},
|
||||
{"type": "Device",
|
||||
{"_type": "Tile", "config": {"chr": "\u2ac5"}},
|
||||
{"_type": "Device",
|
||||
"config": {"test": true}, "events": ["Events::GUI::STAIRS_DOWN"]
|
||||
}
|
||||
]
|
||||
|
@ -24,8 +24,8 @@
|
|||
"inventory_count": 0,
|
||||
"placement": "fixed",
|
||||
"components": [
|
||||
{"type": "Tile", "config": {"chr": "\u2259"}},
|
||||
{"type": "Device",
|
||||
{"_type": "Tile", "config": {"chr": "\u2259"}},
|
||||
{"_type": "Device",
|
||||
"config": {"test": true}, "events": ["Events::GUI::STAIRS_UP"]
|
||||
}
|
||||
]
|
||||
|
@ -38,8 +38,8 @@
|
|||
"description": "Spikes stab you from the floor.",
|
||||
"inventory_count": 0,
|
||||
"components": [
|
||||
{"type": "Tile", "config": {"chr": "\u1ac7"}},
|
||||
{"type": "Device",
|
||||
{"_type": "Tile", "config": {"chr": "\u1ac7"}},
|
||||
{"_type": "Device",
|
||||
"config": {"test": true}, "events": ["Events::GUI::TRAP"]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -3,21 +3,21 @@
|
|||
"foreground": [255, 200, 125],
|
||||
"background": [30, 20, 75],
|
||||
"components": [
|
||||
{"type": "Tile", "config": {"chr": "\ua66b"}},
|
||||
{"type": "Combat", "config": {"hp": 200, "damage": 15}},
|
||||
{"type": "Motion", "config": {"dx": 0, "dy": 0, "random": false}},
|
||||
{"type": "LightSource", "config": {"strength": 70, "radius": 2}},
|
||||
{"type": "EnemyConfig", "config": {"hearing_distance": 5}}
|
||||
{"_type": "Tile", "config": {"chr": "\ua66b"}},
|
||||
{"_type": "Combat", "config": {"hp": 200, "damage": 15}},
|
||||
{"_type": "Motion", "config": {"dx": 0, "dy": 0, "random": false}},
|
||||
{"_type": "LightSource", "config": {"strength": 70, "radius": 2}},
|
||||
{"_type": "EnemyConfig", "config": {"hearing_distance": 5}}
|
||||
]
|
||||
},
|
||||
"EVIL_EYE": {
|
||||
"foreground": [75, 200, 125],
|
||||
"background": [30, 20, 75],
|
||||
"components": [
|
||||
{"type": "Tile", "config": {"chr": "\u08ac"}},
|
||||
{"type": "Combat", "config": {"hp": 100, "damage": 50}},
|
||||
{"type": "Motion", "config": {"dx": 0, "dy": 0, "random": false}},
|
||||
{"type": "EnemyConfig", "config": {"hearing_distance": 10}}
|
||||
{"_type": "Tile", "config": {"chr": "\u08ac"}},
|
||||
{"_type": "Combat", "config": {"hp": 100, "damage": 50}},
|
||||
{"_type": "Motion", "config": {"dx": 0, "dy": 0, "random": false}},
|
||||
{"_type": "EnemyConfig", "config": {"hearing_distance": 10}}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
"description": "A torch that barely lights the way. You wonder if it'd be better to not see the person who murders you.",
|
||||
"inventory_count": 1,
|
||||
"components": [
|
||||
{"type": "LightSource", "config": {"strength": 70, "radius": 2.0}},
|
||||
{"type": "Tile", "config": {"chr": "\u0f08"}}
|
||||
{"_type": "LightSource", "config": {"strength": 70, "radius": 2.0}},
|
||||
{"_type": "Tile", "config": {"chr": "\u0f08"}}
|
||||
]
|
||||
},
|
||||
"SWORD_RUSTY": {
|
||||
|
@ -19,8 +19,8 @@
|
|||
"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", "config": {"damage": 15}},
|
||||
{"type": "Tile", "config": {"chr": "\u1e37"}}
|
||||
{"_type": "Weapon", "config": {"damage": 15}},
|
||||
{"_type": "Tile", "config": {"chr": "\u1e37"}}
|
||||
]
|
||||
},
|
||||
"SWORD_LIGHT_AND_FLAME": {
|
||||
|
@ -31,9 +31,9 @@
|
|||
"description": "A sword so powerful, a great man from the Land of The Rising Sun thrust it into the ocean of Nerf to chill its effects.",
|
||||
"inventory_count": 1,
|
||||
"components": [
|
||||
{"type": "LightSource", "config": {"strength": 70, "radius": 1.8}},
|
||||
{"type": "Tile", "config": {"chr": "\u0236"}},
|
||||
{"type": "Weapon", "config": {"damage": 30}}
|
||||
{"_type": "LightSource", "config": {"strength": 70, "radius": 1.8}},
|
||||
{"_type": "Tile", "config": {"chr": "\u0236"}},
|
||||
{"_type": "Weapon", "config": {"damage": 30}}
|
||||
]
|
||||
},
|
||||
"CHEST_SMALL": {
|
||||
|
@ -43,8 +43,8 @@
|
|||
"background": [150, 100, 189],
|
||||
"description": "A small chest of gold. You wonder who would leave something like this around.",
|
||||
"components": [
|
||||
{"type": "Tile", "config": {"chr": "\uaaea"}},
|
||||
{"type": "Loot", "config": {"amount": 10}}
|
||||
{"_type": "Tile", "config": {"chr": "\uaaea"}},
|
||||
{"_type": "Loot", "config": {"amount": 10}}
|
||||
],
|
||||
"inventory_count": 1
|
||||
},
|
||||
|
@ -56,8 +56,8 @@
|
|||
"description": "A torch on a wall you can't pick up.",
|
||||
"inventory_count": 0,
|
||||
"components": [
|
||||
{"type": "Tile", "config": {"chr": "\u077e"}},
|
||||
{"type": "LightSource", "config": {"strength": 60, "radius": 1.8}}
|
||||
{"_type": "Tile", "config": {"chr": "\u077e"}},
|
||||
{"_type": "LightSource", "config": {"strength": 60, "radius": 1.8}}
|
||||
]
|
||||
},
|
||||
"POTION_HEALING_SMALL": {
|
||||
|
@ -68,8 +68,8 @@
|
|||
"description": "A small healing potion.",
|
||||
"inventory_count": 1,
|
||||
"components": [
|
||||
{"type": "Tile", "config": {"chr": "\u03eb"}},
|
||||
{"type": "Curative", "config": {"hp": 20}}
|
||||
{"_type": "Tile", "config": {"chr": "\u03eb"}},
|
||||
{"_type": "Curative", "config": {"hp": 20}}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
#include "components.hpp"
|
||||
|
||||
namespace components {
|
||||
void configure(DinkyECS::World &world, DinkyECS::Entity entity, json& entity_data) {
|
||||
for(auto &comp : entity_data["components"]) {
|
||||
json& config = comp["config"];
|
||||
const string comp_type = comp["type"];
|
||||
|
||||
if(comp_type == "Weapon") {
|
||||
world.set<Weapon>(entity, {config["damage"]});
|
||||
} else if(comp_type == "LightSource") {
|
||||
world.set<LightSource>(entity, {config["strength"], config["radius"]});
|
||||
} else if(comp_type == "Loot") {
|
||||
world.set<Loot>(entity, {config["amount"]});
|
||||
} else if(comp_type == "Tile") {
|
||||
world.set<Tile>(entity, {
|
||||
config["chr"],
|
||||
entity_data["foreground"][0],
|
||||
entity_data["foreground"][1],
|
||||
entity_data["foreground"][2],
|
||||
entity_data["background"][0],
|
||||
entity_data["background"][1],
|
||||
entity_data["background"][2]});
|
||||
|
||||
} else if(comp_type == "EnemyConfig") {
|
||||
world.set<EnemyConfig>(entity, {config["hearing_distance"]});
|
||||
} else if(comp_type == "Combat") {
|
||||
world.set<Combat>(entity, {config["hp"], config["damage"]});
|
||||
} else if(comp_type == "Curative") {
|
||||
world.set<Curative>(entity, {config["hp"]});
|
||||
} else if(comp_type == "Motion") {
|
||||
world.set<Motion>(entity, {config["dx"], config["dy"], config["random"]});
|
||||
} else if(comp_type == "Device") {
|
||||
Device device{.config=config, .events={}};
|
||||
device.configure_events(comp["events"]);
|
||||
world.set<Device>(entity, device);
|
||||
} else {
|
||||
dbc::sentinel(fmt::format("ITEM COMPONENT TYPE MISSING: {}",
|
||||
std::string(comp_type)));
|
||||
}
|
||||
|
||||
// json config variable dies
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,43 +3,38 @@
|
|||
#include "devices.hpp"
|
||||
#include "combat.hpp"
|
||||
#include "inventory.hpp"
|
||||
#include "tser.hpp"
|
||||
#include "config.hpp"
|
||||
|
||||
namespace components {
|
||||
|
||||
struct Player {
|
||||
DinkyECS::Entity entity;
|
||||
DEFINE_SERIALIZABLE(Player, entity);
|
||||
};
|
||||
|
||||
struct Position {
|
||||
Point location;
|
||||
DEFINE_SERIALIZABLE(Position, location);
|
||||
};
|
||||
|
||||
struct Motion {
|
||||
int dx;
|
||||
int dy;
|
||||
bool random=false;
|
||||
DEFINE_SERIALIZABLE(Motion, dx, dy);
|
||||
};
|
||||
|
||||
struct Loot {
|
||||
int amount;
|
||||
DEFINE_SERIALIZABLE(Loot, amount);
|
||||
};
|
||||
|
||||
struct Tile {
|
||||
std::string chr;
|
||||
std::array<uint8_t, 3> foreground;
|
||||
std::array<uint8_t, 3> background;
|
||||
uint8_t fg_h = 200;
|
||||
uint8_t fg_s = 20;
|
||||
uint8_t fg_v = 200;
|
||||
uint8_t bg_h = 100;
|
||||
uint8_t bg_s = 20;
|
||||
uint8_t bg_v = 0;
|
||||
|
||||
DEFINE_SERIALIZABLE(Tile, chr);
|
||||
};
|
||||
|
||||
struct GameConfig {
|
||||
|
@ -66,6 +61,13 @@ namespace components {
|
|||
struct Curative {
|
||||
int hp = 10;
|
||||
};
|
||||
|
||||
void configure(DinkyECS::World &world, DinkyECS::Entity entity, json& entity_data);
|
||||
}
|
||||
|
||||
DINKY_HAS_COMPONENT(components::Loot, amount);
|
||||
DINKY_HAS_COMPONENT(Point, x, y);
|
||||
DINKY_HAS_COMPONENT(components::Position, location);
|
||||
DINKY_HAS_COMPONENT(components::Weapon, damage);
|
||||
DINKY_HAS_COMPONENT(components::Curative, hp);
|
||||
DINKY_HAS_COMPONENT(components::EnemyConfig, hearing_distance);
|
||||
DINKY_HAS_COMPONENT(components::Tile, chr, foreground, background);
|
||||
DINKY_HAS_COMPONENT(components::Motion, dx, dy, random);
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
#include "dinkyecs.hpp"
|
||||
#include "dbc.hpp"
|
||||
#include <fmt/core.h>
|
||||
|
||||
namespace DinkyECS {
|
||||
void configure(World& world, const ComponentMap& component_map, Entity ent, json& data) {
|
||||
void configure(const ComponentMap& component_map, World& world, Entity ent, json& data) {
|
||||
for (auto &i : data) {
|
||||
assert(i.contains("_type") && i["_type"].is_string());
|
||||
assert(component_map.contains(i["_type"]));
|
||||
dbc::check(i.contains("_type") && i["_type"].is_string(), fmt::format("component has no _type: {}", data.dump()));
|
||||
dbc::check(component_map.contains(i["_type"]), fmt::format("component_map doesn't have type {}", std::string(i["_type"])));
|
||||
component_map.at(i["_type"])(world, ent, i);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -178,6 +178,6 @@ namespace DinkyECS {
|
|||
};
|
||||
}
|
||||
|
||||
void configure(World& world, const ComponentMap& component_map, Entity ent, json& data);
|
||||
void configure(const ComponentMap& component_map, World& world, Entity ent, json& data);
|
||||
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ size_t LevelManager::create_level(shared_ptr<DinkyECS::World> prev_world) {
|
|||
auto scaling = scale_level();
|
||||
|
||||
auto map = make_shared<Map>(scaling.map_width, scaling.map_height);
|
||||
WorldBuilder builder(*map);
|
||||
WorldBuilder builder(*map, $components);
|
||||
builder.generate(*world);
|
||||
|
||||
size_t index = $levels.size();
|
||||
|
|
|
@ -24,6 +24,7 @@ struct LevelScaling {
|
|||
|
||||
class LevelManager {
|
||||
public:
|
||||
DinkyECS::ComponentMap $components;
|
||||
std::vector<GameLevel> $levels;
|
||||
size_t $current_level = 0;
|
||||
|
||||
|
|
3
map.hpp
3
map.hpp
|
@ -6,7 +6,6 @@
|
|||
#include <algorithm>
|
||||
#include <fmt/core.h>
|
||||
#include "point.hpp"
|
||||
#include "tser.hpp"
|
||||
#include "lights.hpp"
|
||||
#include "pathing.hpp"
|
||||
#include "matrix.hpp"
|
||||
|
@ -22,8 +21,6 @@ struct Room {
|
|||
size_t height = 0;
|
||||
Point entry{(size_t)-1, (size_t)-1};
|
||||
Point exit{(size_t)-1, (size_t)-1};
|
||||
|
||||
DEFINE_SERIALIZABLE(Room, x, y, width, height);
|
||||
};
|
||||
|
||||
class Map {
|
||||
|
|
|
@ -47,7 +47,6 @@ sources = [
|
|||
'ansi_parser.cpp',
|
||||
'camera.cpp',
|
||||
'combat.cpp',
|
||||
'components.cpp',
|
||||
'config.cpp',
|
||||
'dbc.cpp',
|
||||
'devices.cpp',
|
||||
|
@ -87,7 +86,6 @@ executable('runtests', sources + [
|
|||
'tests/pathing.cpp',
|
||||
'tests/spatialmap.cpp',
|
||||
'tests/tilemap.cpp',
|
||||
'tests/worldbuilder.cpp',
|
||||
], override_options: exe_defaults,
|
||||
dependencies: dependencies + [catch2])
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include "tser.hpp"
|
||||
|
||||
struct Point {
|
||||
size_t x = 0;
|
||||
|
@ -9,8 +8,6 @@ struct Point {
|
|||
bool operator==(const Point& other) const {
|
||||
return other.x == x && other.y == y;
|
||||
}
|
||||
|
||||
DEFINE_SERIALIZABLE(Point, x, y);
|
||||
};
|
||||
|
||||
typedef std::vector<Point> PointList;
|
||||
|
|
66
save.cpp
66
save.cpp
|
@ -17,70 +17,16 @@ inline void extract(DinkyECS::World &world, std::map<DinkyECS::Entity, CompT> &i
|
|||
}
|
||||
|
||||
void save::to_file(fs::path path, DinkyECS::World &world, Map &map) {
|
||||
SaveData save_data;
|
||||
tser::BinaryArchive archive;
|
||||
|
||||
save_data.facts.player = world.get_the<Player>();
|
||||
save_data.map = MapData{
|
||||
map.$width, map.$height,
|
||||
map.$rooms, map.$walls};
|
||||
|
||||
// BUG: lights aren't saved/restored
|
||||
extract<Position>(world, save_data.position);
|
||||
extract<Combat>(world, save_data.combat);
|
||||
extract<Motion>(world, save_data.motion);
|
||||
extract<Tile>(world, save_data.tile);
|
||||
// extract<Inventory>(world, save_data.inventory);
|
||||
|
||||
archive.save(save_data);
|
||||
std::string_view archive_view = archive.get_buffer();
|
||||
|
||||
std::ofstream out(path, std::ios::binary);
|
||||
out << archive_view;
|
||||
out.flush();
|
||||
(void)path;
|
||||
(void)world;
|
||||
(void)map;
|
||||
}
|
||||
|
||||
template<typename CompT>
|
||||
inline void inject(DinkyECS::World &world, std::map<DinkyECS::Entity, CompT> &outof) {
|
||||
for(auto [entity, value] : outof) {
|
||||
world.set<CompT>(entity, value);
|
||||
}
|
||||
}
|
||||
|
||||
void save::from_file(fs::path path, DinkyECS::World &world_out, Map &map_out) {
|
||||
tser::BinaryArchive archive(0);
|
||||
dbc::check(fs::exists(path), format("save file does not exist {}", path.string()));
|
||||
auto size = fs::file_size(path);
|
||||
|
||||
if(std::ifstream in_file{path, std::ios::binary}) {
|
||||
std::string in_data(size, '\0');
|
||||
|
||||
if(in_file.read(&in_data[0], size)) {
|
||||
std::string_view in_view(in_data);
|
||||
archive.initialize(in_view);
|
||||
} else {
|
||||
dbc::sentinel(format("wrong size or error reading {}", path.string()));
|
||||
}
|
||||
} else {
|
||||
dbc::sentinel(format("failed to load file {}", path.string()));
|
||||
}
|
||||
|
||||
auto save_data = archive.load<SaveData>();
|
||||
|
||||
world_out.set_the<Player>(save_data.facts.player);
|
||||
inject<Position>(world_out, save_data.position);
|
||||
inject<Combat>(world_out, save_data.combat);
|
||||
inject<Motion>(world_out, save_data.motion);
|
||||
inject<Tile>(world_out, save_data.tile);
|
||||
// inject<Inventory>(world_out, save_data.inventory);
|
||||
|
||||
size_t width = save_data.map.width;
|
||||
size_t height = save_data.map.height;
|
||||
|
||||
Pathing paths(width, height);
|
||||
map_out = Map(save_data.map.walls, paths);
|
||||
|
||||
save::load_configs(world_out);
|
||||
(void)path;
|
||||
(void)world_out;
|
||||
(void)map_out;
|
||||
}
|
||||
|
||||
void save::load_configs(DinkyECS::World &world) {
|
||||
|
|
7
save.hpp
7
save.hpp
|
@ -3,7 +3,6 @@
|
|||
#include "components.hpp"
|
||||
#include "map.hpp"
|
||||
#include "dinkyecs.hpp"
|
||||
#include "tser.hpp"
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
@ -16,14 +15,10 @@ namespace save {
|
|||
size_t height;
|
||||
std::vector<Room> rooms;
|
||||
Matrix walls;
|
||||
|
||||
DEFINE_SERIALIZABLE(MapData, width, height, rooms, walls);
|
||||
};
|
||||
|
||||
struct Facts {
|
||||
components::Player player;
|
||||
|
||||
DEFINE_SERIALIZABLE(Facts, player);
|
||||
};
|
||||
|
||||
struct SaveData {
|
||||
|
@ -35,8 +30,6 @@ namespace save {
|
|||
std::map<DinkyECS::Entity, components::Combat> combat;
|
||||
std::map<DinkyECS::Entity, components::Tile> tile;
|
||||
// std::map<DinkyECS::Entity, components::Inventory> inventory;
|
||||
|
||||
DEFINE_SERIALIZABLE(SaveData, facts, map, position, motion, combat, tile);
|
||||
};
|
||||
|
||||
void to_file(fs::path path, DinkyECS::World &world, Map &map);
|
||||
|
|
|
@ -234,8 +234,8 @@ TEST_CASE("test serialization with nlohmann::json", "[ecs-serialize]") {
|
|||
DinkyECS::Entity ent1 = world.entity();
|
||||
DinkyECS::Entity ent2 = world.entity();
|
||||
|
||||
DinkyECS::configure(world, component_map, ent1, data);
|
||||
DinkyECS::configure(world, component_map, ent2, data);
|
||||
DinkyECS::configure(component_map, world, ent1, data);
|
||||
DinkyECS::configure(component_map, world, ent2, data);
|
||||
|
||||
world.query<Position, Motion>([&](const auto ent, auto &pos, auto &motion) {
|
||||
fmt::println("entity: {}; position={},{} and motion={},{} motion.random={}",
|
||||
|
|
|
@ -15,15 +15,18 @@ using std::string;
|
|||
using namespace components;
|
||||
|
||||
|
||||
DinkyECS::Entity add_items(DinkyECS::World &world, GameConfig &config) {
|
||||
DinkyECS::Entity add_items(DinkyECS::ComponentMap component_map, DinkyECS::World &world, GameConfig &config) {
|
||||
auto sword = world.entity();
|
||||
json& item_data = config.items["SWORD_RUSTY"];
|
||||
world.set<InventoryItem>(sword, {item_data["inventory_count"], item_data});
|
||||
components::configure(world, sword, item_data);
|
||||
DinkyECS::configure(component_map, world, sword, item_data);
|
||||
return sword;
|
||||
}
|
||||
|
||||
TEST_CASE("basic inventory test", "[inventory]") {
|
||||
// BUG: rewrite this
|
||||
REQUIRE(true == false);
|
||||
/*
|
||||
DinkyECS::World world;
|
||||
save::load_configs(world);
|
||||
auto& config = world.get_the<GameConfig>();
|
||||
|
@ -68,4 +71,5 @@ TEST_CASE("basic inventory test", "[inventory]") {
|
|||
|
||||
inventory.erase_item(0);
|
||||
REQUIRE(inventory.count() == 0);
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -3,16 +3,17 @@
|
|||
#include <nlohmann/json.hpp>
|
||||
#include <fstream>
|
||||
#include "map.hpp"
|
||||
#include "worldbuilder.hpp"
|
||||
#include "levelmanager.hpp"
|
||||
#include "lights.hpp"
|
||||
#include "point.hpp"
|
||||
|
||||
using namespace lighting;
|
||||
|
||||
TEST_CASE("lighting a map works", "[lighting]") {
|
||||
Map map(20,23);
|
||||
WorldBuilder builder(map);
|
||||
builder.generate_map();
|
||||
LevelManager levels;
|
||||
GameLevel level = levels.current();
|
||||
auto &map = *level.map;
|
||||
|
||||
Point light1, light2;
|
||||
|
||||
REQUIRE(map.place_entity(0, light1));
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include <nlohmann/json.hpp>
|
||||
#include <fstream>
|
||||
#include "map.hpp"
|
||||
#include "worldbuilder.hpp"
|
||||
#include "levelmanager.hpp"
|
||||
|
||||
using namespace fmt;
|
||||
using namespace nlohmann;
|
||||
|
@ -15,9 +15,9 @@ json load_test_data(const string &fname) {
|
|||
}
|
||||
|
||||
TEST_CASE("camera control", "[map]") {
|
||||
Map map(20, 20);
|
||||
WorldBuilder builder(map);
|
||||
builder.generate_map();
|
||||
LevelManager levels;
|
||||
GameLevel level = levels.current();
|
||||
auto &map = *level.map;
|
||||
|
||||
Point center = map.center_camera({10,10}, 5, 5);
|
||||
|
||||
|
@ -32,11 +32,10 @@ TEST_CASE("camera control", "[map]") {
|
|||
|
||||
TEST_CASE("map placement test", "[map:placement]") {
|
||||
for(int i = 0; i < 50; i++) {
|
||||
size_t width = Random::uniform<size_t>(9, 21);
|
||||
size_t height = Random::uniform<size_t>(13, 25);
|
||||
Map map(width, height);
|
||||
WorldBuilder builder(map);
|
||||
builder.generate_rooms();
|
||||
LevelManager levels;
|
||||
GameLevel level = levels.current();
|
||||
auto &map = *level.map;
|
||||
|
||||
map.invert_space();
|
||||
|
||||
for(size_t rnum = 0; rnum < map.room_count(); rnum++) {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "config.hpp"
|
||||
#include "matrix.hpp"
|
||||
#include "rand.hpp"
|
||||
#include "worldbuilder.hpp"
|
||||
#include "levelmanager.hpp"
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <fstream>
|
||||
|
||||
|
@ -13,6 +13,12 @@ using namespace fmt;
|
|||
using std::string;
|
||||
using matrix::Matrix;
|
||||
|
||||
shared_ptr<Map> make_map() {
|
||||
LevelManager levels;
|
||||
GameLevel level = levels.current();
|
||||
return level.map;
|
||||
}
|
||||
|
||||
TEST_CASE("basic matrix iterator", "[matrix:basic]") {
|
||||
std::ifstream infile("./tests/dijkstra.json");
|
||||
json data = json::parse(infile);
|
||||
|
@ -252,20 +258,18 @@ TEST_CASE("prototype circle algorithm", "[matrix:circle]") {
|
|||
TEST_CASE("viewport iterator", "[matrix:viewport]") {
|
||||
size_t width = Random::uniform<size_t>(20, 22);
|
||||
size_t height = Random::uniform<size_t>(21, 25);
|
||||
Map map(width,height);
|
||||
WorldBuilder builder(map);
|
||||
builder.generate_map();
|
||||
shared_ptr<Map> map = make_map();
|
||||
|
||||
size_t view_width = width/2;
|
||||
size_t view_height = height/2;
|
||||
Point player;
|
||||
REQUIRE(map.place_entity(1, player));
|
||||
Point start = map.center_camera(player, view_width, view_height);
|
||||
REQUIRE(map->place_entity(1, player));
|
||||
Point start = map->center_camera(player, view_width, view_height);
|
||||
|
||||
size_t end_x = std::min(view_width, map.width() - start.x);
|
||||
size_t end_y = std::min(view_height, map.height() - start.y);
|
||||
size_t end_x = std::min(view_width, map->width() - start.x);
|
||||
size_t end_y = std::min(view_height, map->height() - start.y);
|
||||
|
||||
matrix::viewport it{map.walls(), start, int(view_width), int(view_height)};
|
||||
matrix::viewport it{map->walls(), start, int(view_width), int(view_height)};
|
||||
|
||||
for(size_t y = 0; y < end_y; ++y) {
|
||||
for(size_t x = 0; x < end_x && it.next(); ++x) {
|
||||
|
@ -276,25 +280,21 @@ TEST_CASE("viewport iterator", "[matrix:viewport]") {
|
|||
|
||||
TEST_CASE("random rectangle", "[matrix:rando_rect]") {
|
||||
for(int i = 0; i < 10; i++) {
|
||||
size_t width = Random::uniform<size_t>(9, 21);
|
||||
size_t height = Random::uniform<size_t>(13, 25);
|
||||
Map map(width, height);
|
||||
WorldBuilder builder(map);
|
||||
builder.generate_rooms();
|
||||
map.invert_space();
|
||||
auto wall_copy = map.walls();
|
||||
shared_ptr<Map> map = make_map();
|
||||
map->invert_space();
|
||||
auto wall_copy = map->walls();
|
||||
|
||||
for(size_t rnum = 0; rnum < map.room_count(); rnum++) {
|
||||
Room &room = map.room(rnum);
|
||||
for(size_t rnum = 0; rnum < map->room_count(); rnum++) {
|
||||
Room &room = map->room(rnum);
|
||||
Point pos;
|
||||
|
||||
for(matrix::rando_rect it{map.walls(), room.x, room.y, room.width, room.height}; it.next();)
|
||||
for(matrix::rando_rect it{map->walls(), room.x, room.y, room.width, room.height}; it.next();)
|
||||
{
|
||||
if(map.iswall(it.x, it.y)) {
|
||||
matrix::dump("BAD RECTANGLE SPOT", map.walls(), it.x, it.y);
|
||||
if(map->iswall(it.x, it.y)) {
|
||||
matrix::dump("BAD RECTANGLE SPOT", map->walls(), it.x, it.y);
|
||||
}
|
||||
|
||||
REQUIRE(!map.iswall(it.x, it.y));
|
||||
REQUIRE(!map->iswall(it.x, it.y));
|
||||
REQUIRE(size_t(it.x) >= room.x);
|
||||
REQUIRE(size_t(it.y) >= room.y);
|
||||
REQUIRE(size_t(it.x) <= room.x + room.width);
|
||||
|
@ -310,25 +310,21 @@ TEST_CASE("random rectangle", "[matrix:rando_rect]") {
|
|||
|
||||
TEST_CASE("standard rectangle", "[matrix:rectangle]") {
|
||||
for(int i = 0; i < 20; i++) {
|
||||
size_t width = Random::uniform<size_t>(9, 21);
|
||||
size_t height = Random::uniform<size_t>(13, 25);
|
||||
Map map(width, height);
|
||||
WorldBuilder builder(map);
|
||||
builder.generate_rooms();
|
||||
map.invert_space();
|
||||
auto wall_copy = map.walls();
|
||||
shared_ptr<Map> map = make_map();
|
||||
map->invert_space();
|
||||
auto wall_copy = map->walls();
|
||||
|
||||
for(size_t rnum = 0; rnum < map.room_count(); rnum++) {
|
||||
Room &room = map.room(rnum);
|
||||
for(size_t rnum = 0; rnum < map->room_count(); rnum++) {
|
||||
Room &room = map->room(rnum);
|
||||
Point pos;
|
||||
|
||||
for(matrix::rectangle it{map.walls(), room.x, room.y, room.width, room.height}; it.next();)
|
||||
for(matrix::rectangle it{map->walls(), room.x, room.y, room.width, room.height}; it.next();)
|
||||
{
|
||||
if(map.iswall(it.x, it.y)) {
|
||||
matrix::dump("BAD RECTANGLE SPOT", map.walls(), it.x, it.y);
|
||||
if(map->iswall(it.x, it.y)) {
|
||||
matrix::dump("BAD RECTANGLE SPOT", map->walls(), it.x, it.y);
|
||||
}
|
||||
|
||||
REQUIRE(!map.iswall(it.x, it.y));
|
||||
REQUIRE(!map->iswall(it.x, it.y));
|
||||
REQUIRE(size_t(it.x) >= room.x);
|
||||
REQUIRE(size_t(it.y) >= room.y);
|
||||
REQUIRE(size_t(it.x) <= room.x + room.width);
|
||||
|
|
|
@ -14,47 +14,8 @@ using namespace fmt;
|
|||
using std::string;
|
||||
using namespace components;
|
||||
|
||||
|
||||
enum class Item : char {
|
||||
RADAR = 'R',
|
||||
TRAP = 'T',
|
||||
ORE = 'O'
|
||||
};
|
||||
|
||||
struct Pixel {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
DEFINE_SERIALIZABLE(Pixel, x, y);
|
||||
};
|
||||
|
||||
struct Robot {
|
||||
Pixel point;
|
||||
std::wstring name;
|
||||
std::optional<Item> item;
|
||||
|
||||
DEFINE_SERIALIZABLE(Robot, point, name, item);
|
||||
};
|
||||
|
||||
|
||||
TEST_CASE("test using tser for serialization", "[config]") {
|
||||
auto robot = Robot{ Pixel{3,4}, L"BIG NAME", Item::RADAR};
|
||||
|
||||
tser::BinaryArchive archive;
|
||||
archive.save(robot);
|
||||
std::string_view archive_view = archive.get_buffer();
|
||||
|
||||
tser::BinaryArchive archive2(0);
|
||||
archive2.initialize(archive_view);
|
||||
auto loadedRobot = archive2.load<Robot>();
|
||||
|
||||
REQUIRE(loadedRobot.point.x == robot.point.x);
|
||||
REQUIRE(loadedRobot.point.y == robot.point.y);
|
||||
REQUIRE(loadedRobot.name == robot.name);
|
||||
REQUIRE(loadedRobot.item == robot.item);
|
||||
}
|
||||
|
||||
TEST_CASE("basic save a world", "[save]") {
|
||||
/*
|
||||
DinkyECS::World world;
|
||||
Map map(20, 20);
|
||||
WorldBuilder builder(map);
|
||||
|
@ -100,4 +61,5 @@ TEST_CASE("basic save a world", "[save]") {
|
|||
|
||||
Inventory &inv = world.get<Inventory>(player.entity);
|
||||
REQUIRE(inv.gold == 102);
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include "map.hpp"
|
||||
#include "worldbuilder.hpp"
|
||||
#include "levelmanager.hpp"
|
||||
#include "tilemap.hpp"
|
||||
#include "config.hpp"
|
||||
#include "rand.hpp"
|
||||
|
@ -10,12 +10,9 @@ using namespace fmt;
|
|||
using std::string;
|
||||
|
||||
TEST_CASE("tilemap can load tiles and make a map", "[tilemap]") {
|
||||
size_t width = Random::uniform<size_t>(10, 25);
|
||||
size_t height = Random::uniform<size_t>(10, 33);
|
||||
|
||||
Map map(width,height);
|
||||
WorldBuilder builder(map);
|
||||
builder.generate_map();
|
||||
LevelManager levels;
|
||||
GameLevel level = levels.current();
|
||||
auto &map = *level.map;
|
||||
|
||||
TileMap tiles(map.width(), map.height());
|
||||
auto& walls = map.walls();
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <fstream>
|
||||
#include "map.hpp"
|
||||
#include "worldbuilder.hpp"
|
||||
|
||||
using namespace fmt;
|
||||
using namespace nlohmann;
|
||||
using std::string;
|
||||
|
||||
TEST_CASE("bsp algo test", "[builder]") {
|
||||
Map map(31, 20);
|
||||
WorldBuilder builder(map);
|
||||
builder.generate_map();
|
||||
}
|
||||
|
||||
TEST_CASE("pathing", "[builder]") {
|
||||
Map map(23, 14);
|
||||
WorldBuilder builder(map);
|
||||
builder.generate_map();
|
||||
|
||||
matrix::dump("WALLS", map.$walls, 0,0);
|
||||
println("wall at 0,0=={}", map.$walls[0][0]);
|
||||
|
||||
for(matrix::each_cell it{map.$walls}; it.next();) {
|
||||
if(map.$walls[it.y][it.x] == WALL_VALUE) {
|
||||
REQUIRE(map.iswall(it.x, it.y) == true);
|
||||
REQUIRE(map.can_move({it.x, it.y}) == false);
|
||||
} else {
|
||||
REQUIRE(map.iswall(it.x, it.y) == false);
|
||||
REQUIRE(map.can_move({it.x, it.y}) == true);
|
||||
}
|
||||
}
|
||||
}
|
220
tser.hpp
220
tser.hpp
|
@ -1,220 +0,0 @@
|
|||
// Licensed under the Boost License <https://opensource.org/licenses/BSL-1.0>.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
#pragma once
|
||||
#include <array>
|
||||
#include <ostream>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <tuple>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
|
||||
|
||||
namespace tser{
|
||||
//implementation details for C++20 is_detected
|
||||
namespace detail {
|
||||
struct ns {
|
||||
~ns() = delete;
|
||||
ns(ns const&) = delete;
|
||||
};
|
||||
|
||||
template <class Default, class AlwaysVoid, template<class...> class Op, class... Args>
|
||||
struct detector {
|
||||
using value_t = std::false_type;
|
||||
using type = Default;
|
||||
};
|
||||
|
||||
template <class Default, template<class...> class Op, class... Args>
|
||||
struct detector<Default, std::void_t<Op<Args...>>, Op, Args...> {
|
||||
using value_t = std::true_type;
|
||||
using type = Op<Args...>;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_array : std::is_array<T> {};
|
||||
|
||||
template<template<typename, size_t> class TArray, typename T, size_t N>
|
||||
struct is_array<TArray<T, N>> : std::true_type {};
|
||||
|
||||
constexpr size_t n_args(char const* c, size_t nargs = 1) {
|
||||
for (; *c; ++c) if (*c == ',') ++nargs;
|
||||
return nargs;
|
||||
}
|
||||
|
||||
constexpr size_t str_size(char const* c, size_t strSize = 1) {
|
||||
for (; *c; ++c) ++strSize;
|
||||
return strSize;
|
||||
}
|
||||
}
|
||||
|
||||
// we need a bunch of template metaprogramming for being able to differentiate between different types
|
||||
template <template<class...> class Op, class... Args>
|
||||
constexpr bool is_detected_v = detail::detector<detail::ns, void, Op, Args...>::value_t::value;
|
||||
|
||||
class BinaryArchive;
|
||||
template<class T> using has_begin_t = decltype(*std::begin(std::declval<T>()));
|
||||
|
||||
template<class T> using has_members_t = decltype(std::declval<T>().members());
|
||||
|
||||
template<class T> using has_smaller_t = decltype(std::declval<T>() < std::declval<T>());
|
||||
|
||||
template<class T> using has_equal_t = decltype(std::declval<T>() == std::declval<T>());
|
||||
|
||||
template<class T> using has_nequal_t = decltype(std::declval<T>() != std::declval<T>());
|
||||
|
||||
template<class T> using has_outstream_op_t = decltype(std::declval<std::ostream>() << std::declval<T>());
|
||||
|
||||
template<class T> using has_tuple_t = std::tuple_element_t<0, T>;
|
||||
|
||||
template<class T> using has_optional_t = decltype(std::declval<T>().has_value());
|
||||
|
||||
template<class T> using has_element_t = typename T::element_type;
|
||||
|
||||
template<class T> using has_mapped_t = typename T::mapped_type;
|
||||
|
||||
template<class T> using has_custom_save_t = decltype(std::declval<T>().save(std::declval<BinaryArchive&>()));
|
||||
|
||||
template<class T> using has_free_save_t = decltype(std::declval<const T&>() << std::declval<BinaryArchive&>());
|
||||
|
||||
template<class T> constexpr bool is_container_v = is_detected_v<has_begin_t, T>;
|
||||
|
||||
template<class T> constexpr bool is_tuple_v = is_detected_v<has_tuple_t, T>;
|
||||
|
||||
template<class T> constexpr bool is_tser_t_v = is_detected_v<has_members_t, T>;
|
||||
|
||||
template<class T> constexpr bool is_pointer_like_v = std::is_pointer_v<T> || is_detected_v<has_element_t, T> || is_detected_v<has_optional_t, T>;
|
||||
|
||||
class BinaryArchive {
|
||||
std::string m_bytes = std::string(1024, '\0');
|
||||
size_t m_bufferSize = 0, m_readOffset = 0;
|
||||
|
||||
public:
|
||||
explicit BinaryArchive(const size_t initialSize = 1024) : m_bytes(initialSize, '\0') {}
|
||||
|
||||
template<typename T>
|
||||
explicit BinaryArchive(const T& t) { save(t); }
|
||||
|
||||
template<typename T>
|
||||
void save(const T& t) {
|
||||
if constexpr (is_detected_v<has_free_save_t, T>) {
|
||||
operator<<(t,*this);
|
||||
} else if constexpr (is_detected_v<has_custom_save_t, T>) {
|
||||
t.save(*this);
|
||||
} else if constexpr(is_tser_t_v<T>) {
|
||||
std::apply([&](auto& ... mVal) { (save(mVal), ...); }, t.members());
|
||||
} else if constexpr(is_tuple_v<T>) {
|
||||
std::apply([&](auto& ... tVal) { (save(tVal), ...); }, t);
|
||||
} else if constexpr (is_pointer_like_v<T>) {
|
||||
save(static_cast<bool>(t));
|
||||
if (t)
|
||||
save(*t);
|
||||
} else if constexpr (is_container_v<T>) {
|
||||
if constexpr (!detail::is_array<T>::value) {
|
||||
save(t.size());
|
||||
}
|
||||
|
||||
for (auto& val : t) save(val);
|
||||
} else {
|
||||
if (m_bufferSize + sizeof(T) + sizeof(T) / 4 > m_bytes.size()) {
|
||||
m_bytes.resize((m_bufferSize + sizeof(T)) * 2);
|
||||
}
|
||||
|
||||
std::memcpy(m_bytes.data() + m_bufferSize, std::addressof(t), sizeof(T));
|
||||
m_bufferSize += sizeof(T);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void load(T& t) {
|
||||
using V = std::decay_t<T>;
|
||||
if constexpr (is_detected_v<has_free_save_t, V>) {
|
||||
operator>>(t, *this);
|
||||
} else if constexpr (is_detected_v<has_custom_save_t, T>) {
|
||||
t.load(*this);
|
||||
} else if constexpr (is_tser_t_v<T>) {
|
||||
std::apply([&](auto& ... mVal) { (load(mVal), ...); }, t.members());
|
||||
} else if constexpr (is_tuple_v<V>) {
|
||||
std::apply([&](auto& ... tVal) { (load(tVal), ...); }, t);
|
||||
} else if constexpr (is_pointer_like_v<T>) {
|
||||
if constexpr (std::is_pointer_v<T>) {
|
||||
t = load<bool>() ? (t = new std::remove_pointer_t<T>(), load(*t), t) : nullptr;
|
||||
} else if constexpr (is_detected_v<has_optional_t, T>) {
|
||||
t = load<bool>() ? T(load<typename V::value_type>()) : T();
|
||||
} else { //smart pointer
|
||||
t = T(load<has_element_t<V>*>());
|
||||
}
|
||||
} else if constexpr (is_container_v<T>) {
|
||||
if constexpr (!detail::is_array<T>::value) {
|
||||
const auto size = load<decltype(t.size())>();
|
||||
using VT = typename V::value_type;
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if constexpr (!is_detected_v<has_mapped_t, V>) {
|
||||
t.insert(t.end(), load<VT>());
|
||||
} else {
|
||||
//we have to special case map, because of the const key
|
||||
t.emplace(VT{ load<typename V::key_type>(), load<typename V::mapped_type>() });
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (auto& val : t) load(val);
|
||||
}
|
||||
} else {
|
||||
std::memcpy(&t, m_bytes.data() + m_readOffset, sizeof(T));
|
||||
m_readOffset += sizeof(T);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T load() {
|
||||
std::remove_const_t<T> t{}; load(t); return t;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
friend BinaryArchive& operator<<(BinaryArchive& ba, const T& t) {
|
||||
ba.save(t); return ba;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
friend BinaryArchive& operator>>(BinaryArchive& ba, T& t) {
|
||||
ba.load(t); return ba;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
m_bufferSize = 0;
|
||||
m_readOffset = 0;
|
||||
}
|
||||
|
||||
void initialize(std::string_view str) {
|
||||
m_bytes = str;
|
||||
m_bufferSize = str.size();
|
||||
m_readOffset = 0;
|
||||
}
|
||||
|
||||
std::string_view get_buffer() const {
|
||||
return std::string_view(m_bytes.data(), m_bufferSize);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<class Base, typename Derived>
|
||||
std::conditional_t<std::is_const_v<Derived>, const Base, Base>& base(Derived* thisPtr) { return *thisPtr; }
|
||||
|
||||
template<typename T>
|
||||
auto load(std::string_view encoded) { BinaryArchive ba(encoded); return ba.load<T>(); }
|
||||
}
|
||||
|
||||
//this macro defines printing, serialisation and comparision operators (==,!=,<) for custom types
|
||||
#define DEFINE_SERIALIZABLE(Type, ...) \
|
||||
inline decltype(auto) members() const { return std::tie(__VA_ARGS__); } \
|
||||
inline decltype(auto) members() { return std::tie(__VA_ARGS__); } \
|
||||
static constexpr std::array<char, tser::detail::str_size(#__VA_ARGS__)> _memberNameData = [](){ \
|
||||
std::array<char, tser::detail::str_size(#__VA_ARGS__)> chars{'\0'}; size_t _idx = 0; constexpr auto* ini(#__VA_ARGS__); \
|
||||
for (char const* _c = ini; *_c; ++_c, ++_idx) { if(*_c != ',' && *_c != ' ') chars[_idx] = *_c; } return chars;}(); \
|
||||
static constexpr const char* _typeName = #Type; \
|
||||
static constexpr std::array<const char*, tser::detail::n_args(#__VA_ARGS__)> _memberNames = \
|
||||
[](){ std::array<const char*, tser::detail::n_args(#__VA_ARGS__)> out{ }; \
|
||||
for(size_t _i = 0, nArgs = 0; nArgs < tser::detail::n_args(#__VA_ARGS__) ; ++_i) { \
|
||||
while(Type::_memberNameData[_i] == '\0') {_i++;} out[nArgs++] = &Type::_memberNameData[_i]; \
|
||||
while(Type::_memberNameData[++_i] != '\0'); } return out;}();
|
|
@ -182,10 +182,10 @@ void WorldBuilder::generate_map() {
|
|||
}
|
||||
|
||||
|
||||
DinkyECS::Entity configure_entity_in_map(DinkyECS::World &world, Map &game_map, json &entity_data, int in_room) {
|
||||
DinkyECS::Entity WorldBuilder::configure_entity_in_map(DinkyECS::World &world, json &entity_data, int in_room) {
|
||||
auto item = world.entity();
|
||||
Point pos_out;
|
||||
bool placed = game_map.place_entity(in_room, pos_out);
|
||||
bool placed = $map.place_entity(in_room, pos_out);
|
||||
dbc::check(placed, "failed to randomly place item in room");
|
||||
world.set<Position>(item, {pos_out.x+1, pos_out.y+1});
|
||||
|
||||
|
@ -194,7 +194,7 @@ DinkyECS::Entity configure_entity_in_map(DinkyECS::World &world, Map &game_map,
|
|||
}
|
||||
|
||||
if(entity_data.contains("components")) {
|
||||
components::configure(world, item, entity_data);
|
||||
DinkyECS::configure($components, world, item, entity_data["components"]);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
@ -235,16 +235,16 @@ void WorldBuilder::randomize_entities(DinkyECS::World &world, GameConfig &config
|
|||
auto entity_data = entity_db[key];
|
||||
|
||||
// pass that to the config as it'll be a generic json
|
||||
auto entity = configure_entity_in_map(world, $map, entity_data, room_num);
|
||||
auto entity = configure_entity_in_map(world, entity_data, room_num);
|
||||
check_player(world, entity);
|
||||
}
|
||||
}
|
||||
|
||||
inline void place_stairs(DinkyECS::World& world, GameConfig& config, Map& map) {
|
||||
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;
|
||||
auto entity = configure_entity_in_map(world, map, entity_data, last_room);
|
||||
int last_room = $map.room_count() - 1;
|
||||
auto entity = configure_entity_in_map(world, entity_data, last_room);
|
||||
check_player(world, entity);
|
||||
}
|
||||
|
||||
|
@ -260,7 +260,7 @@ void WorldBuilder::place_entities(DinkyECS::World &world) {
|
|||
world.set<Position>(player.entity, {pos_out.x+1, pos_out.y+1});
|
||||
} else {
|
||||
auto player_data = config.enemies["PLAYER_TILE"];
|
||||
auto player_ent = configure_entity_in_map(world, $map, player_data, 0);
|
||||
auto player_ent = configure_entity_in_map(world, player_data, 0);
|
||||
// configure player in the world
|
||||
Player player{player_ent};
|
||||
world.set_the<Player>(player);
|
||||
|
@ -269,7 +269,7 @@ void WorldBuilder::place_entities(DinkyECS::World &world) {
|
|||
}
|
||||
|
||||
randomize_entities(world, config);
|
||||
place_stairs(world, config, $map);
|
||||
place_stairs(world, config);
|
||||
}
|
||||
|
||||
void WorldBuilder::generate(DinkyECS::World &world) {
|
||||
|
|
|
@ -7,8 +7,12 @@
|
|||
class WorldBuilder {
|
||||
public:
|
||||
Map& $map;
|
||||
DinkyECS::ComponentMap& $components;
|
||||
|
||||
WorldBuilder(Map &map) : $map(map) { }
|
||||
WorldBuilder(Map &map, DinkyECS::ComponentMap& components) :
|
||||
$map(map),
|
||||
$components(components)
|
||||
{ }
|
||||
|
||||
void partition_map(Room &cur, int depth);
|
||||
void make_room(size_t origin_y, size_t origin_x, size_t width, size_t height);
|
||||
|
@ -20,8 +24,11 @@ class WorldBuilder {
|
|||
void stylize_room(int room, string tile_name, float size);
|
||||
void generate_rooms();
|
||||
void generate_map();
|
||||
|
||||
DinkyECS::Entity configure_entity_in_map(DinkyECS::World &world, nlohmann::json &entity_data, int in_room);
|
||||
void place_entities(DinkyECS::World &world);
|
||||
void generate(DinkyECS::World &world);
|
||||
void random_entity(DinkyECS::World &world, components::GameConfig &config);
|
||||
void randomize_entities(DinkyECS::World &world, components::GameConfig &config);
|
||||
void place_stairs(DinkyECS::World& world, components::GameConfig& config);
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue