#include // for operator""s, chrono_literals #include // for cout, ostream #include #include // for allocator, shared_ptr #include // for string, operator<< #include // for sleep_for #include // for hflow, paragraph, separator, hbox, vbox, filler, operator|, border, Element #include // for Render #include // for ftxui #include #include #include #include #include #include "dbc.hpp" #include "gui.hpp" using std::string; using namespace fmt; using namespace std::chrono_literals; using namespace ftxui; 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 }; sf::Color GUI::color(Value val) { return VALUES[size_t(val)]; } GUI::GUI() : game_map_(50, 20), canvas_(60 * 2, 20 * 4), window_(sf::VideoMode(1600,900), "Roguish"), screen_(0,0) { int res = hit_buf_.loadFromFile("./assets/hit.wav"); dbc::check(res, "failed to load hit.wav"); hit_sound_.setBuffer(hit_buf_); font_.loadFromFile("./assets/text.otf"); text_.setFont(font_); text_.setCharacterSize(30); text_.setFillColor(color(Value::LIGHT_DARK)); game_map_.generate(); player_.location = game_map_.place_entity(0); enemy_.location = game_map_.place_entity(1); goal_ = game_map_.place_entity(game_map_.room_count() - 1); screen_ = Screen::Create(Dimension::Full()); } void GUI::create_renderer() { map_view_ = Renderer([&] { Matrix &walls = game_map_.walls(); game_map_.set_target(player_.location); game_map_.make_paths(); Matrix &paths = game_map_.paths(); if(player_.in_state(EntityState::DEAD)) { status_text_ = "DEAD!"; } for(size_t x = 0; x < walls[0].size(); ++x) { for(size_t y = 0; y < walls.size(); ++y) { string tile = walls[y][x] == 1 ? "#" : format("{}", paths[y][x]); if(tile == "#") { canvas_.DrawText(x*2, y*4, tile); } else if(show_paths_) { //int pnum = paths[y][x]; canvas_.DrawText(x*2, y*4, tile); } else { canvas_.DrawText(x*2, y*4, "."); } } } canvas_.DrawText(enemy_.location.x*2, enemy_.location.y*4, "!"); canvas_.DrawText(player_.location.x*2, player_.location.y*4, "@"); canvas_.DrawText(goal_.x*2, goal_.y*4, "$"); return canvas(canvas_); }); document_ = Renderer([&]{ return hbox({ hflow( vbox( text(format("HP: {}", player_.hp)) | border, text(status_text_) | border ) | xflex_grow ), separator(), hbox(map_view_->Render()), }); }); } void GUI::handle_events() { sf::Event event; while(window_.pollEvent(event)) { if(event.type == sf::Event::Closed) { window_.close(); } else if(event.type == sf::Event::KeyPressed) { size_t x = player_.location.x; size_t y = player_.location.y; if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) { x -= 1; } else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) { x += 1; } else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) { y -= 1; } else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) { y += 1; } if(game_map_.inmap(x,y) && !game_map_.iswall(x,y)) { game_map_.clear_target(player_.location); player_.move({x, y}); } else { hit_sound_.play(); } // move enemy_ here bool found = game_map_.neighbors(enemy_.location, true); if(!found) { status_text_ = "ENEMY STUCK!"; } if(enemy_.location.x == player_.location.x && enemy_.location.y == player_.location.y) { player_.event(EntityEvent::HIT); } else if(goal_.x == player_.location.x && goal_.y == player_.location.y) { status_text_ = "YOU WIN!"; } } } } void GUI::render_scene() { Render(screen_, document_->Render()); std::string screen_out = screen_.ToString(); std::wstring utf8 = converter_.from_bytes(screen_out); text_.setString(utf8); text_.setPosition({0,0}); window_.clear(); window_.draw(text_); window_.display(); } int GUI::main() { create_renderer(); while(window_.isOpen()) { render_scene(); handle_events(); } return 0; }