diff --git a/gui.cpp b/gui.cpp index 7c10b81..ce75b76 100644 --- a/gui.cpp +++ b/gui.cpp @@ -227,6 +227,7 @@ void GUI::run_systems() { auto player = $world.get_the(); System::motion($world, $game_map); System::enemy_pathing($world, $game_map, player); + System::lighting($world, $game_map, player); System::collision($world, player); System::death($world); } diff --git a/map.cpp b/map.cpp index 329ee1b..b678ca7 100644 --- a/map.cpp +++ b/map.cpp @@ -43,9 +43,21 @@ inline void add_neighbors(PointList &neighbors, Matrix &closed, size_t y, size_t * can run make_rooms and generate on. It will * NOT be valid until you actually run generate. */ -Map::Map(size_t width, size_t height) : $limit(1000) { - $walls = Matrix(height, MatrixRow(width, INV_WALL)); - $input_map = Matrix(height, MatrixRow(width, 1)); +Map::Map(size_t width, size_t height) : + $limit(1000), + $input_map(height, MatrixRow(width, 1)), + $walls(height, MatrixRow(width, INV_WALL)), + $paths(height, MatrixRow(width, 1)), + $lighting(height, MatrixRow(width, 0)) +{ +} + +// make explicit +Map::Map(Matrix input_map, Matrix walls_map, int limit) : + $limit(limit), + $input_map(input_map), + $walls(walls_map) +{ } void Map::make_paths() { diff --git a/map.hpp b/map.hpp index f17505e..1c8353c 100644 --- a/map.hpp +++ b/map.hpp @@ -32,17 +32,14 @@ void add_neighbors(Matrix &closed, size_t j, size_t i); class Map { public: + int $limit; Matrix $input_map; Matrix $walls; Matrix $paths; + Matrix $lighting; // BUG: this is not the place std::vector $rooms; - int $limit = 0; - // make explicit - Map(Matrix input_map, Matrix walls_map, int limit) : - $input_map(input_map), - $walls(walls_map), $limit(limit) { - } + Map(Matrix input_map, Matrix walls_map, int limit); // make random Map(size_t width, size_t height); @@ -51,6 +48,7 @@ public: Map(Map &map) = delete; Matrix& paths() { return $paths; } + Matrix& lighting() { return $lighting; } Matrix& input_map() { return $input_map; } Matrix& walls() { return $walls; } int limit() { return $limit; } diff --git a/systems.cpp b/systems.cpp index ae05f09..143e926 100644 --- a/systems.cpp +++ b/systems.cpp @@ -16,6 +16,21 @@ using namespace fmt; using namespace components; using ftxui::Color; +void System::lighting(DinkyECS::World &world, Map &game_map, Player &player) { + const auto& player_light = world.get(player.entity); + auto &paths = game_map.paths(); + auto &lighting = game_map.lighting(); + const int LIGHT_MIN = 10; + const int LIGHT_MAX = 110; + + for(size_t x = 0; x < game_map.width(); ++x) { + for(size_t y = 0; y < game_map.height(); ++y) { + int dnum = paths[y][x]; + lighting[y][x] = std::clamp(255 - (dnum * player_light.strength), LIGHT_MIN, LIGHT_MAX); + } + } +} + void System::enemy_pathing(DinkyECS::World &world, Map &game_map, Player &player) { // TODO: this will be on each enemy not a global thing const auto &config = world.get_the(); @@ -128,17 +143,22 @@ void System::collision(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) { + auto &lighting = game_map.lighting(); + world.query([&](const auto &ent, auto &pos, auto &tile) { 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); - // the 2 and 4 are from ftxui::Canvas since it does a kind of "subpixel" drawing + int light_value = lighting[pos.location.y][pos.location.x]; - // BUG: this color is a made up BS color for seeing entities until I can work on them - canvas.DrawText(loc.x*2, loc.y*4, tile.chr, Color::RGB(255, 50, 50)); + // the 2 and 4 are from ftxui::Canvas since it does a kind of "subpixel" drawing + canvas.DrawText(loc.x*2, loc.y*4, tile.chr, [light_value](auto &pixel) { + pixel.foreground_color = Color::HSV(255, 200, light_value + 20); + pixel.background_color = Color::HSV(30, 20, light_value / 5); + }); } }); } @@ -147,10 +167,10 @@ void System::draw_map(DinkyECS::World &world, Map &game_map, ftxui::Canvas &canv const auto& config = world.get_the(); const auto& player = world.get_the(); const auto& player_position = world.get(player.entity); - const auto& player_light = world.get(player.entity); Point start = game_map.center_camera(player_position.location, view_x, view_y); auto &walls = game_map.walls(); auto &paths = game_map.paths(); + auto &lighting = game_map.lighting(); 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); @@ -158,25 +178,17 @@ void System::draw_map(DinkyECS::World &world, Map &game_map, ftxui::Canvas &canv 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 ? config.WALL_TILE : config.FLOOR_TILE; - // the 2 and 4 are from ftxui::Canvas since it does a kind of "subpixel" drawing - // LIGHT: if tile is in light then color ++ otherwise -- - // LIGHT: is put into the/a collision map and if a cell is a light's neighbor - // it gets brighter. - const int LIGHT_MIN = 10; - const int LIGHT_MAX = 110; - - Point light_at{start.x+x, start.y+y}; - int dnum = paths[light_at.y][light_at.x]; - int light_value = std::clamp(255 - (dnum * player_light.strength), LIGHT_MIN, LIGHT_MAX); - // "WALL_TILE": "\u2591", // "WALL_TILE": "\ua5b8", + int light_value = lighting[start.y+y][start.x+x]; + if(tile == config.WALL_TILE) { canvas.DrawText(x * 2, y * 4, config.WALL_TILE, [](auto &pixel) { pixel.foreground_color = Color::HSV(230, 20, 10); pixel.background_color = Color::HSV(230, 20, 30); }); } else if(DEBUG_MAP) { + int dnum = paths[start.y+y][start.x+x]; string num = format("{:x}", dnum); num = num.size() > 2 ? "*" : num; diff --git a/systems.hpp b/systems.hpp index 96ea011..5be0af9 100644 --- a/systems.hpp +++ b/systems.hpp @@ -7,6 +7,7 @@ using namespace components; namespace System { + void lighting(DinkyECS::World &world, Map &game_map, Player &player); void motion(DinkyECS::World &world, Map &game_map); void collision(DinkyECS::World &world, Player &player); void death(DinkyECS::World &world);