From 2825faf038e6c464f7871f1d31bc9e530331b4db Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Fri, 24 Jan 2025 13:47:00 -0500 Subject: [PATCH] You can now go down stairs to new levels, but when you do you become stairs or a random monster. --- assets/config.json | 4 ++-- dinkyecs.hpp | 9 ++++++- gui.cpp | 58 ++++++++++++++++++++++++++++------------------ gui.hpp | 27 ++++++++++++--------- levelmanager.cpp | 24 +++++++++++++++++-- levelmanager.hpp | 11 +++++---- worldbuilder.cpp | 16 ++++++++----- 7 files changed, 100 insertions(+), 49 deletions(-) diff --git a/assets/config.json b/assets/config.json index 5b289aa..009c4f9 100644 --- a/assets/config.json +++ b/assets/config.json @@ -6,8 +6,8 @@ }, "worldgen": { - "enemy_probability": 10, - "empty_room_probability": 60, + "enemy_probability": 20, + "empty_room_probability": 10, "device_probability": 100 } } diff --git a/dinkyecs.hpp b/dinkyecs.hpp index 4cf59be..5b39593 100644 --- a/dinkyecs.hpp +++ b/dinkyecs.hpp @@ -58,13 +58,20 @@ namespace DinkyECS { template Comp &get_the() { auto comp_id = std::type_index(typeid(Comp)); - dbc::check($facts.contains(comp_id), "!!!! ATTEMPT to access world fact that hasn't been set yet."); + dbc::check($facts.contains(comp_id), + fmt::format("!!!! ATTEMPT to access world fact that hasn't been set yet: {}", typeid(Comp).name())); // use .at to get std::out_of_range if fact not set std::any &res = $facts.at(comp_id); return std::any_cast(res); } + template + bool has_the() { + auto comp_id = std::type_index(typeid(Comp)); + return $facts.contains(comp_id); + } + template void set(Entity ent, Comp val) { EntityMap &map = entity_map_for(); diff --git a/gui.cpp b/gui.cpp index 945b001..a38ca33 100644 --- a/gui.cpp +++ b/gui.cpp @@ -69,8 +69,8 @@ void InventoryUI::create_render() { $inventory_box = Menu(&$menu_list, &$selected, option); $inventory_render = Renderer([&] { - auto &player = $world.get_the(); - auto &inventory = $world.get(player.entity); + auto &player = $level.world->get_the(); + auto &inventory = $level.world->get(player.entity); update_menu_list(inventory); return hbox({ @@ -101,12 +101,12 @@ void InventoryUI::update_menu_list(Inventory& inventory) { } void StatusUI::create_render() { - auto player = $world.get_the(); + auto player = $level.world->get_the(); auto status_rend = Renderer([&, player]{ - const auto& player_combat = $world.get(player.entity); - const auto& inventory = $world.get(player.entity); - const auto& combat = $world.get(player.entity); + const auto& player_combat = $level.world->get(player.entity); + const auto& inventory = $level.world->get(player.entity); + const auto& combat = $level.world->get(player.entity); $status_text = player_combat.hp > 0 ? "NOT DEAD" : "DEAD!!!!!!"; std::vector log_list; @@ -136,23 +136,27 @@ void StatusUI::create_render() { set_renderer(status_rend); } -MapViewUI::MapViewUI(DinkyECS::World& world, LightRender& lights, Map& game_map) : +MapViewUI::MapViewUI(GameLevel &level) : Panel(GAME_MAP_PIXEL_POS, 0, 0, 0, true), - $world(world), $lights(lights), $game_map(game_map) + $level(level) {} +void MapViewUI::update_level(GameLevel &level) { + $level = level; +} + void MapViewUI::draw_map() { - const auto& debug = $world.get_the(); - const auto& player = $world.get_the(); - const auto& player_position = $world.get(player.entity); - Point start = $game_map.center_camera(player_position.location, width, height); - auto &tiles = $game_map.tiles(); - auto &paths = $game_map.paths(); - auto &lighting = $lights.lighting(); + const auto& debug = $level.world->get_the(); + const auto& player = $level.world->get_the(); + const auto& player_position = $level.world->get(player.entity); + Point start = $level.map->center_camera(player_position.location, width, height); + auto &tiles = $level.map->tiles(); + auto &paths = $level.map->paths(); + auto &lighting = $level.lights->lighting(); // WARN: this is exploiting that -1 in size_t becomes largest - size_t end_x = std::min(size_t(width), $game_map.width() - start.x); - size_t end_y = std::min(size_t(height), $game_map.height() - start.y); + size_t end_x = std::min(size_t(width), $level.map->width() - start.x); + size_t end_y = std::min(size_t(height), $level.map->height() - start.y); for(size_t y = 0; y < end_y; ++y) { for(size_t x = 0; x < end_x; ++x) @@ -178,7 +182,7 @@ void MapViewUI::draw_map() { } } - System::draw_entities($world, $game_map, lighting, $canvas, start, width, height); + System::draw_entities(*$level.world, *$level.map, lighting, $canvas, start, width, height); } void MapViewUI::create_render() { @@ -195,9 +199,9 @@ void MapViewUI::resize_canvas() { GUI::GUI() : $level($level_manager.current()), - $status_ui(*$level.world), - $map_view(*$level.world, *$level.lights, *$level.map), - $inventory_ui(*$level.world), + $status_ui($level), + $map_view($level), + $inventory_ui($level), $sounds("./assets") { // this needs a config file soon @@ -291,7 +295,7 @@ void GUI::handle_world_events() { $status_ui.log(format("Up stairs has test {}.", (bool)device.config["test"])); - toggle_modal(&$next_level_ui, $next_level); + // toggle_modal(&$next_level_ui, $next_level); } break; default: $status_ui.log(format("INVALID EVENT! {},{}", evt, entity)); @@ -502,5 +506,15 @@ int GUI::main(bool run_once) { } void GUI::next_level() { + size_t index = $level_manager.create_level($level.world); + fmt::println("LEVEL manager returned index: {}", index); + auto &level = $level_manager.next(); + $status_ui.update_level(level); + $inventory_ui.update_level(level); + $map_view.update_level(level); + $level = level; + + render_scene(); + run_systems(); } diff --git a/gui.hpp b/gui.hpp index eae91d8..d31120e 100644 --- a/gui.hpp +++ b/gui.hpp @@ -79,16 +79,19 @@ class InventoryUI : public Panel { Component $inventory_box; Component $inventory_render; Component $inventory_table; - DinkyECS::World& $world; + GameLevel $level; std::vector $menu_list; std::string $item_text = "No item selected."; - InventoryUI(DinkyECS::World& world) : + InventoryUI(GameLevel level) : Panel(INVENTORY_PIXEL_X, INVENTORY_PIXEL_Y, INVENTORY_WIDTH, INVENTORY_HEIGHT), - $world(world) + $level(level) {} void create_render(); + + void update_level(GameLevel &level) { $level = level; } + void update_menu_list(components::Inventory& inventory); }; @@ -96,40 +99,42 @@ class StatusUI : public Panel { public: ActionLog $log; string $status_text = "NOT DEAD"; - DinkyECS::World& $world; + GameLevel $level; - StatusUI(DinkyECS::World& world) : + StatusUI(GameLevel level) : Panel(0, 0, STATUS_UI_WIDTH, STATUS_UI_HEIGHT), $log({{"Welcome to the game!"}}), - $world(world) {} + $level(level) {} void create_render(); void log(string msg) { $log.log(msg); } + void update_level(GameLevel &level) { $level = level; } }; class MapViewUI : public Panel { public: Canvas $canvas; - DinkyECS::World& $world; - LightRender& $lights; - Map& $game_map; + GameLevel $level; - MapViewUI(DinkyECS::World& world, LightRender& lights, Map& game_map); + MapViewUI(GameLevel &level); void create_render(); void resize_canvas(); void draw_map(); + void update_level(GameLevel &level); }; class GUI { LevelManager $level_manager; - GameLevel &$level; + GameLevel $level; + StatusUI $status_ui; MapViewUI $map_view; InventoryUI $inventory_ui; DeathUI $death_ui; NextLevelUI $next_level_ui; + Canvas $canvas; bool $inventory_open = false; bool $player_died = false; diff --git a/levelmanager.cpp b/levelmanager.cpp index 1f21f6c..b6d2bfa 100644 --- a/levelmanager.cpp +++ b/levelmanager.cpp @@ -3,20 +3,40 @@ #include "constants.hpp" #include "save.hpp" #include "systems.hpp" +#include "components.hpp" using lighting::LightRender; using std::shared_ptr, std::make_shared; +using namespace components; LevelManager::LevelManager() { create_level(); } - -size_t LevelManager::create_level() { +size_t LevelManager::create_level(shared_ptr prev_world) { auto world = make_shared(); save::load_configs(*world); auto map = make_shared(GAME_MAP_X, GAME_MAP_Y); + + if(prev_world != nullptr) { + auto player = prev_world->get_the(); + world->set_the(player); + + auto inventory = prev_world->get(player.entity); + world->set(player.entity, inventory); + + world->set_the(prev_world->get_the()); + auto& combat = prev_world->get(player.entity); + world->set(player.entity, combat); + + auto& motion = prev_world->get(player.entity); + world->set(player.entity, motion); + + auto& tile = prev_world->get(player.entity); + world->set(player.entity, tile); + } + WorldBuilder builder(*map); builder.generate(*world); diff --git a/levelmanager.hpp b/levelmanager.hpp index 89a47e3..365acbd 100644 --- a/levelmanager.hpp +++ b/levelmanager.hpp @@ -7,13 +7,14 @@ #include #include "spatialmap.hpp" +using std::shared_ptr; struct GameLevel { size_t index; - std::shared_ptr map; - std::shared_ptr world; - std::shared_ptr lights; - std::shared_ptr collision; + shared_ptr map; + shared_ptr world; + shared_ptr lights; + shared_ptr collision; }; class LevelManager { @@ -23,7 +24,7 @@ class LevelManager { LevelManager(); - size_t create_level(); + size_t create_level(shared_ptr prev_world = nullptr); GameLevel &next(); GameLevel &previous(); GameLevel ¤t(); diff --git a/worldbuilder.cpp b/worldbuilder.cpp index f45bdb8..a9c1fb1 100644 --- a/worldbuilder.cpp +++ b/worldbuilder.cpp @@ -226,12 +226,16 @@ void WorldBuilder::place_entities(DinkyECS::World &world) { auto &config = world.get_the(); // configure a player as a fact of the world - auto player_data = config.enemies["PLAYER_TILE"]; - auto player_ent = configure_entity_in_map(world, $map, player_data, 0); - // configure player in the world - Player player{player_ent}; - world.set_the(player); - world.set(player.entity, {5}); + if(world.has_the()) { + fmt::println("PLAYER ALREADY EXISTS LEAVING ALONE"); + } else { + auto player_data = config.enemies["PLAYER_TILE"]; + auto player_ent = configure_entity_in_map(world, $map, player_data, 0); + // configure player in the world + Player player{player_ent}; + world.set_the(player); + world.set(player.entity, {5}); + } randomize_entities(world, config); }