Bala::Bala(float _v, sf::Sprite& _cannon, sf::Image& imagen) { float cannonA, cannonX, cannonY, cannonH; //Cargo sprite sprite.SetImage(imagen); sprite.SetCenter(imagen.GetWidth()/2, imagen.GetHeight()/2); //Inicializo variables dt = 0.0f; cannonA = _cannon.GetRotation(); cannonX = _cannon.GetPosition().x; cannonY = _cannon.GetPosition().y; //Tomo el tamaño sobre el eje x como el largo del cañon //porque sin rotar la misma se encuentra en horizontal cannonH = _cannon.GetSize().x; //Descompongo la velocidad inicial vx = _v * (cos(cannonA/180*PI)); vy = _v * (sin(cannonA/180*PI)); //Posicion inicial bala según la posición del cañon //usando trigonometria xi = cannonX + ((cos(cannonA/180*PI) * cannonH)); yi = cannonY - ((sin(cannonA/180*PI) * cannonH)); sprite.SetPosition(xi, yi); }
sf::IntRect Collision::GetAABB(const sf::Sprite& Object) { //Get the top left corner of the sprite regardless of the sprite's center //This is in Global Coordinates so we can put the rectangle back into the right place sf::Vector2f pos = Object.TransformToGlobal(sf::Vector2f(0, 0)); //Store the size so we can calculate the other corners sf::Vector2f size = Object.GetSize(); float Angle = Object.GetRotation(); //Bail out early if the sprite isn't rotated if (Angle == 0.0f) { return sf::IntRect(static_cast<int> (pos.x), static_cast<int> (pos.y), static_cast<int> (pos.x + size.x), static_cast<int> (pos.y + size.y)); } //Calculate the other points as vectors from (0,0) //Imagine sf::Vector2f A(0,0); but its not necessary //as rotation is around this point. sf::Vector2f B(size.x, 0); sf::Vector2f C(size.x, size.y); sf::Vector2f D(0, size.y); //Rotate the points to match the sprite rotation B = RotatePoint(B, Angle); C = RotatePoint(C, Angle); D = RotatePoint(D, Angle); //Round off to int and set the four corners of our Rect int Left = static_cast<int> (MinValue(0.0f, B.x, C.x, D.x)); int Top = static_cast<int> (MinValue(0.0f, B.y, C.y, D.y)); int Right = static_cast<int> (MaxValue(0.0f, B.x, C.x, D.x)); int Bottom = static_cast<int> (MaxValue(0.0f, B.y, C.y, D.y)); //Create a Rect from out points and move it back to the correct position on the screen sf::IntRect AABB = sf::IntRect(Left, Top, Right, Bottom); AABB.Offset(static_cast<int> (pos.x), static_cast<int> (pos.y)); return AABB; }
bool Collision::BoundingBoxTest(const sf::Sprite& Object1, const sf::Sprite& Object2) { sf::Vector2f A, B, C, BL, TR; sf::Vector2f HalfSize1 = Object1.GetSize(); sf::Vector2f HalfSize2 = Object2.GetSize(); //For somereason the Vector2d divide by operator //was misbehaving //Doing it manually HalfSize1.x /= 2; HalfSize1.y /= 2; HalfSize2.x /= 2; HalfSize2.y /= 2; //Get the Angle we're working on float Angle = Object1.GetRotation() - Object2.GetRotation(); float CosA = cos(Angle * RADIANS_PER_DEGREE); float SinA = sin(Angle * RADIANS_PER_DEGREE); float t, x, a, dx, ext1, ext2; //Normalise the Center of Object2 so its axis aligned an represented in //relation to Object 1 C = Object2.GetPosition(); C -= Object1.GetPosition(); C = RotatePoint(C, Object2.GetRotation()); //Get the Corners BL = TR = C; BL -= HalfSize2; TR += HalfSize2; //Calculate the vertices of the rotate Rect A.x = -HalfSize1.y*SinA; B.x = A.x; t = HalfSize1.x*CosA; A.x += t; B.x -= t; A.y = HalfSize1.y*CosA; B.y = A.y; t = HalfSize1.x*SinA; A.y += t; B.y -= t; t = SinA * CosA; // verify that A is vertical min/max, B is horizontal min/max if (t < 0) { t = A.x; A.x = B.x; B.x = t; t = A.y; A.y = B.y; B.y = t; } // verify that B is horizontal minimum (leftest-vertex) if (SinA < 0) { B.x = -B.x; B.y = -B.y; } // if rr2(ma) isn't in the horizontal range of // colliding with rr1(r), collision is impossible if (B.x > TR.x || B.x > -BL.x) return false; // if rr1(r) is axis-aligned, vertical min/max are easy to get if (t == 0) { ext1 = A.y; ext2 = -ext1; }// else, find vertical min/max in the range [BL.x, TR.x] else { x = BL.x - A.x; a = TR.x - A.x; ext1 = A.y; // if the first vertical min/max isn't in (BL.x, TR.x), then // find the vertical min/max on BL.x or on TR.x if (a * x > 0) { dx = A.x; if (x < 0) { dx -= B.x; ext1 -= B.y; x = a; } else { dx += B.x; ext1 += B.y; } ext1 *= x; ext1 /= dx; ext1 += A.y; } x = BL.x + A.x; a = TR.x + A.x; ext2 = -A.y; // if the second vertical min/max isn't in (BL.x, TR.x), then // find the local vertical min/max on BL.x or on TR.x if (a * x > 0) { dx = -A.x; if (x < 0) { dx -= B.x; ext2 -= B.y; x = a; } else { dx += B.x; ext2 += B.y; } ext2 *= x; ext2 /= dx; ext2 -= A.y; } } // check whether rr2(ma) is in the vertical range of colliding with rr1(r) // (for the horizontal range of rr2) return !((ext1 < BL.y && ext2 < BL.y) || (ext1 > TR.y && ext2 > TR.y)); }