Systems now control most of the game's operations and a lot of the rendering logic, this now brings in a camera so maps can be larger than the viewport.

main
Zed A. Shaw 11 months ago
parent e42647d727
commit da64e526c4
  1. 34
      gui.cpp
  2. 10
      gui.hpp
  3. 18
      map.hpp
  4. 33
      systems.cpp
  5. 3
      systems.hpp

@ -49,10 +49,10 @@ sf::Color GUI::color(Value val) {
} }
GUI::GUI() : $game_map(GAME_MAP_X, GAME_MAP_Y), GUI::GUI() : $game_map(GAME_MAP_X, GAME_MAP_Y),
$canvas(GAME_MAP_X * 2, GAME_MAP_Y * 4), $canvas(VIEW_PORT_X * 2, VIEW_PORT_Y * 4),
$window(sf::VideoMode(VIDEO_X,VIDEO_Y), "Roguish"), $window(sf::VideoMode(VIDEO_X,VIDEO_Y), "Roguish"),
$screen(SCREEN_X, SCREEN_Y), $screen(SCREEN_X, SCREEN_Y),
$map_screen(GAME_MAP_X, GAME_MAP_Y) $map_screen(VIEW_PORT_X, VIEW_PORT_Y)
{ {
int res = $hit_buf.loadFromFile("./assets/hit.wav"); int res = $hit_buf.loadFromFile("./assets/hit.wav");
dbc::check(res, "failed to load hit.wav"); dbc::check(res, "failed to load hit.wav");
@ -77,27 +77,7 @@ void GUI::create_renderer() {
auto player = $world.get<Player>(); auto player = $world.get<Player>();
$map_view = Renderer([&, player] { $map_view = Renderer([&, player] {
const auto& player_position = $world.component<Position>(player.entity); System::draw_map($world, $game_map, $canvas, VIEW_PORT_X, VIEW_PORT_Y);
Matrix &walls = $game_map.walls();
$game_map.set_target(player_position.location);
$game_map.make_paths();
Matrix &paths = $game_map.paths();
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 ? WALL_TILE : format("{}", paths[y][x]);
if(tile == WALL_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, FLOOR_TILE);
}
}
}
System::draw_entities($world, $canvas);
return canvas($canvas); return canvas($canvas);
}); });
@ -118,13 +98,15 @@ void GUI::create_renderer() {
void GUI::handle_events() { void GUI::handle_events() {
sf::Event event; sf::Event event;
auto player = $world.get<Player>();
auto& player_motion = $world.component<Motion>(player.entity);
while($window.pollEvent(event)) { while($window.pollEvent(event)) {
if(event.type == sf::Event::Closed) { if(event.type == sf::Event::Closed) {
$window.close(); $window.close();
} else if(event.type == sf::Event::KeyPressed) { } else if(event.type == sf::Event::KeyPressed) {
auto player = $world.get<Player>();
auto& player_motion = $world.component<Motion>(player.entity);
auto& player_position = $world.component<Position>(player.entity);
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) { if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) {
player_motion.dx = -1; player_motion.dx = -1;
} else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) { } else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) {
@ -135,6 +117,8 @@ void GUI::handle_events() {
player_motion.dy = 1; player_motion.dy = 1;
} }
$game_map.set_target(player_position.location);
$game_map.make_paths();
// COMPOSE system? You create a bunch of callbacks and then combine them into // COMPOSE system? You create a bunch of callbacks and then combine them into
// a single run over the data? // a single run over the data?
System::enemy_pathing($world, $game_map, player); System::enemy_pathing($world, $game_map, player);

@ -16,8 +16,10 @@
using std::string; using std::string;
using ftxui::Canvas, ftxui::Component, ftxui::Screen; using ftxui::Canvas, ftxui::Component, ftxui::Screen;
constexpr int GAME_MAP_X = 30; constexpr int GAME_MAP_X = 60;
constexpr int GAME_MAP_Y = 15; constexpr int GAME_MAP_Y = 30;
constexpr int VIEW_PORT_X = 30;
constexpr int VIEW_PORT_Y = 15;
constexpr int GAME_MAP_POS = 600; constexpr int GAME_MAP_POS = 600;
constexpr int SCREEN_X = 40; constexpr int SCREEN_X = 40;
constexpr int SCREEN_Y = 30; constexpr int SCREEN_Y = 30;
@ -25,10 +27,6 @@ constexpr int VIDEO_X = 1600;
constexpr int VIDEO_Y = 900; constexpr int VIDEO_Y = 900;
constexpr int MAP_FONT_SIZE=60; constexpr int MAP_FONT_SIZE=60;
constexpr int UI_FONT_SIZE=30; constexpr int UI_FONT_SIZE=30;
#define WALL_TILE "█"
#define FLOOR_TILE "·"
#define PLAYER_TILE "☺"
#define ENEMY_TILE "Ω"
enum class Value { enum class Value {
BLACK=0, DARK_DARK, DARK_MID, BLACK=0, DARK_DARK, DARK_MID,

@ -3,12 +3,18 @@
#include <utility> #include <utility>
#include <string> #include <string>
#include <random> #include <random>
#include <algorithm>
#include <fmt/core.h>
#define INV_WALL 0 #define INV_WALL 0
#define INV_SPACE 1 #define INV_SPACE 1
#define WALL_VALUE 1 #define WALL_VALUE 1
#define SPACE_VALUE 0 #define SPACE_VALUE 0
#define WALL_TILE "█"
#define FLOOR_TILE "·"
#define PLAYER_TILE "☺"
#define ENEMY_TILE "Ω"
struct Point { struct Point {
size_t x = 0; size_t x = 0;
@ -81,4 +87,14 @@ public:
void set_door(Room &room, int value); void set_door(Room &room, int value);
void dump(); void dump();
Point place_entity(size_t room_index); Point place_entity(size_t room_index);
Point map_to_camera(const Point &loc, const Point &cam_orig) {
return {loc.x - cam_orig.x, loc.y - cam_orig.y};
}
Point center_camera(const Point &around, size_t view_x, size_t view_y) {
size_t start_x = std::clamp(int(around.x - view_x / 2), 0, int(width() - view_x));
size_t start_y = std::clamp(int(around.y - view_y / 2), 0, int(height() - view_y));
return {start_x, start_y};
}
}; };

@ -1,4 +1,9 @@
#include "systems.hpp" #include "systems.hpp"
#include <fmt/core.h>
#include <string>
using std::string;
using namespace fmt;
void System::enemy_pathing(DinkyECS::World &world, Map &game_map, Player &player) { void System::enemy_pathing(DinkyECS::World &world, Map &game_map, Player &player) {
// move enemies system // move enemies system
@ -38,9 +43,31 @@ void System::combat(DinkyECS::World &world, Player &player) {
}); });
}; };
void System::draw_entities(DinkyECS::World &world, Map &game_map, ftxui::Canvas &canvas, const Point &cam_orig, size_t view_x, size_t view_y) {
void System::draw_entities(DinkyECS::World &world, ftxui::Canvas &canvas) {
world.system<Position, Tile>([&](const auto &ent, auto &pos, auto &tile) { world.system<Position, Tile>([&](const auto &ent, auto &pos, auto &tile) {
canvas.DrawText(pos.location.x*2, pos.location.y*4, tile.chr); if(pos.location.x >= cam_orig.x && pos.location.x <= cam_orig.x + view_x
&& pos.location.y >= cam_orig.y && pos.location.y <= cam_orig.y + view_y) {
Point loc = game_map.map_to_camera(pos.location, cam_orig);
canvas.DrawText(loc.x*2, loc.y*4, tile.chr);
}
}); });
} }
void System::draw_map(DinkyECS::World &world, Map &game_map, ftxui::Canvas &canvas, size_t view_x, size_t view_y) {
const auto& player = world.get<Player>();
const auto& player_position = world.component<Position>(player.entity);
Point start = game_map.center_camera(player_position.location, view_x, view_y);
Matrix &walls = game_map.walls();
size_t end_x = std::min(view_x, game_map.width() - start.x);
size_t end_y = std::min(view_y, game_map.height() - start.y);
for(size_t x = 0; x < end_x; ++x) {
for(size_t y = 0; y < end_y; ++y) {
string tile = walls[start.y+y][start.x+x] == 1 ? WALL_TILE : FLOOR_TILE;
canvas.DrawText(x * 2, y * 4, tile);
}
}
System::draw_entities(world, game_map, canvas, start, view_x, view_y);
}

@ -7,6 +7,7 @@
namespace System { namespace System {
void motion(DinkyECS::World &world, Map &game_map); void motion(DinkyECS::World &world, Map &game_map);
void combat(DinkyECS::World &world, Player &player); void combat(DinkyECS::World &world, Player &player);
void draw_entities(DinkyECS::World &world, ftxui::Canvas &canvas);
void enemy_pathing(DinkyECS::World &world, Map &game_map, Player &player); void enemy_pathing(DinkyECS::World &world, Map &game_map, Player &player);
void draw_map(DinkyECS::World &world, Map &game_map, ftxui::Canvas &canvas, size_t view_x, size_t view_y);
void draw_entities(DinkyECS::World &world, Map &game_map, ftxui::Canvas &canvas, const Point &cam_orig, size_t view_x, size_t view_y);
} }