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