I'm working on a top-down shooter in XNA, and I need to implement line-of-sight checking. I've come up with a solution that seems to work, but I get the nagging feeling that it won't be efficient enough to do every frame for multiple calls (the game already hiccups slightly at about 10 calls per frame).
The code is below, but my general plan was to create a series of rectangles with a width and height of zero to act as points along the sight line, and then check to see if any of these rectangles intersects a ClutterObject (an interface I defined for things like walls or other obstacles) after first screening for any that can't possibly be in the line of sight (i.e. behind the viewer) or are too far away (a concession I made for efficiency).
public static bool LOSCheck(Vector2 pos1, Vector2 pos2)
{
Vector2 currentPos = pos1;
Vector2 perMove = (pos2 - pos1);
perMove.Normalize();
HashSet<ClutterObject> clutter = new HashSet<ClutterObject>();
foreach (Room r in map.GetRooms())
{
if (r != null)
{
foreach (ClutterObject c in r.GetClutter())
{
if (c != null
&&!(c.GetRectangle().X * perMove.X < 0)
&& !(c.GetRectangle().Y * perMove.Y < 0))
{
Vector2 cVector = new Vector2(c.GetRectangle().X, c.GetRectangle().Y);
if ((cVector - pos1).Length() < 1500)
clutter.Add(c);
}
}
}
}
while (currentPos != pos2 && ((currentPos - pos1).Length() < 1500))
{
Rectangle position = new Rectangle((int)currentPos.X, (int)currentPos.Y, 0, 0);
foreach (ClutterObject c in clutter)
{
if (position.Intersects(c.GetRectangle()))
return false;
}
currentPos += perMove;
}
return true;
}
I'm sure that there's a better way to do this (or at least a way to make this method more efficient), but I'm not too used to XNA yet, so I figured it couldn't hurt to bring it here. At the very least, is there an efficient to determine which objects may be in front of the viewer with greater precision than the rather broad 90 degree window I've given myself?