A simple approach of implementing a field of view could be to use a modified midpoint circle algorithm. You can use this algorithm to clear a circular area around a given point on a fog of war map (for example). The algorithm looks something like the this:
// This code was taken from http://en.wikipedia.org/wiki/Midpoint_circle_algorithm, ported to JavaScript and modified
// to draw a filled circle.
function drawFilledCircle(centerX, centerY, radius) {
var x = radius,
y = 0,
radiusError = 1 - x;
while (x >= y) {
drawLine(x + centerX, y + centerY, -x + centerX, y + centerY);
drawLine(y + centerX, x + centerY, -y + centerX, x + centerY);
drawLine(y + centerX, -x + centerY, -y + centerX, -x + centerY);
drawLine(x + centerX, -y + centerY, -x + centerX, -y + centerY);
y += 1;
if (radiusError < 0) {
radiusError += 2 * y + 1;
} else {
x--;
radiusError += 2 * (y - x + 1);
}
}
}
However, the code above doesn't take line of sight into consideration, meaning all tiles in range will be considered visible.
To check for line of sight between two given tiles you could use Bresenham's line algorithm instead. Here it is (again JavaScript):
// This code is based on an example taken from http://de.wikipedia.org/wiki/Bresenham-Algorithmus
function drawLine(fromX, fromY, toX, toY) {
var deltaX = Math.abs(toX - fromX),
deltaY = -Math.abs(toY - fromY),
signX = fromX < toX ? 1 : -1,
signY = fromY < toY ? 1 : -1,
error = deltaX + deltaY;
while (true) {
drawPixel(fromX, fromY);
if (fromX === toX && fromY === toY) {
break;
}
if (error * 2 > deltaY) {
error += deltaY;
fromX += signX;
}
if (error * 2 < deltaX) {
error += deltaX;
fromY += signY;
}
}
}
You could also combine both algorithms to get what you want:
- Collect all tiles within range using the first algorithm.
- Check for each collected tile if it is in line of sight using the second algorithm.
- Remove all tiles that are not in line of sight from the collection.
- You're done!
This might not be the very best solution for your problem but it might be a start (and it should work I guess). I hope it helps!