I'm trying to create a Line of Sight method for an enemy class. However, it always returns false, no matter how close the player is to the enemy or whether the ray passes through any blocks to get to the player.
public virtual bool PlayerInLOS()
{
Vector3 middleOfPlayer = new Vector3(Level.Player.Position.X, Level.Player.Position.Y - Level.Player.BoundingRectangle.Height / 2, 0);
Vector3 middleOfEnemy = new Vector3(Position.X, Position.Y - localBounds.Height / 2, 0);
Vector3 direction = middleOfPlayer - middleOfEnemy;
float distanceToPlayer = Vector3.Distance(middleOfEnemy, middleOfPlayer);
if (direction != Vector3.Zero)
direction.Normalize();
Ray lineOfSight = new Ray(middleOfEnemy, direction);
float? lineToPlayer = lineOfSight.Intersects(Level.Player.BoundingBox);
foreach (BoundingBox box in Level.boundingBoxes)
{
float? distanceToIntersect = lineOfSight.Intersects(box);
if (distanceToIntersect == null)
continue;
else if (distanceToIntersect < visionLength && distanceToIntersect < distanceToPlayer && distanceToIntersect != null)
return false;
}
// Never gets to this part because it always returns before it exits the for loop
if (lineToPlayer < visionLength)
return true;
else return false;
}
Any ideas? Thanks.
I ended up fixing the problem by implementing an entirely different solution: checking every Vector2 along the distance between the enemy and the player. Works perfectly.
public bool CanSeePlayer()
{
Vector2 middleOfPlayer = new Vector2(Level.Player.Position.X, Level.Player.Position.Y - Level.Player.BoundingRectangle.Height / 2);
Vector2 middleOfEnemy = new Vector2(Position.X, Position.Y - localBounds.Height / 2);
Vector2 direction = middleOfPlayer - middleOfEnemy;
float distanceToPlayer = Vector2.Distance(middleOfEnemy, middleOfPlayer);
if (visionLength > distanceToPlayer) // If the enemy can see farther than the player's distance,
{
if (direction != Vector2.Zero)
direction.Normalize();
for (int y = 0; y < Level.tiles.GetLength(1); ++y) // loop through every tile,
{
for (int x = 0; x < Level.tiles.GetLength(0); ++x)
{
if (Level.GetCollision(x, y) != TileCollision.Passable) // and if the block is solid,
{
Vector2 currentPos = middleOfEnemy;
float lengthOfLine = 0.0f;
Rectangle tileRect = new Rectangle(x * Tile.Width, y * Tile.Height, Tile.Width, Tile.Height);
while (lengthOfLine < distanceToPlayer + 1.0f) // check every point along the line
{
currentPos += direction;
if (tileRect.Contains(currentPos)) // to see if the tile contains it.
{
return false;
}
lengthOfLine = Vector2.Distance(middleOfEnemy, currentPos);
}
}
}
}
// If every tile does not contain a single point along the line from the enemy to the player,
return true;
}
return false;
}