#define _USE_MATH_DEFINES #include #include #include #include #include #include #include #include #include #include #include #include "sfmlbackend.hpp" #include #include #include "dbc.hpp" #include "constants.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 }; SFMLBackend::SFMLBackend(GameEngine &g) : window(sf::VideoMode({SCREEN_WIDTH, SCREEN_HEIGHT}), "Turing's Tarpit"), game(g), current_face(textures::get("building")) { } 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 = SCREEN_WIDTH / TEXT_SIZE; float step_y = (SCREEN_HEIGHT - 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); current_face.sprite->setPosition(translate(2,2)); window.draw(*current_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); } void SFMLBackend::change_face(const string& name) { current_face = textures::get(name); } /* * 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"); if(!font.openFromFile(FONT_FILE_NAME)) { fmt::println("Cannot load font."); } window.setPosition({0,0}); window.setFramerateLimit(FRAME_LIMIT); window.setVerticalSyncEnabled(VSYNC); } bool SFMLBackend::is_open() { return window.isOpen(); } void SFMLBackend::shutdown() { }