Refactor the light calculations to be part of map instead of spread out all over. Still need to bring back lighting on walls and also pathing for enemies is currently busted.

This commit is contained in:
Zed A. Shaw 2024-11-28 02:41:01 -05:00
parent 0e8a2e520a
commit 54fa1a23ce
7 changed files with 168 additions and 112 deletions

105
map.cpp
View file

@ -45,10 +45,12 @@ inline void add_neighbors(PointList &neighbors, Matrix &closed, size_t y, size_t
*/
Map::Map(size_t width, size_t height) :
$limit(1000),
$width(width),
$height(height),
$input_map(height, MatrixRow(width, 1)),
$walls(height, MatrixRow(width, INV_WALL)),
$paths(height, MatrixRow(width, 1)),
$lighting(height, MatrixRow(width, 0))
$lightmap(height, MatrixRow(width, 0))
{
}
@ -58,6 +60,8 @@ Map::Map(Matrix input_map, Matrix walls_map, int limit) :
$input_map(input_map),
$walls(walls_map)
{
$width = $walls[0].size();
$height = $walls.size();
}
void Map::make_paths() {
@ -108,10 +112,10 @@ void Map::make_paths() {
}
void Map::make_room(size_t origin_x, size_t origin_y, size_t w, size_t h) {
dbc::pre("x out of bounds", origin_x < width());
dbc::pre("y out of bounds", origin_y < height());
dbc::pre("w out of bounds", w <= width());
dbc::pre("h out of bounds", h <= height());
dbc::pre("x out of bounds", origin_x < $width);
dbc::pre("y out of bounds", origin_y < $height);
dbc::pre("w out of bounds", w <= $width);
dbc::pre("h out of bounds", h <= $height);
for(size_t y = origin_y; y < origin_y + h; ++y) {
dbc::check(y < $walls.size(), "y is out of bounds");
@ -215,7 +219,7 @@ bool Map::neighbors(Point &out, bool greater) {
}
bool Map::inmap(size_t x, size_t y) {
return x < width() && y < height();
return x < $width && y < $height;
}
void Map::set_door(Room &room, int value) {
@ -304,8 +308,8 @@ void Map::generate() {
Room root{
.x = 0,
.y = 0,
.width = width(),
.height = height()
.width = $width,
.height = $height
};
partition_map(root, 10);
@ -329,8 +333,8 @@ void Map::generate() {
walk(src.exit, target.entry);
clear_target(target.entry);
for(size_t y = 0; y < height(); ++y) {
for(size_t x = 0; x < width(); ++x) {
for(size_t y = 0; y < $height; ++y) {
for(size_t x = 0; x < $width; ++x) {
$walls[y][x] = !$walls[y][x];
}
}
@ -345,3 +349,84 @@ void Map::dump() {
dump_map("WALLS", $walls);
dump_map("INPUT", $input_map);
}
bool Map::can_move(Point move_to) {
return inmap(move_to.x, move_to.y) &&
!iswall(move_to.x, move_to.y);
}
Point Map::map_to_camera(const Point &loc, const Point &cam_orig) {
return {loc.x - cam_orig.x, loc.y - cam_orig.y};
}
Point Map::center_camera(const Point &around, size_t view_x, size_t view_y) {
int high_x = int(width() - view_x);
int high_y = int(height() - view_y);
int center_x = int(around.x - view_x / 2);
int center_y = int(around.y - view_y / 2);
// BUG: is clamp really the best thing here? this seems wrong.
size_t start_x = high_x > 0 ? std::clamp(center_x, 0, high_x) : 0;
size_t start_y = high_y > 0 ? std::clamp(center_y, 0, high_y) : 0;
return {start_x, start_y};
}
void Map::reset_light() {
for(auto &row : $lightmap) {
for(size_t i = 0; i < row.size(); i++) {
row[i] = lighting::MIN;
}
}
}
void Map::set_light_target(const Point &at, int value) {
set_target(at, value);
}
void Map::path_light() {
make_paths();
}
void Map::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, width() - 1);
}
int Map::light_level(int level, size_t x, size_t y) {
size_t at = level + $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 Map::render_light(LightSource source, Point at) {
Point min, max;
light_box(source, at, min, max);
for(size_t x = min.x; x <= max.x; ++x) {
for(size_t y = min.y; y <= max.y; ++y) {
$lightmap[y][x] = light_level(source.strength, x, y);
}
}
/*
const int UNPATH = game_map.limit();
for(auto point : has_light) {
for(int i = -1; i <= 1; i++) {
for(int j = -1; j <= 1; j++) {
if(!game_map.inmap(point.x+i, point.y+j)) continue;
if(paths[point.y+j][point.x+i] == UNPATH) {
lightmap[point.y+j][point.x+i] = lighting::MAX;
}
}
}
}
*/
}