Beispiel #1
0
void Camera::follow(sf::Sprite& sp, float d)
{
	Vector2D vd(0, d);
	vd.rotate( sp.getRotation());

	setRotation(sp.getRotation());
	setCenter( sp.getPosition() + vd);
}
Beispiel #2
0
void Model::update( const sf::Sprite& parent)
{
	float alfa=((parent.getRotation() + rotAround)* M_PI) /180.f;
	sf::Vector2f v,p(pos.x * parent.getScale().x, pos.y * parent.getScale().y);

	v.x = p.x * cos(alfa) - p.y * sin(alfa);
	v.y = p.x * sin(alfa) + p.y * cos(alfa);

	setRotation(parent.getRotation() + rot);
	setPosition(parent.getPosition() + v + posNoRot);

	sf::Sprite::setScale(	ModelDef::scale.x * parent.getScale().x, 
							ModelDef::scale.y * parent.getScale().y	);

	//setColor( sf::Color( clR, clG, clB, clA ) );
}
void cursor::manageHit()
{
    if(hit)
    {
        hitSprite.setColor(sf::Color(255, 255, 255, 255));
        hit = false;
    }
    else if(hitSprite.getColor().a > 0)
    {
        int currentAlpha = hitSprite.getColor().a;
        a += timeModifier;
        while(a > 1)
        {
            currentAlpha -= 15;
            a -= 15;
        }
        if(a < 0)
            a = 0;

        if(currentAlpha < 0)
            currentAlpha = 0;

        hitSprite.setColor(sf::Color(255, 255, 255, currentAlpha));
    }
    hitSprite.setPosition(sprite.getPosition());
    hitSprite.setRotation(sprite.getRotation());
}
void cursor::LowAmmo(int current, int maximum)
{
    lowAmmoSprite.setPosition(sprite.getPosition());
    lowAmmoSprite.setRotation(sprite.getRotation());

    double ammoLimit = 0.3 * maximum;
    double ammoPseudoPercentage = static_cast <float> (current) / ammoLimit;
    ammoPseudoPercentage *= 255;

    lowAmmoSprite.setColor(sf::Color(255, 255, 255, 255 - ammoPseudoPercentage));
}
void cursor::HighAmmo(int current, int maximum)
{
    highAmmoSprite.setPosition(sprite.getPosition());
    highAmmoSprite.setRotation(sprite.getRotation());

    double pseudoAmmo = current - (0.7 * maximum);
    double pseudoAmmoMax = maximum - (0.7 * maximum);

    double ammoPseudoPercentage = static_cast <float> (pseudoAmmo) / pseudoAmmoMax;
    ammoPseudoPercentage *= 255;

    highAmmoSprite.setColor(sf::Color(255, 255, 255, ammoPseudoPercentage));
}
Beispiel #6
0
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::Transform objectGlobalTransform = Object.getTransform();
    sf::Vector2f pos = objectGlobalTransform.transformPoint(sf::Vector2f(0, 0));

    //Store the size so we can calculate the other corners
    sf::Vector2f size = getSize(Object);

    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));

    Left += pos.x;
    Top  += pos.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, size.x, size.y);
    //AABB.Offset(static_cast<int> (pos.x), static_cast<int> (pos.y));
    return AABB;
}
Beispiel #7
0
Collision::OBB Collision::getOBB(const sf::Sprite& object){
	//Gets the oriented bounding box of object, which is the local bounds of the object rotated
	sf::FloatRect box(object.getLocalBounds());
	maths::Vector2 topleft, botright, topright, botleft;

	float rot = object.getRotation();
	maths::Vector2 origin = object.getOrigin();
	maths::Vector2 position = object.getPosition();
	
	//Get rotated coordinates of vertices
	topleft = position + maths::Vector2(box.left, box.top).rotate(rot, origin);
	botright = position + maths::Vector2(box.left + box.width, box.top + box.height).rotate(rot, origin);
	topright = position + maths::Vector2(box.left + box.width, box.top).rotate(rot, origin);
	botleft = position + maths::Vector2(box.left, box.top + box.height).rotate(rot, origin);


	return OBB(topleft, botleft, topright, botright);
}
Beispiel #8
0
bool Collision::BoundingBoxTest(const sf::Sprite& Object1, const sf::Sprite& Object2) {

    sf::Vector2f A, B, C, BL, TR;
    sf::Vector2f HalfSize1 = getSize(Object1);
    sf::Vector2f HalfSize2 = getSize(Object2);

    //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));

}
 float                           getRotation(){ return mSprite.getRotation(); }
Beispiel #10
0
MTV Collision::getCollision(const sf::Sprite& object1,Entity::ENTITY_SHAPE shape1,const sf::Sprite& object2,Entity::ENTITY_SHAPE shape2){
	//Use Separating Axis Theorem to determine whether two objects are overlapping
	//See documentation for full explanation of this algorithm

	//Get the oriented bounding box in world coordinates (includes rotation) of objects
	OBB obb1 = getOBB(object1);
	OBB obb2 = getOBB(object2);
	float rot = object1.getRotation();

	double overlap = LONG_MAX;
	maths::Vector2 smallest(0,0);

	std::vector<maths::Vector2> axis1;
	std::vector<maths::Vector2> axis2;

	maths::Vector2 circleCentre1;
	maths::Vector2 circleCentre2;

	sf::FloatRect gbounds1 = object1.getGlobalBounds();
	sf::FloatRect gbounds2 = object2.getGlobalBounds();
	 
	//Find all the axes to check using SAT based on shapes of objects
	//Works with squares/rectangles or circles
	//Rectangles only need 2 axes because they have 2 sets of parallel lines
	if(shape1 == Entity::SHAPE_CIRCLE && shape2 == Entity::SHAPE_CIRCLE){
		//If both shapes are circles, the only axis needed is the axis between centres of circles
		circleCentre1 = maths::Vector2(gbounds1.left + gbounds1.width / 2, gbounds1.top + gbounds1.height / 2);
		circleCentre2 = maths::Vector2(gbounds2.left + gbounds2.width / 2, gbounds2.top + gbounds2.height / 2);
		axis1.push_back(maths::Vector2(circleCentre1 - circleCentre2).normalise());

	}else if(shape1 != shape2){ //if one shape is circle and one shape is rectangle
		maths::Vector2 circleCentre;
		sf::FloatRect squareRect;
		float rotation;

		//First get the unrotated bounding box and centre of the circle of the 2 objects
		if(shape1 == Entity::SHAPE_CIRCLE){
			circleCentre = maths::Vector2(gbounds1.left + gbounds1.width / 2, gbounds1.top + gbounds1.height / 2);
			circleCentre1 = circleCentre;
			squareRect = getOriginalBoundingBox(object2);
			rotation = object2.getRotation();
		}else if(shape2 == Entity::SHAPE_CIRCLE){
			circleCentre = maths::Vector2(gbounds2.left + gbounds2.width / 2, gbounds2.top + gbounds2.height / 2);
			circleCentre2 = circleCentre;
			squareRect = getOriginalBoundingBox(object1);
			rotation = object1.getRotation();
		}

		maths::Vector2 squareCentre(squareRect.left + squareRect.width / 2, squareRect.top + squareRect.height / 2);
		OBB* square = (shape1 == Entity::SHAPE_SQUARE ? &obb1 : &obb2);
		maths::Vector2 relativeCircleCentre = circleCentre.rotate(-rotation, squareCentre); //get circle centre in relation to the rotated square
		bool vertice = false;
		maths::Vector2 axis;

		maths::Vector2 topLeft(squareRect.left, squareRect.top);
		maths::Vector2 topRight(squareRect.left + squareRect.width, squareRect.top);
		maths::Vector2 botLeft(squareRect.left, squareRect.top + squareRect.height);
		maths::Vector2 botRight(squareRect.left + squareRect.width, squareRect.top + squareRect.height);

		//Get the closest vertex of the rectangle to the circle centre.
		//The axis to check is the vector between these 2 points.
		if(circleCentre.x < topLeft.x){
			if(circleCentre.y < topLeft.y){
				vertice = true;
				axis = topLeft;
			}else if(circleCentre.y >  botLeft.y){
				vertice = true;
				axis = botLeft;
			}else{
				axis = maths::Vector2(topLeft - botLeft).normalise();
			}
		}else if(circleCentre.x > topRight.x){
			if(circleCentre.y < topLeft.y){
				vertice = true;
				axis = topRight;
			}else if(circleCentre.y >  botLeft.y){
				vertice = true;
				axis = botRight;
			}else{
				axis = maths::Vector2(topRight - botRight).normalise();
			}
		}else{
			if(circleCentre.y < topLeft.y){
				axis = maths::Vector2(topRight - topLeft).normalise();
			}else if(circleCentre.y >  botLeft.y){
				axis = maths::Vector2(botLeft - botRight).normalise();
			}else{
				//contains point!
			}
		}

		if(vertice){
			axis1.push_back(maths::Vector2(circleCentre - axis).normalise());
		}else{
			axis1.push_back(maths::Vector2(topRight - topLeft).normalise());
			axis1.push_back(maths::Vector2(topRight - botRight).normalise());
		}
	}else{ //If both shapes are rectangles
		//Get vectors for sides of shapes
		maths::Vector2 Xside1(obb1.bot_left - obb1.bot_right);
		maths::Vector2 Yside1(obb1.top_left - obb1.bot_left);
		maths::Vector2 Xside2(obb2.bot_left - obb2.bot_right);
		maths::Vector2 Yside2(obb2.top_left - obb2.bot_left);

		//Axes requires are perpendicular to the sides of the shape
		//Vector2.perpendicular() normalises for greater accuracy
		axis1.push_back(Xside1.perpendicular());
		axis1.push_back(Yside1.perpendicular());
		axis2.push_back(Xside2.perpendicular());
		axis2.push_back(Yside2.perpendicular());
	}

	//We have all the axes to check.
	//Now find details on collisions with projections.

	for(int i=0;i<axis1.size();i++){
		//Get projection of axis for both shapes
		maths::Vector2 axis = axis1[i];
		Projection projection1 = project(obb1, axis);
		if(shape1 == Entity::SHAPE_CIRCLE){
			float radius = gbounds1.width / 2;
			projection1 = projectCircle(circleCentre1, radius, axis);
		}
		Projection projection2 = project(obb2, axis);
		if (shape2 == Entity::SHAPE_CIRCLE){
			float radius = gbounds2.width / 2;
			projection2 = projectCircle(circleCentre2, radius, axis);
		}

		//If a projection does not overlap, we know the objects do not collide so we can exit the function.
		//Otherwise, the MTV (minimum translation vector required to make the objects not collide) is calculated.

		if(!projection1.overlap(projection2)){
			return MTV::NONE;
		}else{
			//The axis with the smallest overlap is the axis used to calculate MTV, so record it.
			double o = projection1.getOverlap(projection2);
			if(o < overlap){
				overlap = o; //set smallest overlap
				smallest = axis; //set smallest separation vector
			}
		}
	}
	
	//Repeat the same process as above with the other set of axes.
	for(int i=0;i<axis2.size();i++){
		maths::Vector2 axis = axis2[i];
		Projection projection1 = project(obb1, axis);
		if(shape1 == Entity::SHAPE_CIRCLE){
			float radius = gbounds1.width/2;
			projection1 = projectCircle(circleCentre1, radius, axis);
		}
		Projection projection2 = project(obb2,axis);
		if(shape2 == Entity::SHAPE_CIRCLE){
			float radius = gbounds2.width / 2;
			projection2 = projectCircle(circleCentre2, radius, axis);
		}

		if(!projection1.overlap(projection2)){
			return MTV::NONE;
		}else{
			double o = projection1.getOverlap(projection2);
			if(o < overlap){
				overlap = o;
				smallest = axis;
			}
		}
	}
	//Get the vector from the centre of object 2 to the centre of object 1
	maths::Vector2 centre1 = maths::Vector2(gbounds1.left + gbounds1.width / 2, gbounds1.top + gbounds1.height / 2);
	maths::Vector2 centre2 = maths::Vector2(gbounds2.left + gbounds2.width / 2, gbounds2.top + gbounds2.height / 2);
	maths::Vector2 between = centre1 - centre2;
	//If the separation vector is in the opposite direction of 'between', flip it round by negating it
	if(between.dot(smallest) < 0){
		smallest = -smallest;
	}
	MTV mtv(overlap, smallest);
	return mtv;
}