Trigonometry to solve physics problem

Hi. I'm trying to move back some squares after collision, and right now it's not working too well. I believe the issue is my trigonometry code where i'm trying to find the penetration in X and Y:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
sf::Vector2<long double> Collision::getVectorDirection() const{
	long double x;
	long double y;
	long double velX = _object->getVelocity().x;
	long double velY = _object->getVelocity().y;
	long double angle = atan2(velY, velX);

	if (_side == SideOfCollision::left || _side == SideOfCollision::right){
		x = getDistance();
		y = x / cos(angle);
		return sf::Vector2<long double>(x, y);
	}
	else if (_side == SideOfCollision::top || _side == SideOfCollision::bottom){
		y = getDistance();
		x = y / sin(angle);
		return sf::Vector2<long double>(x, y);
	}
}

long double Collision::getDistance() const{
	if (_side == SideOfCollision::right){
		return _object->getRight() - _otherObject->getLeft();
	}
	if (_side == SideOfCollision::left){
		return _object->getLeft() - _otherObject->getRight();
	}
	if (_side == SideOfCollision::bottom){
		return _object->getBottom() - _otherObject->getTop();
	}
	if (_side == SideOfCollision::top){
		return _object->getTop() - _otherObject->getBottom();
	}
}


edit: Also, i should mention that i'm doing pos.x -= getVectorDirection().x and pos.y -= getVectorDirection().y when things are colliding. If they are moving towards eachother i'm using a slightly different formula, but this part has been working before except for when several things collide, which is why i'm trying this other method.
Last edited on
This is a more complex problem than it seems at first, back when I designed my first game engine this problem tripped me up for a while.

Some things to keep in mind:

1. Top down physics should probably be handled differently than sidescrolling physics. (You generally want to make it easier to get on the top of the object.
2. Simply checking for depth could mean you get "stuck" on edges, you may want to keep track of your last position and use that as a reference for which side you need to check collisions against.

What kinds of problems are you having? Is it simply not functioning? How are you determining your _side?
Hi, thanks for your answer. My problem was pretty much this problem: http://stackoverflow.com/questions/18578656/collision-between-multiple-objects?rq=1

There was a reply to do what i'm trying to do now to solve it.

My problem is that things aren't colliding properly, especially when hitting the ground or one box gets on top of another box. They slide to the left then.

This is a video of what i'm doing, but from yesterday before i tried this approach. In the end when i go in between the boxes, it freezes. But that was, as i said my old problem, which hopefuly gets solved with this new approach.

https://www.youtube.com/watch?v=IRf9N6WU6KQ

edit: Sorry i forgot to reply to how i'm determining my side.

This is the code for that:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
void PhysicsRect::updateCollisions(vector<PhysicsObject*> objectVector){
	_collision.clear();
	for (int i = 0; i < objectVector.size(); i++){
		//Collision finding code for 2 rectangles.
		if (this != objectVector[i] && objectVector[i]->identify() == ObjectType::rectangle){
			//Check if colliding
			if (contains(objectVector[i]) && collisionExists(objectVector[i], _collision) == false){

				//Determine side of collision
				long double leftPenetration = getRight() - objectVector[i]->getLeft();
				long double rightPenetration = objectVector[i]->getRight() - getLeft();
				long double topPenetration = getBottom() - objectVector[i]->getTop();
				long double bottomPenetration = objectVector[i]->getBottom() - getTop();

				if (leftPenetration < rightPenetration &&  leftPenetration < topPenetration && leftPenetration < bottomPenetration){
					_collision.push_back(Collision(*this, *objectVector[i], SideOfCollision::right));
					if (collisionExists(objectVector[i], _collisionsThisFrame) == false){
						_collisionsThisFrame.push_back(Collision(*this, *objectVector[i], SideOfCollision::right));
					}
				}
				else if (rightPenetration < leftPenetration &&  rightPenetration < topPenetration && rightPenetration < bottomPenetration){
					_collision.push_back(Collision(*this, *objectVector[i], SideOfCollision::left));
					if (collisionExists(objectVector[i], _collisionsThisFrame) == false){
						_collisionsThisFrame.push_back(Collision(*this, *objectVector[i], SideOfCollision::left));
					}
				}
				else if (topPenetration < rightPenetration &&  topPenetration < leftPenetration && topPenetration < bottomPenetration){
					_collision.push_back(Collision(*this, *objectVector[i], SideOfCollision::bottom));
					if (collisionExists(objectVector[i], _collisionsThisFrame) == false){
						_collisionsThisFrame.push_back(Collision(*this, *objectVector[i], SideOfCollision::bottom));
					}
				}
				else if (bottomPenetration < rightPenetration &&  bottomPenetration < topPenetration && bottomPenetration < leftPenetration){
					_collision.push_back(Collision(*this, *objectVector[i], SideOfCollision::top));
					if (collisionExists(objectVector[i], _collisionsThisFrame) == false){
						_collisionsThisFrame.push_back(Collision(*this, *objectVector[i], SideOfCollision::top));
					}
				}
			}
		}
	}
}
Last edited on
Ofcourse this method of side detection doesn't work at high velocities, and will return the wrong value when moving along a corner. Not sure if this will result in any bugs though.
Alright! So why are you subtracting from the perpendicular direction at all? In other words, object a is moving at a vector of 2,3, it collides with object b's top side, I move object a upwards so the bottom of a is no longer touching b, but I don't mess with the x position if there was a y collision.
Because of the problem i linked over here: http://stackoverflow.com/questions/18578656/collision-between-multiple-objects?rq=1

There are cases where you can go between other boxes like that, and then you're screwed :P. It caused me to crash alot.
I've managed to solve most problems, and now my only issue is that when colliding with top or bottom side, the boxes are pulling to the left. The only place where i handle x and y differently is in this part of the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
sf::Vector2<long double> Collision::getVectorDirection() const{
	long double x;
	long double y;
	long double velX = _object->getVelocity().x;
	long double velY = _object->getVelocity().y;
	long double angle = atan2(velY, velX);

	if (_side == SideOfCollision::left || _side == SideOfCollision::right){
		x = getDistance();
		y = x / cos(angle);
		return sf::Vector2<long double>(x, y);
	}
	else if (_side == SideOfCollision::top || _side == SideOfCollision::bottom){
		y = getDistance();
		x = y / sin(angle);
		return sf::Vector2<long double>(x, y);
	}
}


Anyone see my error? Can't remember trigonometry perfectly.
Topic archived. No new replies allowed.