I recently implemented the SAT algorithm into my 2D game and at first it appeared to be working fine. However, when I move around and rotate the character in and out of the wall tiles, there are some angles and positions that do not register as a collision when the player and wall tile are clearly overlapping. I created my own RotatingRectangle class that rotates around the player and is the bounding box.
I am unsure what could be causing this, or if this is just natural SAT behaviour and it does not actually detect all collisions accurately? There are no other resources online for inconsistent SAT collision detection so I am lost. I will post my code for the projections and actual collision detection in case I made a silly mistake somewhere
// Returns an array of projections, one onto each axes
public Vector2[] ProjectOntoAxes(List<Vector2> points)
{
Vector2[] projections = new Vector2[2];
for (int i = 0; i < Axes.Length; i++)
{
float max = float.MinValue;
float min = float.MaxValue;
for (int j = 0; j < points.Count; j++)
{
float res = Vector2.Dot(Axes[i], points[j]);
if (res < min)
{
min = res;
}
else if (res > max)
{
max = res;
}
}
projections[i] = new Vector2(min, max);
}
return projections;
}
private bool PlayerTileCollision(Tile tile)
{
// Check overlap on projections onto player axes
Vector2[] projections = Player.BoundingRect.ProjectOntoAxes(tile.BoundingRect.Corners);
for (int j = 0; j < projections.Length; j++)
{
if (Player.BoundingRect.Projections[j].X > projections[j].Y ||
Player.BoundingRect.Projections[j].Y < projections[j].X)
{
// No overlap can exit
return false;
}
}
// Check overlap on projections onto tile axes
projections = tile.BoundingRect.ProjectOntoAxes(Player.BoundingRect.Corners);
for (int j = 0; j < projections.Length; j++)
{
if (projections[j].X > tile.BoundingRect.Projections[j].Y ||
projections[j].Y < tile.BoundingRect.Projections[j].X)
{
// No overlap can exit
return false;
}
}
return true;
}
UDPATE: I have added code to visualise the projections and axes to see what is going on, and it appears that the projection code is not properly selecting the correct minimum and maximum values. I will try to figure out why now. (Purple lines are player projections and orange is the projections of that tile I am standing on, the top left one and the player axes can be visualised via the white lines at the origin)