#define _USE_MATH_DEFINES #include #include #include #include #include #include #include #include #include #include #include "sfmlbackend.hpp" using namespace fmt; using namespace nlohmann; using std::string; void SoundQuip::load(json &data, const char *file_key, bool loop) { auto audio = data["audio"]; json::string_t file_name = audio[file_key].template get(); if(!buffer.loadFromFile(file_name)) { println("Failed to load sound: {} with file {}", file_key, file_name); } sound.setBuffer(buffer); sound.setLoop(loop); } void SoundQuip::play() { sound.play(); } void SoundQuip::stop() { sound.stop(); } void SFMLBackend::Window_update() { window.display(); } void SFMLBackend::handle_events() { sf::Event event; // is this a main event loop while (window.pollEvent(event)) { switch(event.type) { case sf::Event::Closed: fmt::print("Exiting...\n"); window.close(); break; case sf::Event::KeyPressed: if(sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) { if(show_build_log) { window_active_out = false; } else { window.close(); } } else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Space)) { window_active_out = !window_active_out; } break; case sf::Event::MouseButtonPressed: { // rect::contains(x,y) for if mouse is in the button rect sf::Event::MouseButtonEvent btn = event.mouseButton; fmt::println("BUTTON: X={}, Y={}", btn.x, btn.y); break; } default: // do nothing break; } } } 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) { sf::Vector2f position = translate(x,y); sf::Text text; text.setFont(font); text.setString(content); text.setCharacterSize(TEXT_SIZE * size_mult); text.setFillColor(sf::Color(100, 250, 50)); text.setPosition(position); window.draw(text); } sf::RectangleShape SFMLBackend::box(int x, int y, int width, int height, sf::Color fill, sf::Color outline, int thickness) { sf::RectangleShape box(translate(width, height)); box.setPosition(translate(x,y)); box.setOutlineColor(outline); box.setOutlineThickness(thickness); box.setFillColor(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, sf::Color(100, 250, 200)); sf::RectangleShape stats_box = box(X_ROWS/4 + 4, 2, X_ROWS - X_ROWS/4 - 5, Y_LINES/2); 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, sf::Color(100, 250, 50)); sf::RectangleShape hp_box = box(2, 21, hp_box_len, 2); 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); std::time_t t = std::time(nullptr); string time = fmt::format("{:%r}", fmt::localtime(t)); write_text(2, 14, time, 2.0f); sf::RectangleShape start_btn = box(27, 16, 8, 3); write_text(29, 16, "START", 1.0f); sf::RectangleShape done_btn = box(37, 16, 8, 3); write_text(39, 16, "DONE", 1.0f); Window_update(); show_build_log = window_active_out; } SFMLBackend::SFMLBackend(GameEngine &g) : window(sf::VideoMode(X_DIM, Y_DIM), "Turing's Tarpit", sf::Style::None, settings), game(g) { } /* * This makes my sould 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"); settings.antialiasingLevel = 8; if(!font.loadFromFile("./assets/text.ttf")) { fmt::println("Cannot load font."); } window.setPosition({.x=0,.y=0}); window.setFramerateLimit(FPS); window.setVerticalSyncEnabled(true); } bool SFMLBackend::is_open() { return window.isOpen(); } void SFMLBackend::shutdown() { }