Circle adjusted to work better but now I think hirdrac was right that it's easier to just calculate a distance from center and use that to determine light levels rather than a whole dpath.

main
Zed A. Shaw 1 month ago
parent 8a94108874
commit 9ac8da30ea
  1. 8
      lights.cpp
  2. 2
      lights.hpp
  3. 4
      main.cpp
  4. 16
      matrix.cpp
  5. 7
      matrix.hpp
  6. 2
      systems.cpp
  7. 6
      tests/matrix.cpp

@ -7,7 +7,7 @@ using std::vector;
namespace lighting { namespace lighting {
void LightRender::render_circle_light(LightSource source, Point at, PointList &has_light) { void LightRender::render_circle_light(LightSource source, Point at, PointList &has_light) {
for(matrix::circle it{$lightmap, at, source.distance + 1}; it.next();) { for(matrix::circle it{$lightmap, at, source.radius}; it.next();) {
for(int x = it.left; x < it.right; x++) { for(int x = it.left; x < it.right; x++) {
$lightmap[it.y][x] = light_level(source.strength, x, it.y); $lightmap[it.y][x] = light_level(source.strength, x, it.y);
has_light.push_back({(size_t)x, (size_t)it.y}); has_light.push_back({(size_t)x, (size_t)it.y});
@ -25,7 +25,7 @@ namespace lighting {
} }
void LightRender::render_square_light(LightSource source, Point at, PointList &has_light) { void LightRender::render_square_light(LightSource source, Point at, PointList &has_light) {
for(matrix::in_box it{$lightmap, at.x, at.y, (size_t)source.distance}; it.next();) { for(matrix::in_box it{$lightmap, at.x, at.y, (size_t)floor(source.radius)}; it.next();) {
if($paths.$paths[it.y][it.x] != WALL_PATH_LIMIT) { if($paths.$paths[it.y][it.x] != WALL_PATH_LIMIT) {
$lightmap[it.y][it.x] = light_level(source.strength, it.x, it.y); $lightmap[it.y][it.x] = light_level(source.strength, it.x, it.y);
has_light.push_back({it.x, it.y}); has_light.push_back({it.x, it.y});
@ -38,9 +38,9 @@ namespace lighting {
clear_light_target(at); clear_light_target(at);
PointList has_light; PointList has_light;
if(source.distance == 0) { if(source.radius < 1.5f) {
render_compass_light(source, at, has_light); render_compass_light(source, at, has_light);
} else if(source.distance == 1) { } else if(source.radius < 2.0f) {
render_square_light(source, at, has_light); render_square_light(source, at, has_light);
} else { } else {
render_circle_light(source, at, has_light); render_circle_light(source, at, has_light);

@ -10,7 +10,7 @@ namespace lighting {
struct LightSource { struct LightSource {
int strength = 0; // lower is better int strength = 0; // lower is better
int distance = 1; // higher is farther, in squares float radius = 1.0f; // higher is farther, in squares
}; };
const int MIN = 50; const int MIN = 50;

@ -33,7 +33,7 @@ void configure_world(DinkyECS::World &world, Map &game_map) {
world.set<Combat>(player.entity, {100, 10}); world.set<Combat>(player.entity, {100, 10});
world.set<Tile>(player.entity, {config.PLAYER_TILE}); world.set<Tile>(player.entity, {config.PLAYER_TILE});
world.set<Inventory>(player.entity, {5}); world.set<Inventory>(player.entity, {5});
world.set<LightSource>(player.entity, {6,1}); world.set<LightSource>(player.entity, {6,2.1});
auto enemy = world.entity(); auto enemy = world.entity();
world.set<Position>(enemy, {game_map.place_entity(1)}); world.set<Position>(enemy, {game_map.place_entity(1)});
@ -55,7 +55,7 @@ void configure_world(DinkyECS::World &world, Map &game_map) {
auto wall_torch = world.entity(); auto wall_torch = world.entity();
world.set<Position>(wall_torch, {game_map.place_entity(4)}); world.set<Position>(wall_torch, {game_map.place_entity(4)});
world.set<LightSource>(wall_torch, {3,4}); world.set<LightSource>(wall_torch, {3,2.4});
world.set<Tile>(wall_torch, {""}); world.set<Tile>(wall_torch, {""});
} }

@ -180,24 +180,24 @@ namespace matrix {
} }
circle::circle(Matrix &mat, Point center, int radius) : circle::circle(Matrix &mat, Point center, float radius) :
center(center), radius(radius) center_x(center.x), center_y(center.y), radius(radius)
{ {
width = matrix::width(mat); width = matrix::width(mat);
height = matrix::height(mat); height = matrix::height(mat);
top = max(int(center.y - radius), 0); top = max(int(floor(center_y - radius)), 0);
bottom = min(int(center.y + radius), height); bottom = min(int(floor(center_y + radius)), height - 1);
y = top; y = top;
} }
bool circle::next() { bool circle::next() {
y++; y++;
if(y < bottom) { if(y <= bottom) {
dy = y - center.y; dy = y - center_y;
dx = floor(sqrt(radius * radius - dy * dy)); dx = floor(sqrt(radius * radius - dy * dy));
left = max(0, int(center.x - dx)); left = max(0, int(center_x) - dx);
right = min(width, int(center.x + dx)); right = min(width, int(center_x) + dx + 1);
return true; return true;
} else { } else {
return false; return false;

@ -118,8 +118,9 @@ namespace matrix {
}; };
struct circle { struct circle {
Point center; float center_x;
int radius = 0; float center_y;
float radius = 0.0f;
int y = 0; int y = 0;
int dx = 0; int dx = 0;
int dy = 0; int dy = 0;
@ -130,7 +131,7 @@ namespace matrix {
int width = 0; int width = 0;
int height = 0; int height = 0;
circle(Matrix &mat, Point center, int radius); circle(Matrix &mat, Point center, float radius);
void update(); void update();
bool next(); bool next();
}; };

@ -144,7 +144,7 @@ void System::collision(DinkyECS::World &world, Player &player) {
world.send<Events::GUI>(Events::GUI::LOOT, entity, loot); world.send<Events::GUI>(Events::GUI::LOOT, entity, loot);
inventory.gold += loot.amount; inventory.gold += loot.amount;
light.strength = 4; light.strength = 4;
light.distance = 2; light.radius = 2.3;
collider.remove(loot_pos.location); collider.remove(loot_pos.location);
} else { } else {
println("UNKNOWN COLLISION TYPE {}", entity); println("UNKNOWN COLLISION TYPE {}", entity);

@ -226,7 +226,7 @@ TEST_CASE("prototype line algorithm", "[matrix:line]") {
} }
TEST_CASE("prototype circle algorithm", "[matrix:circle]") { TEST_CASE("prototype circle algorithm", "[matrix:circle]") {
for(int count = 0; count < 2000; count++) { for(int count = 0; count < 2; count++) {
size_t width = Random::uniform<size_t>(10, 13); size_t width = Random::uniform<size_t>(10, 13);
size_t height = Random::uniform<size_t>(10, 15); size_t height = Random::uniform<size_t>(10, 15);
int pos_mod = Random::uniform<int>(-3,3); int pos_mod = Random::uniform<int>(-3,3);
@ -234,7 +234,7 @@ TEST_CASE("prototype circle algorithm", "[matrix:circle]") {
// create a target for the paths // create a target for the paths
Point start{.x=map.width() / 2 + pos_mod, .y=map.height()/2 + pos_mod}; Point start{.x=map.width() / 2 + pos_mod, .y=map.height()/2 + pos_mod};
for(int radius = 2; radius < 10; radius++) { for(float radius = 1.0f; radius < 4.0f; radius += 0.1f) {
// use an empty map // use an empty map
Matrix result = map.walls(); Matrix result = map.walls();
@ -250,7 +250,7 @@ TEST_CASE("prototype circle algorithm", "[matrix:circle]") {
} }
} }
// matrix::dump("RESULT AFTER CIRCLE", result, start.x, start.y); matrix::dump(format("RESULT AFTER CIRCLE radius {}", radius), result, start.x, start.y);
} }
} }
} }

Loading…
Cancel
Save