FOV Errors holding me down

Today I worked on implementing FOV using the recursive shadowcasting improved as described at Roguebasin. It even had a link to a C# implementation. I have it working but there is an error in Octant 7, maybe 6 as well. I have all the code for it posted in a post Here

The red should be lit just like the green is.

 

protected bool In_Range(int x1, int y1, int x2, int y2, int Range)
{
try
{
char i = map.tile[y1, x1].Symbol;
i = map.tile[y2, x2].Symbol;
if (x1 == x2) { return Math.Abs(y1 – y2) <= Range; }
if (y1 == y2) { return Math.Abs(x1 – x2) <= Range; }
return (Math.Pow((x1 – x2), 2) + Math.Pow((y1 – y2), 2)) <= Math.Pow(Range, 2);
}
catch
{
return false;
}
}
private double Get_Slope(double x1, double y1, double x2, double y2)
{
return (x1 – x2) / (y1 – y2);
}
private double Get_SlopeInv(double x1, double y1, double x2, double y2)
{
return (y1 – y2) / (x1 – x2);
}
protected void Set_Visible(int Depth, int Octant, double StartSlope, double EndSlope)
{
int x = 0;
int y = 0;
switch (Octant)
{
case 1:
y = player.Location.Y – Depth;
x = player.Location.X – Convert.ToInt32((StartSlope * Convert.ToDouble(Depth)));
if (x < 0) break;
if (x >= map.Width) break;
if (y < 0) break;
if (y >= map.Height) break;
while (Get_Slope(x, y, player.Location.X, player.Location.Y) >= EndSlope)
{
if (In_Range(player.Location.X, player.Location.Y, x, y, player.Sight_Range))
{
if (!map.tile[y, x].Seethrough)
{
if (map.tile[y, x – 1].Seethrough)
{
Set_Visible(Depth + 1, Octant, StartSlope, Get_Slope(x – 0.5, y + 0.5, player.Location.X, player.Location.Y));
}
}
else
{
if (!map.tile[y, x – 1].Seethrough)
{
StartSlope = Get_Slope(x – 0.5, y – 0.5, player.Location.X, player.Location.Y);
}
}
map.tile[y, x].Visible = true;
if (!map.tile[y, x].Seen) { map.tile[y, x].Seen = true; }
}
x++;
}
x–;
break;
case 2:
y = player.Location.Y – Depth;
x = player.Location.X + Convert.ToInt32((StartSlope * Convert.ToDouble(Depth)));
if (x < 0) break;
if (x >= map.Width) break;
if (y < 0) break;
if (y >= map.Height) break;
while (Get_Slope(x, y, player.Location.X, player.Location.Y) <= EndSlope)
{
if (In_Range(player.Location.X, player.Location.Y, x, y, player.Sight_Range))
{
if (!map.tile[y, x].Seethrough)
{
if (map.tile[y, x + 1].Seethrough)
{
Set_Visible(Depth + 1, Octant, StartSlope, Get_Slope(x + 0.5, y + 0.5, player.Location.X, player.Location.Y));
}
}
else
{
if (!map.tile[y, x + 1].Seethrough)
{
StartSlope = -Get_Slope(x + 0.5, y – 0.5, player.Location.X, player.Location.Y);
}
}
map.tile[y, x].Visible = true;
if (!map.tile[y, x].Seen) { map.tile[y, x].Seen = true; }
}
x–;
}
x++;
break;
case 3:
x = player.Location.X + Depth;
y = player.Location.Y – Convert.ToInt32((StartSlope * Convert.ToDouble(Depth)));
if (x < 0) break;
if (x >= map.Width) break;
if (y < 0) break;
if (y >= map.Height) break;
while (Get_SlopeInv(x, y, player.Location.X, player.Location.Y) <= EndSlope)
{
if (In_Range(player.Location.X, player.Location.Y, x, y, player.Sight_Range))
{
if (!map.tile[y, x].Seethrough)
{
if (map.tile[y – 1, x].Seethrough)
{
Set_Visible(Depth + 1, Octant, StartSlope, Get_Slope(x – 0.5, y – 0.5, player.Location.X, player.Location.Y));
}
}
else
{
if (!map.tile[y – 1, x].Seethrough)
{
StartSlope = -Get_SlopeInv(x + 0.5, y – 0.5, player.Location.X, player.Location.Y);
}
}
map.tile[y, x].Visible = true;
if (!map.tile[y, x].Seen) { map.tile[y, x].Seen = true; }
}
y++;
}
y–;
break;
case 4:
x = player.Location.X + Depth;
y = player.Location.Y + Convert.ToInt32((StartSlope * Convert.ToDouble(Depth)));
if (x < 0) break;
if (x >= map.Width) break;
if (y < 0) break;
if (y >= map.Height) break;
while (Get_SlopeInv(x, y, player.Location.X, player.Location.Y) >= EndSlope)
{
if (In_Range(player.Location.X, player.Location.Y, x, y, player.Sight_Range))
{
if (!map.tile[y, x].Seethrough)
{
if (map.tile[y + 1, x].Seethrough)
{
Set_Visible(Depth + 1, Octant, StartSlope, Get_SlopeInv(x – 0.5, y + 0.5, player.Location.X, player.Location.Y));
}
}
else
{
if (!map.tile[y + 1, x].Seethrough)
{
StartSlope = Get_SlopeInv(x + 0.5, y + 0.5, player.Location.X, player.Location.Y);
}
}
map.tile[y, x].Visible = true;
if (!map.tile[y, x].Seen) { map.tile[y, x].Seen = true; }
}
y–;
}
y++;
break;
case 5:
y = player.Location.Y + Depth;
x = player.Location.X + Convert.ToInt32((StartSlope * Convert.ToDouble(Depth)));
if (x < 0) break;
if (x >= map.Width) break;
if (y < 0) break;
if (y >= map.Height) break;
while (Get_Slope(x, y, player.Location.X, player.Location.Y) >= EndSlope)
{
if (In_Range(player.Location.X, player.Location.Y, x, y, player.Sight_Range))
{
if (!map.tile[y, x].Seethrough)
{
if (map.tile[y, x + 1].Seethrough)
{
Set_Visible(Depth + 1, Octant, StartSlope, Get_Slope(x + 0.5, y – 0.5, player.Location.X, player.Location.Y));
}
}
else
{
if (!map.tile[y, x + 1].Seethrough)
{
StartSlope = Get_Slope(x + 0.5, y + 0.5, player.Location.X, player.Location.Y);
}
}
map.tile[y, x].Visible = true;
if (!map.tile[y, x].Seen) { map.tile[y, x].Seen = true; }
}
x–;
}
x++;
break;
case 6:
y = player.Location.Y + Depth;
x = player.Location.X – Convert.ToInt32((StartSlope * Convert.ToDouble(Depth)));
if (x < 0) break;
if (x >= map.Width) break;
if (y < 0) break;
if (y >= map.Height) break;
while (Get_Slope(x, y, player.Location.X, player.Location.Y) <= EndSlope)
{
if (In_Range(player.Location.X, player.Location.Y, x, y, player.Sight_Range))
{
if (!map.tile[y, x].Seethrough)
{
if (map.tile[y, x – 1].Seethrough)
{
Set_Visible(Depth + 1, Octant, StartSlope, Get_Slope(x – 0.5, y – 0.5, player.Location.X, player.Location.Y));
}
}
else
{
if (!map.tile[y, x – 1].Seethrough)
{
StartSlope = -Get_Slope(x – 0.5, y + 0.5, player.Location.X, player.Location.Y);
}
}
map.tile[y, x].Visible = true;
if (!map.tile[y, x].Seen) { map.tile[y, x].Seen = true; }
}
x++;
}
x–;
break;
case 7:
x = player.Location.X – Depth;
y = player.Location.Y + Convert.ToInt32((StartSlope * Convert.ToDouble(Depth)));
if (x < 0) break;
if (x >= map.Width) break;
if (y < 0) break;
if (y >= map.Height) break;
while (Get_SlopeInv(x, y, player.Location.X, player.Location.Y) <= EndSlope)
{
if (In_Range(player.Location.X, player.Location.Y, x, y, player.Sight_Range))
{
if (!map.tile[y, x].Seethrough)
{
if (map.tile[y + 1, x].Seethrough)
{
Set_Visible(Depth + 1, Octant, StartSlope, Get_SlopeInv(x + 0.5, y + 0.5, player.Location.X, player.Location.Y));
}
}
else
{
if (!map.tile[y + 1, x].Seethrough)
{
StartSlope = Get_SlopeInv(x – 0.5, y + 0.5, player.Location.X, player.Location.Y);
}
}
map.tile[y, x].Visible = true;
if (!map.tile[y, x].Seen) { map.tile[y, x].Seen = true; }
}
y–;
}
y++;
break;
case 8:
x = player.Location.X – Depth;
y = player.Location.Y – Convert.ToInt32((StartSlope * Convert.ToDouble(Depth)));
if (x < 0) break;
if (x >= map.Width) break;
if (y < 0) break;
if (y >= map.Height) break;
while (Get_SlopeInv(x, y, player.Location.X, player.Location.Y) >= EndSlope)
{
if (In_Range(player.Location.X, player.Location.Y, x, y, player.Sight_Range))
{
if (!map.tile[y, x].Seethrough)
{
if (map.tile[y – 1, x].Seethrough)
{
Set_Visible(Depth + 1, Octant, StartSlope, Get_SlopeInv(x + 0.5, y – 0.5, player.Location.X, player.Location.Y));
}
}
else
{
if (!map.tile[y – 1, x].Seethrough)
{
StartSlope = Get_SlopeInv(x – 0.5, y – 0.5, player.Location.X, player.Location.Y);
}
}
map.tile[y, x].Visible = true;
if (!map.tile[y, x].Seen) { map.tile[y, x].Seen = true; }
}
y++;
}
y–;
break;
}
if (x < 0) x = 0;
if (x >= map.Width) x = map.Width – 1;
if (y < 0) y = 0;
if (y >= map.Height) y = map.Height – 1;
if[1] && (map.tile[y, x].Seethrough))
{
Set_Visible(Depth + 1, Octant, StartSlope, EndSlope);
}
}
public void Calculate_Sight()
{
for (int y = 0; y < map.Height; y++)
{
for (int x = 0; x < map.Width; x++)
{
map.tile[y, x].Visible = false;
}
}
for (int Octant = 1; Octant < 9; Octant++)
{
Set_Visible(1, Octant, 1.0, 0.0);
}
}
  1. In_Range(player.Location.X, player.Location.Y, x, y, player.Sight_Range []

5 thoughts on “FOV Errors holding me down”

  1. I found the error. In the octant 7 when it made a new slope if the current tile was Seethrough and the y+1 was not it got the Get_SlopeInv and it should have been get the -Get_SlopeInv. One single ‘-‘ completely removed a full octant of my FOV but now it is fixed!

Leave a Reply