diff --git a/source/abstract/CollisionModel.cpp b/source/abstract/CollisionModel.cpp index 2de4b78..1b8794d 100644 --- a/source/abstract/CollisionModel.cpp +++ b/source/abstract/CollisionModel.cpp @@ -31,58 +31,60 @@ bool CollisionModel::testCollision(const Circle& circle, const Rectangle& rect, sf::Vector2f& offsetFirst, const sf::Vector2f& offsetSecond) { sf::Vector2f halfSize = rect.getSize() / 2.0f; - sf::Vector2f circleNewPos = circle.getPosition() + offsetFirst; sf::Vector2f rectNewPos = rect.getPosition() + offsetSecond; + sf::Vector2f circleRotatedPos = circle.getPosition() + offsetFirst - rectNewPos; + circleRotatedPos = thor::rotatedVector(circleRotatedPos, -rect.mShape.getRotation()); + circleRotatedPos += rectNewPos; // If circle center is inside rect on x plane, we just take y direction result. if (Interval::IntervalFromRadius(rectNewPos.x, halfSize.x) - .isInside(circleNewPos.x)) { + .isInside(circleRotatedPos.x)) { float overlapY = - Interval::IntervalFromRadius(circleNewPos.y, circle.getRadius()) + Interval::IntervalFromRadius(circleRotatedPos.y, circle.getRadius()) .getOverlap(Interval::IntervalFromRadius(rectNewPos.y, halfSize.y)) .getLength(); - offsetFirst.y += (circleNewPos.y > rectNewPos.y) - ? overlapY : - overlapY; + offsetFirst += ((circleRotatedPos.y > rectNewPos.y) ? 1.0f : - 1.0f) * + thor::rotatedVector(sf::Vector2f(0, overlapY), rect.mShape.getRotation()); return overlapY > 0; } // Same here (just switched x/y). else if (Interval::IntervalFromRadius(rectNewPos.y, halfSize.y) - .isInside(circleNewPos.y)) { + .isInside(circleRotatedPos.y)) { float overlapX = - Interval::IntervalFromRadius(circleNewPos.x, circle.getRadius()) + Interval::IntervalFromRadius(circleRotatedPos.x, circle.getRadius()) .getOverlap(Interval::IntervalFromRadius(rectNewPos.x, halfSize.x)) .getLength(); - offsetFirst.x += (circleNewPos.x > rectNewPos.x) - ? overlapX : - overlapX; + offsetFirst += ((circleRotatedPos.x > rectNewPos.x) ? 1.0f : - 1.0f) * + thor::rotatedVector(sf::Vector2f(overlapX, 0), rect.mShape.getRotation()); return overlapX > 0; } // Test if the circle is colliding with a corner of the rectangle, using // the same method as circle-circle collision (distance to corner instead // of radius. else { - sf::Vector2f axis(thor::unitVector(rectNewPos - circleNewPos)); + sf::Vector2f axis(thor::unitVector(rectNewPos - circleRotatedPos)); // Use correct vector for corner projections (positive/negative // direction does not matter). float rectHalfSizeProjected; - if ((circleNewPos.x > rectNewPos.x && circleNewPos.y > rectNewPos.y) || - (circleNewPos.x < rectNewPos.x && circleNewPos.y < rectNewPos.y)) + if ((circleRotatedPos.x > rectNewPos.x && circleRotatedPos.y > rectNewPos.y) || + (circleRotatedPos.x < rectNewPos.x && circleRotatedPos.y < rectNewPos.y)) rectHalfSizeProjected = thor::dotProduct(axis, halfSize); else rectHalfSizeProjected = thor::dotProduct(axis, sf::Vector2f(halfSize.x, -halfSize.y)); Interval projectedCircle = Interval::IntervalFromRadius( - thor::dotProduct(axis, circleNewPos), + thor::dotProduct(axis, circleRotatedPos), circle.getRadius()); Interval projectedRect = Interval::IntervalFromRadius( thor::dotProduct(axis, rectNewPos), rectHalfSizeProjected); // using -5: works perfectly going between corner/side - // without -5 works perfectly on corner, but skips when going in between + // without -5 works perfectly on corner, but skips when going in between tiles float overlap = projectedCircle.getOverlap(projectedRect).getLength() - 5; if (overlap > 0) - offsetFirst -= overlap * axis; + offsetFirst -= thor::rotatedVector(overlap * axis, rect.mShape.getRotation()); return overlap > 0; } } diff --git a/source/abstract/Sprite.h b/source/abstract/Sprite.h index eea6ead..8ab2b56 100755 --- a/source/abstract/Sprite.h +++ b/source/abstract/Sprite.h @@ -64,6 +64,7 @@ protected: void setPosition(const sf::Vector2f& position); private: + friend class CollisionModel; friend class World; sf::RectangleShape mShape;