bool Collision::PixelPerfectTest(const sf::Sprite& Object1, const sf::Sprite& Object2, sf::Uint8 AlphaLimit) { //Get AABBs of the two sprites sf::IntRect Object1AABB = GetAABB(Object1); sf::IntRect Object2AABB = GetAABB(Object2); sf::IntRect Intersection; if (Object1AABB.Intersects(Object2AABB, &Intersection)) { //We've got an intersection we need to process the pixels //In that Rect. //Bail out now if AlphaLimit = 0 if (AlphaLimit == 0) return true; //There are a few hacks here, sometimes the TransformToLocal returns negative points //Or Points outside the image. We need to check for these as they print to the error console //which is slow, and then return black which registers as a hit. sf::IntRect O1SubRect = Object1.GetSubRect(); sf::IntRect O2SubRect = Object2.GetSubRect(); sf::Vector2i O1SubRectSize(O1SubRect.GetWidth(), O1SubRect.GetHeight()); sf::Vector2i O2SubRectSize(O2SubRect.GetWidth(), O2SubRect.GetHeight()); sf::Vector2f o1v; sf::Vector2f o2v; //Loop through our pixels for (int i = Intersection.Left; i < Intersection.Right; i++) { for (int j = Intersection.Top; j < Intersection.Bottom; j++) { o1v = Object1.TransformToLocal(sf::Vector2f(i, j)); //Creating Objects each loop :( o2v = Object2.TransformToLocal(sf::Vector2f(i, j)); //Hack to make sure pixels fall withint the Sprite's Image if (o1v.x > 0 && o1v.y > 0 && o2v.x > 0 && o2v.y > 0 && o1v.x < O1SubRectSize.x && o1v.y < O1SubRectSize.y && o2v.x < O2SubRectSize.x && o2v.y < O2SubRectSize.y) { //If both sprites have opaque pixels at the same point we've got a hit if ((Object1.GetPixel(static_cast<int> (o1v.x), static_cast<int> (o1v.y)).a > AlphaLimit) && (Object2.GetPixel(static_cast<int> (o2v.x), static_cast<int> (o2v.y)).a > AlphaLimit)) { return true; } } } } return false; } return false; }
bool Bullet::detectCollision(sf::Vector2f p, const sf::Sprite& sprite) const { /* collide if the pixel is not transparent */ int img_width = sprite.GetSize().x, img_height = sprite.GetSize().y; int img_x = pos.x - p.x + img_width / 2, img_y = pos.y - p.y + img_height / 2; if (img_x < 0 || img_x >= img_width) return false; if (img_y < 0 || img_y >= img_height) return false; return sprite.GetPixel(img_x, img_y).a != 0; }
/*! * \brief Tests whether the sprite Obj1 collides with the sprite Obj2 * \param Obj1 The first of the two objects * \param Obj2 The second of the two objects * \param AlphaLimit The limit of the alpha value * \return Are the two objects are in collision (via a pixel-perfect method) ? * * It tests using a pixel-perfect condition, with AlphaLimit to test whether * the pixels are colliding. */ bool Collision::PixelTest(const sf::Sprite &Obj1, const sf::Sprite &Obj2, sf::Uint8 AlphaLimit) { sf::IntRect Obj1BoundingBox(GetBoundingBox(Obj1)); sf::IntRect Obj2BoundingBox(GetBoundingBox(Obj2)); sf::IntRect Intersection; if (!Obj1BoundingBox.Intersects(Obj2BoundingBox, &Intersection)) return false; if (AlphaLimit == 0) return true; for (int I = Intersection.Left ; I <= Intersection.Right ; ++I) { for (int J = Intersection.Top ; J <= Intersection.Bottom ; ++J) { sf::Vector2i Obj1Pix(I - Obj1BoundingBox.Left, J - Obj1BoundingBox.Top); sf::Vector2i Obj2Pix(I - Obj2BoundingBox.Left, J - Obj2BoundingBox.Top); if (Obj1Pix.x >= 0 && Obj1Pix.x < Obj1BoundingBox.GetWidth() && Obj1Pix.y >= 0 && Obj1Pix.y < Obj1BoundingBox.GetHeight() && Obj2Pix.x >= 0 && Obj2Pix.x < Obj2BoundingBox.GetWidth() && Obj2Pix.y >= 0 && Obj2Pix.y < Obj2BoundingBox.GetHeight() && Obj1.GetPixel(Obj1Pix.x, Obj1Pix.y).a > AlphaLimit && Obj2.GetPixel(Obj2Pix.x, Obj2Pix.y).a > AlphaLimit) return true; } } return false; }