#define _USE_MATH_DEFINES #include #include #include #include #include #include #include #include #include #include #include #include "sfmlbackend.hpp" #include #include #include "dbc.hpp" using namespace nlohmann; using std::string, std::make_shared; std::array VALUES{ sf::Color{1, 4, 2}, // black sf::Color{9, 29, 16}, // dark dark sf::Color{14, 50, 26}, // dark mid sf::Color{0, 109, 44}, // dark light sf::Color{63, 171, 92}, // mid sf::Color{161, 217, 155}, // light dark sf::Color{199, 233, 192}, // light mid sf::Color{229, 245, 224}, // light light sf::Color{255, 255, 255}, // white sf::Color::Transparent, // white }; void SoundQuip::load(json &data, const char *file_key, bool loop) { buffer = make_shared(); auto audio = data["audio"]; json::string_t file_name = audio[file_key].template get(); if(!buffer->loadFromFile(file_name)) { fmt::println("Failed to load sound: {} with file {}", file_key, file_name); } sound = make_shared(*buffer); sound->setLooping(loop); } void SoundQuip::play() { sound->play(); } void SoundQuip::stop() { sound->stop(); } void SFMLBackend::Window_update() { window.display(); } sf::Color SFMLBackend::value(Value level) { return VALUES.at(int(level)); } void SFMLBackend::handle_events() { // is this a main event loop while(const auto ev = window.pollEvent()) { if(ev->is()) { fmt::print("Exiting...\n"); window.close(); } } } sf::Vector2f translate(int x, int y) { float step_x = X_DIM / TEXT_SIZE; float step_y = (Y_DIM - 12) / TEXT_SIZE; sf::Vector2f position{step_x * x, step_y * y * 2}; return position; } void SFMLBackend::write_text(int x, int y, string content, float size_mult, Value color) { sf::Vector2f position = translate(x,y); sf::Text text(font); text.setString(content); text.setCharacterSize(TEXT_SIZE * size_mult); text.setFillColor(value(color)); text.setPosition(position); window.draw(text); } sf::RectangleShape SFMLBackend::box(int x, int y, int width, int height, Value fill, Value outline, int thickness) { sf::RectangleShape box(translate(width, height)); box.setPosition(translate(x,y)); box.setOutlineColor(value(outline)); box.setOutlineThickness(thickness); box.setFillColor(value(fill)); window.draw(box); return box; } void SFMLBackend::update_entities() { window.clear(); sf::RectangleShape face_box = box(2, 2, X_ROWS/4, Y_LINES/2, Value::DARK_DARK); face_sprite->setPosition(translate(2,2)); window.draw(*face_sprite); sf::RectangleShape stats_box = box(X_ROWS/4 + 4, 2, X_ROWS - X_ROWS/4 - 5, Y_LINES/2, Value::DARK_DARK); constexpr int hp_box_len = 45; int current_hp = (float(game.hit_points) / float(game.starting_hp)) * float(hp_box_len); sf::RectangleShape hp_bar = box(2, 21, current_hp, 2, Value::LIGHT_MID, Value::LIGHT_MID, 0); sf::RectangleShape hp_box = box(2, 21, hp_box_len, 2, Value::TRANSPARENT); string status = fmt::format("HP {}\nRounds {}\nStreaks {}\nDeaths {}", game.hit_points, game.rounds, game.streak, game.deaths); write_text(X_ROWS/4 + 5, 2, status); if(buttons == Button::START) { // better thing here please } else if(buttons == Button::STOP) { clock_start = std::chrono::system_clock::now(); } auto elapsed_time = std::chrono::system_clock::now() - clock_start; string time = fmt::format("{:%H:%M:%OS}", elapsed_time); write_text(7, 14, time, 2.0f); Window_update(); } void SFMLBackend::change_face(const string name) { std::ifstream infile(".tarpit.json"); json data = json::parse(infile); auto images = data["images"]; json::string_t file_name = images[name].template get(); bool good = face_texture->loadFromFile(file_name); dbc::check(good, fmt::format("failed to load texture {}", file_name)); face_sprite->setTexture(*face_texture); } SFMLBackend::SFMLBackend(GameEngine &g) : window(sf::VideoMode({X_DIM, Y_DIM}), "Turing's Tarpit"), game(g) { std::ifstream infile(".tarpit.json"); json data = json::parse(infile); auto images = data["images"]; std::string build_name = images["building"]; face_texture = make_shared(build_name); face_sprite = make_shared(*face_texture); } /* * This makes my soul hurt. Make it stop. * * TODO: Make this more efficient, and don't display * more than 10 or so errors since more than that is * not very useful. */ void SFMLBackend::update_log(std::vector &lines) { log.clear(); for(string &line : lines) { log.push_back(line); } } void SFMLBackend::startup() { fmt::print("Setting up a window for you...\n"); std::ifstream infile(".tarpit.json"); json data = json::parse(infile); std::string font_file = data["font"]; if(!font.openFromFile(font_file)) { fmt::println("Cannot load font."); } window.setPosition({0,0}); window.setFramerateLimit(FPS); window.setVerticalSyncEnabled(true); } bool SFMLBackend::is_open() { return window.isOpen(); } void SFMLBackend::shutdown() { }