#include "gui.hpp" #include // for EXIT_SUCCESS #include // for milliseconds #include #include // for Event #include // for ftxui #include // for text, separator, Element, operator|, vbox, border #include // for allocator, shared_ptr #include // for operator+, to_string #include // for sleep_for #include "ftxui/component/component.hpp" // for CatchEvent, Renderer, operator|= #include "ftxui/component/loop.hpp" // for Loop #include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive #include #include #include #include using namespace ftxui; using namespace std; using namespace fmt; using namespace nlohmann; namespace fs = std::filesystem; void SoundQuip::load(json &data, const char *file_key) { auto audio = data["audio"]; json::string_t file_name = audio[file_key].template get(); if(!buffer.loadFromFile(file_name)) { cout << "Failed to load sound: " << file_key << " with file " << file_name << "\n"; } sound.setBuffer(buffer); } void SoundQuip::play() { sound.play(); } void SoundQuip::stop() { sound.stop(); } GUI::GUI() { ifstream infile(".tarpit.json"); json data = json::parse(infile); // json load the config file you_died_sound.load(data, "you_died"); build_works_sound.load(data, "build_works"); build_failed_sound.load(data, "build_failed"); building_sound.load(data, "building"); } void GUI::output(const string &msg) { lines.push_back(msg); } int GUI::main_loop(GameEngine &game, std::function runner) { auto screen = ScreenInteractive::Fullscreen(); screen.TrackMouse(true); // Create a component counting the number of frames drawn and event handled. float scroll_x = 0.1; float scroll_y = 1.0; auto status = Renderer([&] { return vbox({ text(fmt::format("HP {} | Hits Taken {} | Round {} | Streak {}", game.hit_points, game.hits_taken, game.rounds, game.streak)), separator(), hbox({ text("HP "), gauge(game.hit_points / 100.0f), }), }); }); auto content = Renderer([&] { vector output; for(const auto line : lines) { output.push_back(text(line)); } return vbox(output); }); auto game_stuff = Renderer([&] { return vbox({ text("Welcome to...Turing's Tarpit!"), separator(), hbox({ text("Your Face") | center | xflex_grow , text("Something Fun") | border | flex, }) | yflex_grow }); }); auto build_log = Renderer(content, [&, content] { return content->Render() | focusPositionRelative(scroll_x, scroll_y) | frame | flex; }); auto component = Renderer(build_log, [&] { return vbox({ status->Render(), separator(), build_log->Render() | vscroll_indicator | yframe | yflex_grow, separator(), game_stuff->Render() | flex | size(HEIGHT, GREATER_THAN, 20), }); }); component |= CatchEvent([&](Event) -> bool { return false; }); Loop loop(&screen, component); while (!loop.HasQuitted()) { int run_error = runner(); if(run_error != 0) output("RUNNER ERROR!!!! CATASTROPHIC!!!"); loop.RunOnce(); screen.Post(Event::Custom); std::this_thread::sleep_for(std::chrono::milliseconds(10)); } return EXIT_SUCCESS; } void GUI::build_works() { building_sound.stop(); build_works_sound.play(); output("BUILD FINISHED!"); } void GUI::build_failed(bool play_sound, const string &command) { building_sound.stop(); if(play_sound) { build_failed_sound.play(); } output(format("!!! BUILD FAILED. Your command correct? '{}'", command)); } void GUI::you_died() { building_sound.stop(); you_died_sound.play(); output("YOU DIED!"); } void GUI::building() { output("############# START ############"); output(">>>> Will it Build?"); building_sound.play(); }