Fog of war

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
sefan
Prole
Posts: 22
Joined: Fri Jul 31, 2015 7:03 am
Contact:

Fog of war

Post by sefan » Sat Aug 08, 2015 1:56 pm

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

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

Re: Fog of war

Post by CaptainMaelstrom » Sat Aug 08, 2015 6:14 pm

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: 61
Joined: Wed Sep 29, 2010 8:14 pm

Re: Fog of war

Post by Xugro » Sat Aug 08, 2015 6:20 pm

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.

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

Re: Fog of war

Post by bakpakin » Sun Aug 09, 2015 3:53 am

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

Post Reply

Who is online

Users browsing this forum: gutborn and 9 guests