Lighting now uses pathing to determine where it can go, but _distance_ to determin strength. Looks way better.
This commit is contained in:
parent
31620adf7a
commit
f46b5f15ef
8 changed files with 72 additions and 63 deletions
37
lights.cpp
37
lights.cpp
|
@ -5,29 +5,10 @@
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
|
||||||
namespace lighting {
|
namespace lighting {
|
||||||
|
|
||||||
void LightRender::render_circle_light(LightSource source, Point at, PointList &has_light) {
|
|
||||||
for(matrix::circle it{$lightmap, at, source.radius}; it.next();) {
|
|
||||||
for(int x = it.left; x < it.right; x++) {
|
|
||||||
$lightmap[it.y][x] = light_level(source.strength, x, it.y);
|
|
||||||
has_light.push_back({(size_t)x, (size_t)it.y});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LightRender::render_compass_light(LightSource source, Point at, PointList &has_light) {
|
|
||||||
for(matrix::compass it{$lightmap, at.x, at.y}; it.next();) {
|
|
||||||
if($paths.$paths[it.y][it.x] != WALL_PATH_LIMIT) {
|
|
||||||
$lightmap[it.y][it.x] = light_level(source.strength, it.x, it.y);
|
|
||||||
has_light.push_back({it.x, it.y});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)floor(source.radius)}; 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.distance(), it.x, it.y);
|
||||||
has_light.push_back({it.x, it.y});
|
has_light.push_back({it.x, it.y});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,26 +19,22 @@ namespace lighting {
|
||||||
clear_light_target(at);
|
clear_light_target(at);
|
||||||
PointList has_light;
|
PointList has_light;
|
||||||
|
|
||||||
if(source.radius < 1.5f) {
|
render_square_light(source, at, has_light);
|
||||||
render_compass_light(source, at, has_light);
|
|
||||||
} else if(source.radius < 2.0f) {
|
|
||||||
render_square_light(source, at, has_light);
|
|
||||||
} else {
|
|
||||||
render_circle_light(source, at, has_light);
|
|
||||||
}
|
|
||||||
|
|
||||||
const int wall_light = source.strength + WALL_LIGHT_LEVEL;
|
const int wall_light = source.strength + WALL_LIGHT_LEVEL;
|
||||||
for(auto point : has_light) {
|
for(auto point : has_light) {
|
||||||
for(matrix::compass it{$lightmap, point.x, point.y}; it.next();) {
|
for(matrix::compass it{$lightmap, point.x, point.y}; 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(wall_light, point.x, point.y);
|
// BUG: include the distance in the list of walls to light
|
||||||
|
// so that they will be closer to the light level at that point
|
||||||
|
$lightmap[it.y][it.x] = light_level(wall_light, 1.0f, point.x, point.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int LightRender::light_level(int level, size_t x, size_t y) {
|
int LightRender::light_level(int level, float distance, size_t x, size_t y) {
|
||||||
size_t at = level + $paths.$paths[y][x];
|
size_t at = level + ceil(distance);
|
||||||
int cur_level = $lightmap[y][x];
|
int cur_level = $lightmap[y][x];
|
||||||
int new_level = at < lighting::LEVELS.size() ? lighting::LEVELS[at] : lighting::MIN;
|
int new_level = at < lighting::LEVELS.size() ? lighting::LEVELS[at] : lighting::MIN;
|
||||||
return cur_level < new_level ? new_level : cur_level;
|
return cur_level < new_level ? new_level : cur_level;
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace lighting {
|
||||||
void clear_light_target(const Point &at);
|
void clear_light_target(const Point &at);
|
||||||
void path_light(Matrix &walls);
|
void path_light(Matrix &walls);
|
||||||
void light_box(LightSource source, Point from, Point &min_out, Point &max_out);
|
void light_box(LightSource source, Point from, Point &min_out, Point &max_out);
|
||||||
int light_level(int level, size_t x, size_t y);
|
int light_level(int level, float distance, size_t x, size_t y);
|
||||||
void render_light(LightSource source, Point at);
|
void render_light(LightSource source, Point at);
|
||||||
void render_square_light(LightSource source, Point at, PointList &has_light);
|
void render_square_light(LightSource source, Point at, PointList &has_light);
|
||||||
void render_compass_light(LightSource source, Point at, PointList &has_light);
|
void render_compass_light(LightSource source, Point at, PointList &has_light);
|
||||||
|
|
4
main.cpp
4
main.cpp
|
@ -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,2.1});
|
world.set<LightSource>(player.entity, {6,1.0});
|
||||||
|
|
||||||
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,2.4});
|
world.set<LightSource>(wall_torch, {4,3});
|
||||||
world.set<Tile>(wall_torch, {"☀"});
|
world.set<Tile>(wall_torch, {"☀"});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
16
matrix.cpp
16
matrix.cpp
|
@ -53,9 +53,11 @@ namespace matrix {
|
||||||
return at_end(y, height);
|
return at_end(y, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
in_box::in_box(Matrix &mat, size_t from_x, size_t from_y, size_t size) {
|
in_box::in_box(Matrix &mat, size_t at_x, size_t at_y, size_t size) :
|
||||||
size_t h = mat.size();
|
from_x(at_x), from_y(at_y)
|
||||||
size_t w = mat[0].size();
|
{
|
||||||
|
size_t h = matrix::height(mat);
|
||||||
|
size_t w = matrix::width(mat);
|
||||||
|
|
||||||
// keeps it from going below zero
|
// keeps it from going below zero
|
||||||
// need extra -1 to compensate for the first next()
|
// need extra -1 to compensate for the first next()
|
||||||
|
@ -78,9 +80,17 @@ namespace matrix {
|
||||||
// if x==0 then this moves it to min_x
|
// if x==0 then this moves it to min_x
|
||||||
x = max(x, left);
|
x = max(x, left);
|
||||||
// and done
|
// and done
|
||||||
|
|
||||||
return at_end(y, bottom);
|
return at_end(y, bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float in_box::distance() {
|
||||||
|
int dx = from_x - x;
|
||||||
|
int dy = from_y - y;
|
||||||
|
|
||||||
|
return sqrt((dx * dx) + (dy * dy));
|
||||||
|
}
|
||||||
|
|
||||||
void in_box::dump() {
|
void in_box::dump() {
|
||||||
println("BOX: x={},y={}; left={},right={}; top={},bottom={}",
|
println("BOX: x={},y={}; left={},right={}; top={},bottom={}",
|
||||||
x, y, left, right, top, bottom);
|
x, y, left, right, top, bottom);
|
||||||
|
|
|
@ -37,6 +37,8 @@ namespace matrix {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct in_box {
|
struct in_box {
|
||||||
|
size_t from_x;
|
||||||
|
size_t from_y;
|
||||||
size_t x = 0; // these are set in constructor
|
size_t x = 0; // these are set in constructor
|
||||||
size_t y = 0; // again, no fancy ~ trick needed
|
size_t y = 0; // again, no fancy ~ trick needed
|
||||||
size_t left = 0;
|
size_t left = 0;
|
||||||
|
@ -45,6 +47,7 @@ namespace matrix {
|
||||||
size_t bottom = 0;
|
size_t bottom = 0;
|
||||||
|
|
||||||
in_box(Matrix &mat, size_t x, size_t y, size_t size);
|
in_box(Matrix &mat, size_t x, size_t y, size_t size);
|
||||||
|
float distance();
|
||||||
bool next();
|
bool next();
|
||||||
void dump();
|
void dump();
|
||||||
};
|
};
|
||||||
|
|
|
@ -143,8 +143,8 @@ 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 = 5;
|
||||||
light.radius = 2.3;
|
light.radius = 2;
|
||||||
collider.remove(loot_pos.location);
|
collider.remove(loot_pos.location);
|
||||||
} else {
|
} else {
|
||||||
println("UNKNOWN COLLISION TYPE {}", entity);
|
println("UNKNOWN COLLISION TYPE {}", entity);
|
||||||
|
|
|
@ -10,38 +10,36 @@
|
||||||
using namespace lighting;
|
using namespace lighting;
|
||||||
|
|
||||||
TEST_CASE("lighting a map works", "[lighting]") {
|
TEST_CASE("lighting a map works", "[lighting]") {
|
||||||
for(int i = 0; i < 5; i++) {
|
Map map(20,23);
|
||||||
Map map(20+i,23+i);
|
WorldBuilder builder(map);
|
||||||
WorldBuilder builder(map);
|
builder.generate();
|
||||||
builder.generate();
|
|
||||||
|
|
||||||
Point light1 = map.place_entity(0);
|
Point light1 = map.place_entity(0);
|
||||||
Point light2 = map.place_entity(1);
|
Point light2 = map.place_entity(1);
|
||||||
LightSource source1{7,1};
|
LightSource source1{0,2};
|
||||||
LightSource source2{3,2};
|
LightSource source2{1,3};
|
||||||
|
|
||||||
LightRender lr(map.width(), map.height());
|
LightRender lr(map.width(), map.height());
|
||||||
|
|
||||||
lr.reset_light();
|
lr.reset_light();
|
||||||
|
|
||||||
lr.set_light_target(light1);
|
lr.set_light_target(light1);
|
||||||
lr.set_light_target(light2);
|
lr.set_light_target(light2);
|
||||||
|
|
||||||
lr.path_light(map.walls());
|
lr.path_light(map.walls());
|
||||||
|
|
||||||
lr.render_light(source1, light1);
|
lr.render_light(source1, light1);
|
||||||
lr.render_light(source2, light2);
|
lr.render_light(source2, light2);
|
||||||
|
|
||||||
lr.clear_light_target(light1);
|
lr.clear_light_target(light1);
|
||||||
lr.clear_light_target(light2);
|
lr.clear_light_target(light2);
|
||||||
|
|
||||||
Matrix &lighting = lr.lighting();
|
Matrix &lighting = lr.lighting();
|
||||||
|
|
||||||
//matrix::dump("WALLS=====", map.walls());
|
matrix::dump("WALLS=====", map.walls(), light1.x, light1.y);
|
||||||
//matrix::dump("LIGHT PATHS======", lr.$paths.$paths);
|
matrix::dump("LIGHTING======", lighting, light1.x, light1.y);
|
||||||
|
|
||||||
// confirm light is set at least at and around the two points
|
// confirm light is set at least at and around the two points
|
||||||
REQUIRE(lighting[light1.y][light1.x] == lighting::LEVELS[source1.strength]);
|
REQUIRE(lighting[light1.y][light1.x] == lighting::LEVELS[source1.strength]);
|
||||||
REQUIRE(lighting[light2.y][light2.x] == lighting::LEVELS[source2.strength]);
|
REQUIRE(lighting[light2.y][light2.x] == lighting::LEVELS[source2.strength]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,6 +101,27 @@ TEST_CASE("thash matrix iterators", "[matrix]") {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("thrash box distance iterators", "[matrix:distance]") {
|
||||||
|
size_t width = Random::uniform<size_t>(10, 21);
|
||||||
|
size_t height = Random::uniform<size_t>(10, 25);
|
||||||
|
|
||||||
|
Matrix result(height, matrix::Row(width));
|
||||||
|
matrix::assign(result, 0);
|
||||||
|
|
||||||
|
size_t size = Random::uniform<int>(4, 10);
|
||||||
|
|
||||||
|
Point target{width/2, height/2};
|
||||||
|
matrix::in_box box{result, target.x, target.y, size};
|
||||||
|
while(box.next()) {
|
||||||
|
result[box.y][box.x] = box.distance();
|
||||||
|
}
|
||||||
|
|
||||||
|
matrix::dump(format("MAP {}x{} @ {},{}; BOX {}x{}; size: {}",
|
||||||
|
matrix::width(result), matrix::height(result),
|
||||||
|
target.x, target.y, box.right - box.left, box.bottom - box.top, size),
|
||||||
|
result, target.x, target.y);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("thrash box iterators", "[matrix]") {
|
TEST_CASE("thrash box iterators", "[matrix]") {
|
||||||
for(int count = 0; count < 20; count++) {
|
for(int count = 0; count < 20; count++) {
|
||||||
size_t width = Random::uniform<size_t>(1, 25);
|
size_t width = Random::uniform<size_t>(1, 25);
|
||||||
|
@ -250,7 +271,7 @@ TEST_CASE("prototype circle algorithm", "[matrix:circle]") {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
matrix::dump(format("RESULT AFTER CIRCLE radius {}", radius), result, start.x, start.y);
|
// matrix::dump(format("RESULT AFTER CIRCLE radius {}", radius), result, start.x, start.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue