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>();
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);
}

@ -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() {

@ -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<Room> $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; }

@ -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<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) {
// TODO: this will be on each enemy not a global thing
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) {
auto &lighting = game_map.lighting();
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
&& 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<MapConfig>();
const auto& player = world.get_the<Player>();
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);
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;

@ -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);