There are a lot of ways to solve this problem but this is the most simple one that comes to mind.
1. Loop through all tiles in a square around your player.
2. Check if a line segment from the tile to the player intersects a wall
3. If so, set the tile to a dark tile. Otherwise, it is a light tile. Also, make sure all tiles outside the square of tiles are dark.
The hard part is clearly number 2, but here is some code from bump.lua that does exactly that.
Code: Select all
local function grid_toCell(cellSize, x, y)
return floor(x / cellSize) + 1, floor(y / cellSize) + 1
-- grid_traverse* functions are based on "A Fast Voxel Traversal Algorithm for Ray Tracing",
-- by John Amanides and Andrew Woo - http://www.cse.yorku.ca/~amana/research/grid.pdf
-- It has been modified to include both cells when the ray "touches a grid corner",
-- and with a different exit condition
local function grid_traverse_initStep(cellSize, ct, t1, t2)
local v = t2 - t1
if v > 0 then
return 1, cellSize / v, ((ct + v) * cellSize - t1) / v
elseif v < 0 then
return -1, -cellSize / v, ((ct + v - 1) * cellSize - t1) / v
return 0, math.huge, math.huge
local function grid_traverse(cellSize, x1,y1,x2,y2, f)
local cx1,cy1 = grid_toCell(cellSize, x1,y1)
local cx2,cy2 = grid_toCell(cellSize, x2,y2)
local stepX, dx, tx = grid_traverse_initStep(cellSize, cx1, x1, x2)
local stepY, dy, ty = grid_traverse_initStep(cellSize, cy1, y1, y2)
local cx,cy = cx1,cy1
-- The default implementation had an infinite loop problem when
-- approaching the last cell in some occassions. We finish iterating
-- when we are *next* to the last cell
while abs(cx - cx2) + abs(cy - cy2) > 1 do
if tx < ty then
tx, cx = tx + dx, cx + stepX
-- Addition: include both cells when going through corners
if tx == ty then f(cx + stepX, cy) end
ty, cy = ty + dy, cy + stepY
-- If we have not arrived to the last cell, use it
if cx ~= cx2 or cy ~= cy2 then f(cx2, cy2) end
That's a lot of code, but the grid_traverse function traverses all cells of size 'cellsize' between (x1, y1) and (x2, y2), and calls f(cellX, cellY) on every cell it encounters. You could pass a function to check if a certain cell was a wall in f, and if so, set the starting tile dark. There are a number ways to optimize this, but this should be quite fast if the fog of war is not huge, and you only update it when the player moves, like others suggested.
Whew, that was long, and not as simple as I imagined. The hard work is all done by bump.lua though.