Lighting system now works and does illumination for the whole map plus entities, but not walls or multiple lights yet.

main
Zed A. Shaw 10 months ago
parent 62f986719d
commit 4ceacecfda
  1. 1
      gui.cpp
  2. 18
      map.cpp
  3. 10
      map.hpp
  4. 44
      systems.cpp
  5. 1
      systems.hpp

@ -227,6 +227,7 @@ void GUI::run_systems() {
auto player = $world.get_the<Player>(); auto player = $world.get_the<Player>();
System::motion($world, $game_map); System::motion($world, $game_map);
System::enemy_pathing($world, $game_map, player); System::enemy_pathing($world, $game_map, player);
System::lighting($world, $game_map, player);
System::collision($world, player); System::collision($world, player);
System::death($world); System::death($world);
} }

@ -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 * can run make_rooms and generate on. It will
* NOT be valid until you actually run generate. * NOT be valid until you actually run generate.
*/ */
Map::Map(size_t width, size_t height) : $limit(1000) { Map::Map(size_t width, size_t height) :
$walls = Matrix(height, MatrixRow(width, INV_WALL)); $limit(1000),
$input_map = Matrix(height, MatrixRow(width, 1)); $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() { void Map::make_paths() {

@ -32,17 +32,14 @@ void add_neighbors(Matrix &closed, size_t j, size_t i);
class Map { class Map {
public: public:
int $limit;
Matrix $input_map; Matrix $input_map;
Matrix $walls; Matrix $walls;
Matrix $paths; Matrix $paths;
Matrix $lighting; // BUG: this is not the place
std::vector<Room> $rooms; std::vector<Room> $rooms;
int $limit = 0;
// make explicit Map(Matrix input_map, Matrix walls_map, int limit);
Map(Matrix input_map, Matrix walls_map, int limit) :
$input_map(input_map),
$walls(walls_map), $limit(limit) {
}
// make random // make random
Map(size_t width, size_t height); Map(size_t width, size_t height);
@ -51,6 +48,7 @@ public:
Map(Map &map) = delete; Map(Map &map) = delete;
Matrix& paths() { return $paths; } Matrix& paths() { return $paths; }
Matrix& lighting() { return $lighting; }
Matrix& input_map() { return $input_map; } Matrix& input_map() { return $input_map; }
Matrix& walls() { return $walls; } Matrix& walls() { return $walls; }
int limit() { return $limit; } int limit() { return $limit; }

@ -16,6 +16,21 @@ using namespace fmt;
using namespace components; using namespace components;
using ftxui::Color; using ftxui::Color;
void System::lighting(DinkyECS::World &world, Map &game_map, Player &player) {
const auto& player_light = world.get<LightSource>(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) { void System::enemy_pathing(DinkyECS::World &world, Map &game_map, Player &player) {
// TODO: this will be on each enemy not a global thing // TODO: this will be on each enemy not a global thing
const auto &config = world.get_the<EnemyConfig>(); const auto &config = world.get_the<EnemyConfig>();
@ -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) { 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<Position, Tile>([&](const auto &ent, auto &pos, auto &tile) { world.query<Position, Tile>([&](const auto &ent, auto &pos, auto &tile) {
if(pos.location.x >= cam_orig.x && pos.location.x <= cam_orig.x + view_x 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) { && 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); 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 // 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, Color::RGB(255, 50, 50)); 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<MapConfig>(); const auto& config = world.get_the<MapConfig>();
const auto& player = world.get_the<Player>(); const auto& player = world.get_the<Player>();
const auto& player_position = world.get<Position>(player.entity); const auto& player_position = world.get<Position>(player.entity);
const auto& player_light = world.get<LightSource>(player.entity);
Point start = game_map.center_camera(player_position.location, view_x, view_y); Point start = game_map.center_camera(player_position.location, view_x, view_y);
auto &walls = game_map.walls(); auto &walls = game_map.walls();
auto &paths = game_map.paths(); 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_x = std::min(view_x, game_map.width() - start.x);
size_t end_y = std::min(view_y, game_map.height() - start.y); 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 x = 0; x < end_x; ++x) {
for(size_t y = 0; y < end_y; ++y) { 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; 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": "\u2591",
// "WALL_TILE": "\ua5b8", // "WALL_TILE": "\ua5b8",
int light_value = lighting[start.y+y][start.x+x];
if(tile == config.WALL_TILE) { if(tile == config.WALL_TILE) {
canvas.DrawText(x * 2, y * 4, config.WALL_TILE, [](auto &pixel) { canvas.DrawText(x * 2, y * 4, config.WALL_TILE, [](auto &pixel) {
pixel.foreground_color = Color::HSV(230, 20, 10); pixel.foreground_color = Color::HSV(230, 20, 10);
pixel.background_color = Color::HSV(230, 20, 30); pixel.background_color = Color::HSV(230, 20, 30);
}); });
} else if(DEBUG_MAP) { } else if(DEBUG_MAP) {
int dnum = paths[start.y+y][start.x+x];
string num = format("{:x}", dnum); string num = format("{:x}", dnum);
num = num.size() > 2 ? "*" : num; num = num.size() > 2 ? "*" : num;

@ -7,6 +7,7 @@
using namespace components; using namespace components;
namespace System { namespace System {
void lighting(DinkyECS::World &world, Map &game_map, Player &player);
void motion(DinkyECS::World &world, Map &game_map); void motion(DinkyECS::World &world, Map &game_map);
void collision(DinkyECS::World &world, Player &player); void collision(DinkyECS::World &world, Player &player);
void death(DinkyECS::World &world); void death(DinkyECS::World &world);