The next little game in the series where I make a fancy rogue game.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
roguish/lights.cpp

80 lines
2.5 KiB

#include "lights.hpp"
#include "constants.hpp"
#include <vector>
using std::vector;
namespace lighting {
void LightRender::render_light(LightSource source, Point at) {
Point min, max;
clear_light_target(at);
vector<Point> has_light;
matrix::in_box it{$lightmap, at.x, at.y, (size_t)source.distance};
light_box(source, at, min, max);
dbc::check(it.x+1 == min.x, "box min x different");
dbc::check(it.y == min.y, "box min y different");
dbc::check(it.right == max.x + 1, "box max.x/right different");
dbc::check(it.bottom == max.y + 1, "box max.y/bottom different");
while(it.next()) {
auto &light_row = $lightmap[it.y];
auto &path_row = $paths.$paths[it.y];
if(path_row[it.x] != WALL_PATH_LIMIT) {
light_row[it.x] = light_level(source.strength, it.x, it.y);
has_light.push_back({it.x, it.y});
}
}
const int wall_light = source.strength + WALL_LIGHT_LEVEL;
for(auto point : has_light) {
for(int j = -1;point.y+j >= 0 && j <= 1 && point.y+j < $height; j++) {
auto &path_row = $paths.$paths[point.y+j];
auto &light_row = $lightmap[point.y+j];
for(int i = -1; point.x+i >= 0 && i <= 1 && point.x+i < $width; i++) {
if(path_row[point.x+i] == WALL_PATH_LIMIT) {
light_row[point.x+i] = light_level(wall_light, point.x, point.y);
}
}
}
}
}
int LightRender::light_level(int level, size_t x, size_t y) {
size_t at = level + $paths.$paths[y][x];
int cur_level = $lightmap[y][x];
int new_level = at < lighting::LEVELS.size() ? lighting::LEVELS[at] : lighting::MIN;
return cur_level < new_level ? new_level : cur_level;
}
void LightRender::reset_light() {
for(auto &row : $lightmap) {
row.assign(row.size(), lighting::MIN);
}
}
void LightRender::clear_light_target(const Point &at) {
$paths.clear_target(at);
}
void LightRender::set_light_target(const Point &at, int value) {
$paths.set_target(at, value);
}
void LightRender::path_light(Matrix &walls) {
$paths.compute_paths(walls);
}
void LightRender::light_box(LightSource source, Point from, Point &min_out, Point &max_out) {
using std::min, std::max;
min_out.x = max(int(from.x), source.distance) - source.distance;
max_out.x = min(from.x + source.distance, $width - 1);
min_out.y = max(int(from.y), source.distance) - source.distance;
max_out.y = min(from.y + source.distance, $height - 1);
}
}