Fog of war

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
sefan
Prole
Posts: 23
Joined: Fri Jul 31, 2015 7:03 am
Contact:

Fog of war

Hi. I'm working on a top down strategy game and need some help with fog of war.

Right now i have a working basic fog of war that light up the things around the player in a circle.
But the problem is that i see thru walls. Anyone have any tips how to solve this?

I have tried to loop thru all my tiles and check if they are behind the walls or not, but ended up with 1 fps.
My ground and walls are defined in arrays based on a Tiled file:

Code: Select all

table.insert(blocks, {x = ((i-1)%80)*16, y = math.floor((i-1)/80)*16, width = 4, height = 4, hbs = false, ils = false})

My fog of war:

Code: Select all

function hbsCollision(players, blocks, width)
for ib,vb in ipairs(blocks) do
ils = false
for ip,vp in ipairs(players) do
if checkCircleColl(vp.x, vp.y, width, vb.x, vb.y, vb.width) then
vb.hbs = true
ils = true
end
end
vb.ils = ils
end
end

Sefan.se GitHub.com Itch.io
Looking for help on graphics/music/sound effects. PM me if interested.

CaptainMaelstrom
Party member
Posts: 157
Joined: Sat Jan 05, 2013 10:38 pm

Re: Fog of war

Just a quick suggestion:

Keep a table of which areas are under fog and which are not. Use that table to determine which areas to draw. Only update this table when the player moves. That way you don't have to continually calculate which areas are under fog, etc.

Xugro
Citizen
Posts: 80
Joined: Wed Sep 29, 2010 8:14 pm

Re: Fog of war

sefan wrote:Right now i have a working basic fog of war that light up the things around the player in a circle.
But the problem is that i see thru walls. Anyone have any tips how to solve this?

I have tried to loop thru all my tiles and check if they are behind the walls or not, but ended up with 1 fps.
You do not need to loop through all tiles - only those near the player.

bakpakin
Party member
Posts: 114
Joined: Sun Mar 15, 2015 9:29 am
Location: Boston

Re: Fog of war

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
end

-- 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
else
return 0, math.huge, math.huge
end
end

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

f(cx, cy)

-- 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
f(cx, cy)
else
-- Addition: include both cells when going through corners
if tx == ty then f(cx + stepX, cy) end
ty, cy = ty + dy, cy + stepY
f(cx, cy)
end
end

-- If we have not arrived to the last cell, use it
if cx ~= cx2 or cy ~= cy2 then f(cx2, cy2) end

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.
((_((_CRAYOLA_((_((_> GitHub <_((_((_CRAYOLA_((_(()

Who is online

Users browsing this forum: zorg and 43 guests