Ok, I find the two points of the perimeter using trigonometry and I proyect it in each axis, but I fail. The collision is produced but in 2 quadrant you can enter inside the circle a little and in the other 1 the collsion is is a little bit outside. In the north east quadrant the collision is produced too many pixels outside.
PD: Sorry, works fine thank you.
float findAngle(sf::Vector2f v)
{
return atan(v.y/ v.x);
}
bool satBoxCircle(const sf::RectangleShape& object1, const sf::CircleShape& object2)
{
sf::Vector2f Points[4];
Points[0] = object1.getTransform().transformPoint(0.f, 0.f);
Points[1] = object1.getTransform().transformPoint(object1.getSize().x, 0.f);
Points[2] = object1.getTransform().transformPoint(object1.getSize().x, object1.getSize().y);
Points[3] = object1.getTransform().transformPoint(0.f, object1.getSize().y);
sf::Vector2f circle_center(Object2.getPosition().x + object2.getRadius(), object2.getPosition().y + Object2.getRadius());
//Find nearest square vertex to the circle center
int index = 0;
float min_distance = distance(Points[0], circle_center);
for (int i = 0; i < 4; i++)
{
if (distance(Points[i], circle_center) < min_distance)
{
min_distance = distance(Points[i], circle_center);
index = i;
}
}
sf::Vector2f Axis[3] = {
sf::Vector2f(Points[1].x - Points[0].x, Points[1].y - Points[0].y),
sf::Vector2f(Points[1].x - Points[2].x, Points[1].y - Points[2].y),
sf::Vector2f(Points[index].x - circle_center.x, Points[index].y - circle_center.y)
};
//Project each point into each axis and find min and max
for (int i = 0; i < 3; i++)
{
float box_min = 0.f, box_max = 0.f;
box_min = dotProduct(Points[0], Axis[i]);
box_max = box_min;
for (int j = 0; j<4; j++)
{
float projection = dotProduct(Points[j], Axis[i]);
if (projection<box_min) box_min = projection;
if (projection>box_max) box_max = projection;
}
float circle_min = 0.f, circle_max = 0.f;
sf::Vector2f point_perimeter1(circle_center.x - Object2.getRadius()*cos(findAngle(Axis[i])), circle_center.y - Object2.getRadius()*sin(findAngle(Axis[i])));
sf::Vector2f point_perimeter2(circle_center.x + Object2.getRadius()*cos(findAngle(Axis[i])), circle_center.y + Object2.getRadius()*sin(findAngle(Axis[i])));
float circle_1_projection = dotProduct(point_perimeter1, Axis[i]);
float circle_2_projection = dotProduct(point_perimeter2, Axis[i]);
if (circle_1_projection < circle_2_projection)
{
circle_min = circle_1_projection;
circle_max = circle_2_projection;
}
else
{
circle_min = circle_2_projection;
circle_max = circle_1_projection;
}
if (!((circle_min <= box_max) && (circle_max >= box_min)))
return false;
}
return true;
}