I have a 2D board made with KonvaJS and tokens that can move on a square grid. I can already add fog of war and remove it manually. However, I would like to make it so, when each token moves, it reveals a certain around it, taking into account walls. Most of the work is done, however it's not entirely accurate.
Basically for each wall, I'm checking if the token is on the top/right/bottom/left of it. And then depending on which one it is, I reduce the width/height of the revealing area so it doesn't go beyond the wall. Here is an image explaining what I have and what I need
Legend:
- Gray is fog of war
- Red area is the wall/obstacle
- Token is the movable token
- Blue area is the revealed area
- Blue lines inside red area is where it intersects
- Purple lines are squares that should be revealed (aka, it should be blue)
Basically, in this case, an intersection was detected and the token is on the right side of the obstacle. So I got the right side of the wall (the x coordinate), and made the blue area starting point be that x coordinate and removed from the total width of the blue area the intersection width(the blue lines, so 1 square of width was removed).
However, because of that, the purple lines don't get filled in. Unfortunately, I can't just check the intersection points between blue and red and only remove those, because if the blue area is bigger than the red area, it would reveal the other side of the obstacle(which I don't want).
Here is the code I'm using to iterate the walls, checking if there is an intersection, checking where the token is, and then removing the width or height according to the intersection.
const tokenPosition = { x: 10, y: 10 };
const haveIntersection = (r1, r2) => !(
r2.x > r1.x + r1.width || // Compares top left with top right
r2.x + r2.width < r1.x || // Compares top right with top left
r2.y > r1.y + r1.height || // Compare bottom left with bottom right
r2.y + r2.height < r1.y // Compare bottom right with bottom left
);
walls.forEach(wall => {
const redArea = { x: wall.x, y: wall.y, width: wall.width, height: wall.height };
// blueArea has the same properties as redArea
if (haveIntersection(blueArea, redArea)) {
const tokenToTheRight = tokenPosition.x > wall.x + wall.width;
const tokenToTheLeft = tokenPosition.x < wall.x;
const tokenToTheTop = tokenPosition.y < wall.y;
const tokenToTheBottom = tokenPosition.y > wall.y + wall.height;
if (tokenToTheRight) {
let diff = wall.x + wall.width - blueArea.x;
blueArea.x = wall.x + wall.width;
blueArea.width = blueArea.width - diff;
}
if (tokenToTheLeft) {
let diff = blueArea.x + blueArea.width - wall.x;
blueArea.width = blueArea.width - diff;
}
if (tokenToTheTop) {
let diff = blueArea.y + blueArea.height - wall.y;
blueArea.height = blueArea.height - diff;
}
if (tokenToTheBottom) {
let diff = wall.y + wall.height - blueArea.y;
blueArea.y = wall.y + wall.height;
blueArea.height = blueArea.height - diff;
}
}
});
Any idea on how to fix this or if I should be taking a different approach?