parent
10e5f53292
commit
187edb898e
@ -0,0 +1,171 @@ |
||||
#include <chrono> // for operator""s, chrono_literals |
||||
#include <iostream> // for cout, ostream |
||||
#include <fstream> |
||||
#include <memory> // for allocator, shared_ptr |
||||
#include <string> // for string, operator<< |
||||
#include <thread> // for sleep_for |
||||
|
||||
#include <ftxui/dom/elements.hpp> // for hflow, paragraph, separator, hbox, vbox, filler, operator|, border, Element |
||||
#include <ftxui/dom/node.hpp> // for Render |
||||
#include <ftxui/screen/box.hpp> // for ftxui |
||||
#include <ftxui/component/loop.hpp> |
||||
#include <ftxui/screen/color.hpp> |
||||
|
||||
#include <SFML/Window.hpp> |
||||
#include <SFML/System.hpp> |
||||
|
||||
#include <fmt/core.h> |
||||
#include "dbc.hpp" |
||||
#include "gui.hpp" |
||||
|
||||
using std::string; |
||||
using namespace fmt; |
||||
using namespace std::chrono_literals; |
||||
using namespace ftxui; |
||||
|
||||
std::array<sf::Color, 10> 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; |
||||
} |
@ -0,0 +1,54 @@ |
||||
#pragma once |
||||
#include <SFML/Audio.hpp> |
||||
#include <SFML/Graphics/Color.hpp> |
||||
#include <SFML/Graphics/Font.hpp> |
||||
#include <SFML/Graphics/RenderWindow.hpp> |
||||
#include <SFML/Graphics/Text.hpp> |
||||
#include <codecvt> |
||||
#include <ftxui/component/component.hpp> |
||||
#include <ftxui/screen/screen.hpp> |
||||
#include <ftxui/dom/canvas.hpp> |
||||
#include <locale> |
||||
#include <string> |
||||
#include "entity.hpp" |
||||
#include "map.hpp" |
||||
|
||||
using std::string; |
||||
using ftxui::Canvas, ftxui::Component, ftxui::Screen; |
||||
|
||||
enum class Value { |
||||
BLACK=0, DARK_DARK, DARK_MID, |
||||
DARK_LIGHT, MID, LIGHT_DARK, LIGHT_MID, |
||||
LIGHT_LIGHT, WHITE, TRANSPARENT |
||||
}; |
||||
|
||||
class GUI { |
||||
sf::Color color(Value val); |
||||
Map game_map_; |
||||
sf::SoundBuffer hit_buf_; |
||||
sf::Sound hit_sound_; |
||||
bool show_paths_ = false; |
||||
string status_text_ = "NOT DEAD"; |
||||
Entity player_; |
||||
Entity enemy_; |
||||
Point goal_; |
||||
Component document_; |
||||
Component map_view_; |
||||
Canvas canvas_; |
||||
sf::Font font_; |
||||
sf::Text text_; |
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter_; |
||||
sf::RenderWindow window_; |
||||
Screen screen_; |
||||
|
||||
public: |
||||
GUI(); |
||||
// disable copying
|
||||
GUI(GUI &gui) = delete; |
||||
|
||||
void create_renderer(); |
||||
void render_scene(); |
||||
void handle_events(); |
||||
|
||||
int main(); |
||||
}; |
Loading…
Reference in new issue