#include "main_ui.hpp" #include "components.hpp" #include "easings.hpp" namespace gui { using namespace components; MainUI::MainUI(sf::RenderWindow& window) : $window(window), $rayview(RAY_VIEW_WIDTH, RAY_VIEW_HEIGHT) { $window.setVerticalSyncEnabled(VSYNC); $window.setFramerateLimit(FRAME_LIMIT); } void MainUI::dirty() { $needs_render = true; } void MainUI::debug() { auto& dbg = $level.world->get_the(); dbg.FPS = !dbg.FPS; dbg.PATHS = !dbg.PATHS; if(dbg.FPS) { // it's on now, enable things auto player = $level.world->get_the(); auto& player_combat = $level.world->get(player.entity); player_combat.hp = player_combat.max_hp; $overlay_ui.show_text("top_left", "STATS"); } else { // it's off now, close it $overlay_ui.close_text("top_left"); } } void MainUI::draw_stats() { auto player = $level.world->get_the(); auto player_combat = $level.world->get(player.entity); auto map = $level.map; std::string stats = fmt::format("STATS\n" "HP: {}\n" "mean:{:>8.5}\n" "sdev: {:>8.5}\n" "min: {:>8.5}\n" "max: {:>8.5}\n" "count:{:<10}\n" "level: {} size: {}x{}\n\n" "dir: {:0.2},{:0.2}\n\n" "VSync? {}\n" "FR Limit: {}\n" "Debug? {}\n\n", player_combat.hp, $stats.mean(), $stats.stddev(), $stats.min, $stats.max, $stats.n, $level.index, map->width(), map->height(), $rayview.$dir_x, $rayview.$dir_y, VSYNC, FRAME_LIMIT, DEBUG_BUILD); $overlay_ui.show_text("top_left", stats); } void MainUI::draw_blood() { auto player = $level.world->get_the(); auto player_combat = $level.world->get(player.entity); if(float(player_combat.hp) / float(player_combat.max_hp) < 0.5) { $overlay_ui.show_sprite("middle", "blood_splatter"); } else { $overlay_ui.close_sprite("middle"); } } void MainUI::init() { auto& player_position = $level.world->get($level.player); auto player = player_position.location; $rayview.init_shaders(); $rayview.set_position(RAY_VIEW_X, RAY_VIEW_Y); $rayview.position_camera(player.x + 0.5, player.y + 0.5); $overlay_ui.show_label("top_left", $compass[$compass_dir]); auto st = textures::get("down_the_well"); auto bounds = st.sprite->getLocalBounds(); st.sprite->setPosition({RAY_VIEW_X + bounds.size.x / 2, RAY_VIEW_Y + bounds.size.y / 2}); st.sprite->setOrigin({bounds.size.x / 2, bounds.size.y / 2}); $overlay_ui.init(); } void MainUI::show_level() { $show_level = true; } void MainUI::render() { auto start = $stats.time_start(); if($show_level) { auto time = $clock.getElapsedTime(); auto st = textures::get("down_the_well"); float tick = ease::in_out_back(ease::sine(time.asSeconds())); float scale = std::lerp(1.0, 1.3, tick); st.sprite->setScale({scale, scale}); $window.draw(*st.sprite); $overlay_ui.show_label("middle", "INTO THE WELL YOU GO..."); } else { if($needs_render) $rayview.render(); $rayview.draw($window); } $stats.sample_time(start); $overlay_ui.render($window); auto debug = $level.world->get_the(); if(debug.FPS) draw_stats(); // draw_blood(); } bool MainUI::play_rotate() { bool done = $camera.play_rotate($rayview); $needs_render = !done; return done; } // this could be an optional that returs a Point std::optional MainUI::play_move() { if($camera.play_move($rayview)) { $needs_render = false; Point pos{ size_t($camera.target_x), size_t($camera.target_y)}; return std::make_optional(pos); } else { $needs_render = true; return std::nullopt; } } void MainUI::plan_rotate(int dir) { // -1 is left, 1 is right $compass_dir = ($compass_dir + dir) % $compass.size(); $overlay_ui.show_label("top_left", $compass[$compass_dir]); $camera.plan_rotate($rayview, dir); } Point MainUI::plan_move(int dir, bool strafe) { return $camera.plan_move($rayview, dir, strafe); } void MainUI::abort_plan() { $camera.abort_plan($rayview); } void MainUI::dead_entity(DinkyECS::Entity entity) { auto &sprite = $level.world->get(entity); $rayview.update_sprite(entity, sprite); } void MainUI::update_level(GameLevel level) { $level = level; auto& player_position = $level.world->get($level.player); auto player = player_position.location; $rayview.update_level($level); $rayview.position_camera(player.x + 0.5, player.y + 0.5); $compass_dir = 0; $overlay_ui.show_label("top_left", $compass[$compass_dir]); dirty(); } void MainUI::mouse(int x, int y) { if($show_level) { $show_level = false; $level.world->send(Events::GUI::STAIRS_DOWN, $level.player, {}); $overlay_ui.close_label("middle"); } else { $overlay_ui.$gui.mouse(x, y); } } }