From 222b39c403e8156266ff7f9c7a2646e97f97d7a8 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Thu, 9 Jan 2025 14:01:40 -0500 Subject: [PATCH] Fixed up building enemies and items using componentsin the JSON. --- assets/enemies.json | 15 ++++++++++----- assets/items.json | 8 +++----- components.hpp | 28 +++++++++++++++++++++++++--- dbc.cpp | 13 ++++++++----- gui.cpp | 3 +-- matrix.hpp | 22 ++++++++++++++++++++-- save.cpp | 5 ----- save.hpp | 1 + status.txt | 1 + systems.cpp | 6 ++++-- tests/components.cpp | 6 ------ tests/matrix.cpp | 2 +- worldbuilder.cpp | 26 ++------------------------ 13 files changed, 76 insertions(+), 60 deletions(-) diff --git a/assets/enemies.json b/assets/enemies.json index 96f7eee..538119d 100644 --- a/assets/enemies.json +++ b/assets/enemies.json @@ -4,7 +4,8 @@ "background": [30, 20, 75], "components": [ {"type": "Tile", "config": {"chr": "\ua66b"}}, - {"type": "Combat", "config": {"hp": 200, "damage": 15}} + {"type": "Combat", "config": {"hp": 200, "damage": 15}}, + {"type": "EnemyConfig", "config": {"hearing_distance": 5}} ] }, "SNAKE": { @@ -12,7 +13,8 @@ "background": [30, 20, 75], "components": [ {"type": "Tile", "config": {"chr": "\u06b1"}}, - {"type": "Combat", "config": {"hp": 20, "damage": 15}} + {"type": "Combat", "config": {"hp": 20, "damage": 15}}, + {"type": "EnemyConfig", "config": {"hearing_distance": 6}} ] }, "GOBLIN": { @@ -21,7 +23,8 @@ "components": [ {"type": "LightSource", "config": {"strength": 70, "radius": 1.8}}, {"type": "Tile", "config": {"chr": "\u06bf"}}, - {"type": "Combat", "config": {"hp": 50, "damage": 35}} + {"type": "Combat", "config": {"hp": 50, "damage": 35}}, + {"type": "EnemyConfig", "config": {"hearing_distance": 4}} ] }, "UNICORN": { @@ -29,7 +32,8 @@ "background": [30, 20, 75], "components": [ {"type": "Tile", "config": {"chr": "\u17a5"}}, - {"type": "Combat", "config": {"hp": 2000, "damage": 5}} + {"type": "Combat", "config": {"hp": 100, "damage": 5}}, + {"type": "EnemyConfig", "config": {"hearing_distance": 3}} ] }, "RAT": { @@ -37,7 +41,8 @@ "background": [30, 20, 75], "components": [ {"type": "Tile", "config": {"chr": "\u08ac"}}, - {"type": "Combat", "config": {"hp": 10, "damage": 5}} + {"type": "Combat", "config": {"hp": 10, "damage": 5}}, + {"type": "EnemyConfig", "config": {"hearing_distance": 10}} ] } } diff --git a/assets/items.json b/assets/items.json index 8de5bc5..19c0e15 100644 --- a/assets/items.json +++ b/assets/items.json @@ -8,8 +8,7 @@ "inventory_count": 1, "components": [ {"type": "LightSource", "config": {"strength": 70, "radius": 2.0}}, - {"type": "Tile", "config": {"chr": "\u0f08"}}, - {"type": "Weapon", "config": {"damage": 35}} + {"type": "Tile", "config": {"chr": "\u0f08"}} ] }, "SWORD_RUSTY": { @@ -57,9 +56,8 @@ "description": "A torch on a wall you can't pick up.", "inventory_count": 0, "components": [ - {"type": "Tile", "config": {"chr": "\u06bf"}}, + {"type": "Tile", "config": {"chr": "\u077e"}}, {"type": "LightSource", "config": {"strength": 60, "radius": 1.8}} - ], - "display": "☀" + ] } } diff --git a/components.hpp b/components.hpp index 49887c0..ad1fa7c 100644 --- a/components.hpp +++ b/components.hpp @@ -1,10 +1,9 @@ #pragma once #include "dinkyecs.hpp" -#include "map.hpp" #include "combat.hpp" #include "inventory.hpp" -#include #include "tser.hpp" +#include "config.hpp" namespace components { struct Player { @@ -41,7 +40,7 @@ namespace components { }; struct EnemyConfig { - int HEARING_DISTANCE; + int hearing_distance = 10; }; struct Debug { @@ -52,4 +51,27 @@ namespace components { struct Weapon { int damage = 0; }; + + inline void configure(DinkyECS::World &world, DinkyECS::Entity entity, json& entity_data) { + for(auto &comp : entity_data["components"]) { + json& config = comp["config"]; + + if(comp["type"] == "Weapon") { + world.set(entity, {config["damage"]}); + } else if(comp["type"] == "LightSource") { + world.set(entity, {config["strength"], config["radius"]}); + } else if(comp["type"] == "Loot") { + world.set(entity, {config["amount"]}); + } else if(comp["type"] == "Tile") { + world.set(entity, {config["chr"]}); + } else if(comp["type"] == "EnemyConfig") { + world.set(entity, {config["hearing_distance"]}); + } else if(comp["type"] == "Combat") { + world.set(entity, {config["hp"], config["damage"]}); + } else { + dbc::sentinel(fmt::format("ITEM COMPONENT TYPE MISSING: {}", + std::string(comp["type"]))); + } + } + } } diff --git a/dbc.cpp b/dbc.cpp index 515a644..4145253 100644 --- a/dbc.cpp +++ b/dbc.cpp @@ -2,17 +2,19 @@ #include void dbc::log(const string &message) { - fmt::print("{}\n", message); + std::cerr << message << std::endl; } void dbc::sentinel(const string &message) { - string err = fmt::format("[SENTINEL!] {}\n", message); + string err = fmt::format("[SENTINEL!] {}", message); + dbc::log(err); throw dbc::SentinelError{err}; } void dbc::pre(const string &message, bool test) { if(!test) { - string err = fmt::format("[PRE!] {}\n", message); + string err = fmt::format("[PRE!] {}", message); + dbc::log(err); throw dbc::PreCondError{err}; } } @@ -23,7 +25,8 @@ void dbc::pre(const string &message, std::function tester) { void dbc::post(const string &message, bool test) { if(!test) { - string err = fmt::format("[POST!] {}\n", message); + string err = fmt::format("[POST!] {}", message); + dbc::log(err); throw dbc::PostCondError{err}; } } @@ -35,7 +38,7 @@ void dbc::post(const string &message, std::function tester) { void dbc::check(bool test, const string &message) { if(!test) { string err = fmt::format("[CHECK!] {}\n", message); - fmt::println("{}", err); + dbc::log(err); throw dbc::CheckError{err}; } } diff --git a/gui.cpp b/gui.cpp index ae9d621..e09cebc 100644 --- a/gui.cpp +++ b/gui.cpp @@ -72,8 +72,7 @@ void InventoryUI::update_menu_list(Inventory& inventory) { $menu_list.clear(); for(size_t i = 0; i < inventory.count(); i++) { auto& item = inventory.get(i); - $menu_list.push_back(fmt::format("{} {} ({})", - string(item.data["display"]), + $menu_list.push_back(fmt::format("{} ({})", string(item.data["name"]), item.count)); diff --git a/matrix.hpp b/matrix.hpp index e9266fa..b6ef16f 100644 --- a/matrix.hpp +++ b/matrix.hpp @@ -10,8 +10,15 @@ namespace matrix { using std::vector, std::queue, std::array; using std::min, std::max, std::floor; - typedef vector Row; - typedef vector Matrix; + template + using BaseRow = vector; + + template + using Base = vector>; + + using Row = vector; + using Matrix = vector; + /* * Just a quick thing to reset a matrix to a value. @@ -40,6 +47,17 @@ namespace matrix { return mat.size(); } + template + inline Base make_base(size_t width, size_t height) { + Base result(height, BaseRow(width)); + return result; + } + + inline Matrix make(size_t width, size_t height) { + Matrix result(height, Row(width)); + return result; + } + inline size_t next_x(size_t x, size_t width) { return (x + 1) * ((x + 1) < width); } diff --git a/save.cpp b/save.cpp index c87e4e0..7e7bad7 100644 --- a/save.cpp +++ b/save.cpp @@ -92,9 +92,4 @@ void save::load_configs(DinkyECS::World &world) { world.set_the({ game, enemies, items, tiles }); - - auto enemy = game["enemy"]; - world.set_the({ - enemy["HEARING_DISTANCE"] - }); } diff --git a/save.hpp b/save.hpp index 84771df..7f3149a 100644 --- a/save.hpp +++ b/save.hpp @@ -1,6 +1,7 @@ #pragma once #include "components.hpp" +#include "map.hpp" #include "dinkyecs.hpp" #include "tser.hpp" #include diff --git a/status.txt b/status.txt index bcfad12..a645e57 100644 --- a/status.txt +++ b/status.txt @@ -1,5 +1,6 @@ TODAY'S GOAL: +* Goblins will be in the world and not move or are already dead. * https://pkl-lang.org/ * Check out https://github.com/stephenberry/glaze * Things are still in walls because I +1 the x,y if they're colliding. diff --git a/systems.cpp b/systems.cpp index d9afc5a..9a182df 100644 --- a/systems.cpp +++ b/systems.cpp @@ -32,15 +32,17 @@ void System::lighting(DinkyECS::World &world, Map &game_map, LightRender &light, void System::enemy_pathing(DinkyECS::World &world, Map &game_map, Player &player) { // TODO: this will be on each enemy not a global thing - const auto &config = world.get_the(); const auto &player_position = world.get(player.entity); game_map.set_target(player_position.location); game_map.make_paths(); world.query([&](const auto &ent, auto &position, auto &motion) { if(ent != player.entity) { + dbc::check(world.has(ent), "enemy is missing config"); + const auto &config = world.get(ent); + Point out = position.location; // copy - if(game_map.distance(out) < config.HEARING_DISTANCE) { + if(game_map.distance(out) < config.hearing_distance) { game_map.neighbors(out); motion = { int(out.x - position.location.x), int(out.y - position.location.y)}; } diff --git a/tests/components.cpp b/tests/components.cpp index dd90449..095acec 100644 --- a/tests/components.cpp +++ b/tests/components.cpp @@ -36,9 +36,6 @@ TEST_CASE("all components can work in the world", "[components]") { auto tile = world.get(ent1); REQUIRE(tile.chr == "Z"); - - auto enemy = world.get(ent1); - REQUIRE(enemy.HEARING_DISTANCE == 4); } TEST_CASE("all components can be facts", "[components]") { @@ -72,9 +69,6 @@ TEST_CASE("all components can be facts", "[components]") { auto tile = world.get_the(); REQUIRE(tile.chr == "Z"); - - auto enemy = world.get_the(); - REQUIRE(enemy.HEARING_DISTANCE == 4); } TEST_CASE("confirm combat works", "[components]") { diff --git a/tests/matrix.cpp b/tests/matrix.cpp index 20c4b3b..56df254 100644 --- a/tests/matrix.cpp +++ b/tests/matrix.cpp @@ -86,7 +86,7 @@ TEST_CASE("thrash matrix iterators", "[matrix]") { size_t width = Random::uniform(1, 100); size_t height = Random::uniform(1, 100); - Matrix test(width, matrix::Row(height)); + Matrix test(height, matrix::Row(width)); random_matrix(test); // first make a randomized matrix diff --git a/worldbuilder.cpp b/worldbuilder.cpp index d6a0bc8..376d210 100644 --- a/worldbuilder.cpp +++ b/worldbuilder.cpp @@ -168,28 +168,6 @@ void WorldBuilder::generate_map() { } } -void configure_components(DinkyECS::World &world, DinkyECS::Entity entity, json& entity_data) { - for(auto &comp : entity_data["components"]) { - json& config = comp["config"]; - - if(comp["type"] == "Weapon") { - world.set(entity, {config["damage"]}); - } else if(comp["type"] == "LightSource") { - world.set(entity, {config["strength"], config["radius"]}); - } else if(comp["type"] == "Loot") { - world.set(entity, {config["amount"]}); - } else if(comp["type"] == "Tile") { - world.set(entity, {config["chr"]}); - } else if(comp["type"] == "EnemyConfig") { - world.set(entity, {config["hearing_distance"]}); - } else if(comp["type"] == "Combat") { - world.set(entity, {config["hp"], config["damage"]}); - } else { - dbc::sentinel(format("ITEM COMPONENT TYPE MISSING: {}", - std::string(comp["type"]))); - } - } -} DinkyECS::Entity place_item(DinkyECS::World &world, Map &game_map, std::string name, int in_room) { auto &config = world.get_the(); @@ -203,7 +181,7 @@ DinkyECS::Entity place_item(DinkyECS::World &world, Map &game_map, std::string n } if(item_data.contains("components")) { - configure_components(world, item, item_data); + components::configure(world, item, item_data); } return item; } @@ -217,7 +195,7 @@ DinkyECS::Entity place_combatant(DinkyECS::World &world, Map &game_map, std::str world.set(enemy, {0,0}); if(enemy_data.contains("components")) { - configure_components(world, enemy, enemy_data); + components::configure(world, enemy, enemy_data); } return enemy; }