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

main
Zed A. Shaw 1 week 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);

Loading…
Cancel
Save