C++ / SDL2 - Ball bouncing/glitching together - c++

I was trying to write some ball bouncing program in C++ using SDL2. I had a hard time getting the velocity exchange correct, but it works pretty neat so far. The only problem I have right now is that the balls are sometimes glitching/stucking together and after some seconds they release themself again.
That is my update() function which gets called every frame:
void Game::update() {
updateFPS();
checkBallCollision();
updateCanCollide();
int newtime = SDL_GetTicks();
int diff = newtime - lasttime;
if (diff > 10)
diff = 10;
for (Ball *ball : balls) {
ball->x = ball->x + ball->velocity->x * (float) diff / 100;
ball->y = ball->y + ball->velocity->y * (float) diff / 100;
checkBorderCollision(ball);
}
lasttime = newtime;
}
I guess that the balls are getting to close and don't bounce at the border of the balls. Therefore I tried to give every ball a boolean canCollide which is always true except a ball is colliding. Then it stays false until the two balls aren't overlapping anymore.
Here are my checkBallCollision() and updateCanCollide() functions:`
void Game::updateCanCollide() {
Ball **ballArr = &balls[0];
int length = balls.size();
for (int i = 0; i < length; i++) {
if (ballArr[i]->canCollide)
continue;
bool updatedCollide = true;
for (int k = i + 1; k < length; k++) {
Ball *ball1 = ballArr[i];
Ball *ball2 = ballArr[k];
int xdiff = abs(ball1->x - ball2->x);
int ydiff = abs(ball1->y - ball2->y);
float distance = sqrt(xdiff * xdiff + ydiff * ydiff);
if (distance <= ball1->radius + ball2->radius) {
updatedCollide = false;
}
}
ballArr[i]->canCollide = updatedCollide;
}
}
// do all collision checks and update the velocity
void Game::checkBallCollision() {
Ball **ballArr = &balls[0];
int length = balls.size();
for (int i = 0; i < length; i++) {
if (!ballArr[i]->canCollide)
continue;
for (int k = i + 1; k < length; k++) {
if (!ballArr[k]->canCollide)
continue;
Ball *ball1 = ballArr[i];
Ball *ball2 = ballArr[k];
int xdiff = abs(ball1->x - ball2->x);
int ydiff = abs(ball1->y - ball2->y);
float distance = sqrt(xdiff * xdiff + ydiff * ydiff);
if (distance <= ball1->radius + ball2->radius) {
// ball1 and ball2 are colliding
// update the velocity of both balls
float m1 = ball1->radius * ball1->radius * 3.14159;
float m2 = ball2->radius * ball2->radius * 3.14159;
Vector2D *v1 = new Vector2D(ball1->velocity->x, ball1->velocity->x);
Vector2D *v2 = new Vector2D(ball2->velocity->x, ball2->velocity->x);
ball1->velocity->x = ((v1->x * (m1 - m2) + 2 * m2 * v2->x) / (m1 + m2));
ball1->velocity->y = ((v1->y * (m1 - m2) + 2 * m2 * v2->y) / (m1 + m2));
ball2->velocity->x = ((v2->x * (m2 - m1) + 2 * m1 * v1->x) / (m1 + m2));
ball2->velocity->y = ((v2->y * (m2 - m1) + 2 * m1 * v1->y) / (m1 + m2));
ball1->canCollide = false;
ball2->canCollide = false;
}
}
}
}

The proper fix
The main problem is that you are letting the balls overlap each other, then update their velocities. However, if the next time step is shorter than the previous one, it can be that after updating their positions, they are still overlapping. Then you think they are colliding again, and update their velocities, but this will most likely cause then to move closer together again. This explains why they get stuck.
The proper wait to solve this is to calculate the exact point in time that two moving balls collide. This can be done analytically, for example by treating time as a third dimension, and then calculating a line-sphere intersection. If this happens during the time step, you advance the time up to the point that the collision happens, then update the velocities, and then perform the rest of the step. If you have more than two balls, then be aware that you can have more than two balls colliding all with each other in the same timestep. This is also solvable, just calculate all the time points that collisions happen, select the earliest one, update velocities at that point, and then recalculate the collision times, and so on until there are no collisions in the time step.
The workaround
Your workaround might fix two balls sticking to each other, but the result is not physically accurate. It breaks down when you start increasing the density of balls, since at some point the chance will be very high that at least one ball of a pair that should collide was in a collision in the previous timestep, and then they will all just start passing through each other all the time.
Another issue is that you have to check every possible pair of balls in updateCanCollide(), which is not efficient. There is a simpler and more common workaround to this problem: when two balls collide, after updating their velocities, immediately update their positions as well such that the balls are no longer colliding. You can try to calculate exactly how much to move them so they no longer overlap, or if you don't want to involve mathematics, you can just have a while loop to do a small step until they no longer overlap.
Other issues in your code
Note that there are also some other thing in your code that you could improve:
Don't new a temporary Vector2D, just declare it on the stack. If for some reason this is not possible, at least delete v1 and v2 afterwards.
You don't need to call abs() if you are going to square the result anyway.
Use std::hypot() to calculate the distance.
Did you write Vector2D yourself or is it from a library? If the latter, maybe it already has functions to reflect two 2D vectors? If the former, consider using a library like GLM, even if you are not using OpenGL.
Use a proper value of π. A simple, portable solution is to declare static constexpr pi = std::atan(1) * 4.

Related

2d Elastic Collision with Circles

I've seen there is a lot of posts about this already but I can't find one that relates to what I want to do,
I used the formula from here:
https://www.vobarian.com/collisions/2dcollisions2.pdf
As well as this one:
https://www.plasmaphysics.org.uk/programs/coll2d_cpp.htm
I think they area basically the same thing, now my problem is one of my circles is always static, and what I want is when the other circle hits it straight on, I want it to bounce back with the same speed, but these formulas have the circle stop still, presumably as it would pass it's energy to the other circle which would then move away.
I tried doing things like bounce = vel.x pre collision - vel.y post collision and add or subtract that to vel.x post collision and it kinda works but not really, the angles are wrong and depending on which direction the ball is coming from it may bounce up instead of down, left instead of right,
would probably require a lot of if/else statements to get to work at all.
Can someone suggest something?
here's the code for the function :
void Collision2(sf::CircleShape* b1, sf::CircleShape* b2, sf::Vector2f vel1,sf::Vector2f& vel2) {
//vel1 is 0,0 but i might want to use it later
//mass
float m1 = 10;
float m2 = 10;
//normal vector
sf::Vector2f nVec((b2->getPosition().x - b1->getPosition().x), (b2->getPosition().y - b1->getPosition().y));
//unit vector
sf::Vector2f uNVec(nVec / sqrt((nVec.x * nVec.x) + (nVec.y * nVec.y)));
//unit tangent vec
sf::Vector2f uTVec(-uNVec.y, uNVec.x);
float v1n = (uNVec.x * vel1.x) + (uNVec.y * vel1.y);
float v2n = (uNVec.x * vel2.x) + (uNVec.y * vel2.y);
float v1t = uTVec.x * vel1.x + uTVec.y * vel2.y;
float v2t = (uTVec.x * vel2.x) + (uTVec.y * vel2.y);
//v1t and v1n after collision
float v1tN = v1t;
float v2tN = v2t;
float v1nN = (v1n * (m1 - m2) + (2 * m2) * v2n) / (m1 + m2);
float v2nN = (v2n * (m2 - m1) + (2 * m1) * v1n) / (m1 + m2);
//new velocities
sf::Vector2f vel1N(v1nN*uNVec);
sf::Vector2f vel1tN(v1tN * uTVec);
sf::Vector2f vel2N(v2nN * uNVec);
sf::Vector2f vel2tN(v2tN * uTVec);
vel1 = (vel1N + vel1tN);
vel2 = (vel2N + vel2tN);
}
Physics part
The sources you added illustrate the physics behind it very well. when the two balls collide they transfer momentum between them. In an elastic collision this transfer keeps the energy of the system, the same.
We can think of the collision in terms of inertia and momentum, rather than starting from velocity. The kinetic energy of a body is generally p^2/(2m), so if we transfer dp from the moving body then we will have change in energy: dE = -pdp/m + dp^2/(2m) + dp^2/(2M) = 0. Here m is the moving and M is the stationary mass. Rearranging gives pdp/m = dp^2*(1/(2m) + 1/(2M)). We can consider m = M yielding p = dp (i.e. All moment is transferred (Note: this is a simplistic view, only dealing with head on collisions)). In the limit where the stationary object is massive however (M >> m) the result will be dp = 2p, simply bouncing off.
Programming
You can achieve the results by setting M to the maximum allowed float value (if I recall 1/inf == NaN in the IEEE standard so that doesn't work unfortunately). Alternatively you can do the collision within the circle by creating custom classes like:
class Circle : public sf::CircleShape{
public:
virtual collide (Circle*);
}
class StaticCircle : public Circle{
public:
collide (Circle*) override;
}
in the second one you can omit any terms where you divide by the mass of the circle, as it is in essence infinite.

Pre-Collision Object Staging

I am making a billiards game. Currently, when one ball collides with another at high speed, the collision is not always calculated correctly. I know what the issue is, but I'm not 100% sure how to fix it.
Say two balls are traveling with these velocities:
More often than not, when the collision is detected, the balls will have some overlap between them that looks like this:
Currently, my physics engine will handle the collision at this moment in time. This will not give the desired result since this is NOT where the balls collide in reality - balls don't go through one another. So, we need back up the balls to where they really collide. That would look like this:
I am looking for an efficient algorithm that would help me do this. Currently, I have a very naive and inefficient method - I move both balls to their locations just before the collision and take very small steps toward the moment of collision. Of course, this is very inefficient. Here is what it looks like:
void CBallCollision::StageCollision()
{
double sumOfRadii = mBall1->GetRadius() + mBall2->GetRadius();
mBall1->SetCenter(mBall1->GetLastLocationOnTable().first, mBall1->GetLastLocationOnTable().second);
mBall2->SetCenter(mBall2->GetLastLocationOnTable().first, mBall2->GetLastLocationOnTable().second);
double timeStep = 0.008;
double tolerance = 0.1 * min(mBall1->GetRadius(), mBall2->GetRadius());
int iter = 0;
while (GetDistance() > sumOfRadii)
{
double xGoal1 = mBall1->GetX() + mBall1->GetVelocityX() * timeStep;
double yGoal1 = mBall1->GetY() + mBall1->GetVelocityY() * timeStep;
pair<double, double> newCoords1 = mBall1->LinearInterpolate(xGoal1, yGoal1);
double xGoal2 = mBall2->GetX() + mBall2->GetVelocityX() * timeStep;
double yGoal2 = mBall2->GetY() + mBall2->GetVelocityY() * timeStep;
pair<double, double> newCoords2 = mBall2->LinearInterpolate(xGoal2, yGoal2);
double dist = (pow(newCoords1.first - newCoords2.first, 2) + pow(newCoords1.second - newCoords2.second, 2));
if (abs(dist - sumOfRadii) > tolerance)
{
timeStep *= 0.5;
}
else
{
mBall1->SetX(newCoords1.first);
mBall1->SetY(newCoords1.second);
mBall2->SetX(newCoords2.first);
mBall2->SetY(newCoords2.second);
}
iter++;
if (iter > 1000)
{
break;
}
}
}
If I don't put an upper bound on the number of iterations, the program crashes. I'm sure there is a much more efficient way of going about this. Any help is appreciated.

Repulsion Vector

I am trying to implement a basic AI for a Turrets game in SFML and C++ and I have some problems.
This AI follows some waypoints stablished in a Bezier Courve.
In first place, this path was followed only by one enemy. For this purpose, the enemy has to calculate his distance between his actual position
to the next waypoint he has to pick.
If the distance is less than a specific value we stablish, then, we get to the next point. This will repeat until the final destination is reached. (in the submitting code, forget about the var m_go)
Okay, our problem gets when we spawn several enemies and all have to follow the same path, because it produces a bad visual effect (everyone gets upside another).
In order to solve this visual problem, we have decided to use a repulsion vector. The calculus gets like this: representation of what we want
As you can see, we calculate the repulsion vector with the inverse of the distance between the enemy and his nearest neighbor.
Then, we get it applying this to the "theorical" direction, by adding it, and we get a resultant, which is the direction that
our enemy has to follow to not "collide" with it's neighbors.
But, our issue comes here:
The enemys get sepparated in the middle of the curve and, as we spawn more enemys, the speed of all of them increases dramatically (including the enemies that don't calculate the repuslion vector).
1 - Is it usual that this sepparation occours in the middle of the trajectory?
2 - Is it there a way to control this direction without the speed getting affected?
3 - Is it there any alternative to this theory?
I submit the code below (There is a variable in Spanish [resultante] which it means resultant in English):
if (!m_pathCompleted) {
if (m_currentWP == 14 && m_cambio == true) {
m_currentWP = 0;
m_path = m_pathA;
m_cambio = false;
}
if (m_neighbors.size() > 1) {
for (int i = 0; i < m_neighbors.size(); i++) {
if (m_enemyId != m_neighbors[i]->GetId()) {
float l_nvx = m_neighbors[i]->GetSprite().getPosition().x - m_enemySprite.getPosition().x;
float l_nvy = m_neighbors[i]->GetSprite().getPosition().y - m_enemySprite.getPosition().y;
float distance = std::sqrt(l_nvx * l_nvx + l_nvy * l_nvy);
if (distance < MINIMUM_NEIGHBOR_DISTANCE) {
l_nvx *= -1;
l_nvy *= -1;
float l_vx = m_path[m_currentWP].x - m_enemySprite.getPosition().x;
float l_vy = m_path[m_currentWP].y - m_enemySprite.getPosition().y;
float l_resultanteX = l_nvx + l_vx;
float l_resultanteY = l_nvy + l_vy;
float l_waypointDistance = std::sqrt(l_resultanteX * l_resultanteX + l_resultanteY * l_resultanteY);
if (l_waypointDistance < MINIMUM_WAYPOINT_DISTANCE) {
if (m_currentWP == m_path.size() - 1) {
std::cout << "\n";
std::cout << "[GAME OVER]" << std::endl;
m_go = false;
m_pathCompleted = true;
} else {
m_currentWP++;
}
}
if (l_waypointDistance > MINIMUM_WAYPOINT_DISTANCE) {
l_resultanteX = l_resultanteX / l_waypointDistance;
l_resultanteY = l_resultanteY / l_waypointDistance;
m_enemySprite.move(ENEMY_SPEED * l_resultanteX * dt, ENEMY_SPEED * l_resultanteY * dt);
}
} else {
float vx = m_path[m_currentWP].x - m_enemySprite.getPosition().x;
float vy = m_path[m_currentWP].y - m_enemySprite.getPosition().y;
float len = std::sqrt(vx * vx + vy * vy);
if (len < MINIMUM_WAYPOINT_DISTANCE) {
if (m_currentWP == m_path.size() - 1) {
std::cout << "\n";
std::cout << "[GAME OVER]" << std::endl;
m_go = false;
m_pathCompleted = true;
} else {
m_currentWP++;
}
}
if (len > MINIMUM_WAYPOINT_DISTANCE) {
vx = vx / len;
vy = vy / len;
m_enemySprite.move(ENEMY_SPEED * vx * dt, ENEMY_SPEED * vy * dt);
}
}
}
}
} else {
float vx = m_path[m_currentWP].x - m_enemySprite.getPosition().x;
float vy = m_path[m_currentWP].y - m_enemySprite.getPosition().y;
float len = std::sqrt(vx * vx + vy * vy);
if (len < MINIMUM_WAYPOINT_DISTANCE) {
if (m_currentWP == m_path.size() - 1) {
std::cout << "\n";
std::cout << "[GAME OVER]" << std::endl;
m_go = false;
m_pathCompleted = true;
} else {
m_currentWP++;
}
}
if (len > MINIMUM_WAYPOINT_DISTANCE) {
vx = vx / len;
vy = vy / len;
m_enemySprite.move(ENEMY_SPEED * vx * dt, ENEMY_SPEED * vy * dt);
}
}
}
I will try to answer your questions one by one, but first, I don't see anything terribly wrong in the code, so it could be simply a set of non contemplated situations.
1 - Is it usual that this sepparation occours in the middle of the
trajectory?
Well, you're applying repulsion forces to every enemy based on distance of near enough others. If something weird happens or if you're moving them more than necessary, could result on a considerable deviation from their original trajectory.
2 - Is it there a way to control this direction without the speed
getting affected?
In this line
m_enemySprite.move(ENEMY_SPEED * l_resultanteX * dt, ENEMY_SPEED * l_resultanteY * dt);
we see you're, in fact, applying that repulsion force based on l_resultante vector. That vector depends directly on l_nv (repulsion vector), which its module (or length) is proportional to the distance between this (enemy you are processing now) and other (the neighbor). As you're multiplying this vector by the speed of the enemy (a constant value), greater the distance, greater the force applied and more separation will be between them.
I suggest you to:
Normalize the vector l_nv (Easier): This is, force it to have module 1. With this solution every enemy will be pushed with the same force (basically ENEMY_SPEED) but in proper direction.
Inverse the vector l_nv (Little harder): If you apply this vector inversely proportional to the distance (module = 1/distance), they will behave the opposite and they will be pushed less if they are farther from each other.
Also consider that you are applying forces consecutively and you're making them effective by every neighbor processed. This implies something undesirable. If you push an enemy, this force could move it into a location where a future enemy (in the for loop) could push it maybe more than before. If this effect concatenates several times, could trigger a chain reaction where your enemy is pushed more and more. This effect will be amplified if you're applying the forces proportional to the distance.
3 - Is it there any alternative to this theory?
I actually run out of ideas, but I left this space here if someone want to edit the answer and suggest something

how to avoid clutch billiard balls?

I'm working on the simple behaviour of billiard balls in a collision with each other. All works normal, but there was a problem when facing a few easy balls is the effect of coupling balls and they're cool with each other. Tell me how to prevent this.
bool MGBilliard::CollisingBall(CCPoint curr_point, CCPoint next_point)
{
float dx = next_point.x - (curr_point.x + dvdt.x);
float dy = next_point.y - (curr_point.y - dvdt.y);
float d = dx*dx+dy*dy;
return d <= BALL_RADIUS * BALL_RADIUS;
}
double MGBilliard::angleCollisionBalls(Ball* current, Ball* next)
{
double na;
double dx = fabs(next->location.x - current->location.x);
double dy = fabs(next->location.y - current->location.y);
na = atan(fabs(dy/dx));
if(atan(fabs(current->location.y/current->location.x)) < atan(fabs(next->location.y/next->location.x)))
na = current->angle - na;
else if(atan(fabs(current->location.y/current->location.x)) > atan(fabs(next->location.y/next->location.x)))
na = current->angle + na;
return na;
}
for(unsigned int i = 0;i<BALL_COUNT;++i)
{
if(vBalls[i]->speed > 0){
vBalls[i]->speed += vBalls[i]->acceleration;
float dsdt = vBalls[i]->speed*dt;
dvdt.x = dsdt*cos(vBalls[i]->angle);
dvdt.y = dsdt*sin(vBalls[i]->angle);
vBalls[i]->location.x += dvdt.x;
vBalls[i]->location.y += dvdt.y;
for(unsigned int j = 1; j < BALL_COUNT; ++j)
{
if(i == j) continue;
if(CollisingBall(vBalls[i]->spriteBall->getPosition(),vBalls[j]->spriteBall->getPosition()))
{
vBalls[j]->speed = 600;
double angle;
angle = angleCollisionBalls(vBalls[i],vBalls[j]);
vBalls[i]->angle = (float)-angle;
vBalls[j]->angle = (float)angle;
}
}
}
}
There are two straightforward bugs that spring to my attention with a quick look at your code.
Firstly, this:
vBalls[i]->angle = (float)-angle;
vBalls[j]->angle = (float)angle;
is not the correct way to calculate opposing angles. For example, it will not do what you want it to do when angle is zero (or 180 degrees, for that matter).
Secondly, you iterate over your whole vBalls array multiple times, once with the index i and an inner loop with the index j. This means collisions will be calculated twice, and the speed of both balls would be set to 600! Changing your inner loop to be this:
for(unsigned int j = i + 1; j < BALL_COUNT; ++j)
should prevent this occurring.
There's also a more subtle bug. Your collision detection does not take into account time. Each ball moves a particular distance each iteration of your game loop. This means that if a collision does not occur in one 'tick', a ball could pass straight through another ball and then trigger the collision code on the far side of the ball. You cannot do a simple radius-based collision test in this situation, as if a ball moves more than (BALL_RADIUS * BALL_RADIUS) in a single step, your system will behave strangely or not work at all.
I personally would use vectors to describe speed and direction for each ball rather than angles and speeds, but refactoring your code to do this is a bit outside the scope of this question.

Sporadic Collision Detection

I've been working on detecting collision between to object in my game. Right now everything tavels vertically, but would like to keep the option for other movement open. It's classic 2d vertical space shooter.
Right now I loop through every object, checking for collisions:
for(std::list<Object*>::iterator iter = mObjectList.begin(); iter != mObjectList.end();) {
Object *m = (*iter);
for(std::list<Object*>::iterator innerIter = ++iter; innerIter != mObjectList.end(); innerIter++ ) {
Object *s = (*innerIter);
if(m->getType() == s->getType()) {
break;
}
if(m->checkCollision(s)) {
m->onCollision(s);
s->onCollision(m);
}
}
}
Here is how I check for a collision:
bool checkCollision(Object *other) {
float radius = mDiameter / 2.f;
float theirRadius = other->getDiameter() / 2.f;
Vector<float> ourMidPoint = getAbsoluteMidPoint();
Vector<float> theirMidPoint = other->getAbsoluteMidPoint();
// If the other object is in between our path on the y axis
if(std::min(getAbsoluteMidPoint().y - radius, getPreviousAbsoluteMidPoint().y - radius) <= theirMidPoint.y &&
theirMidPoint.y <= std::max(getAbsoluteMidPoint().y + radius, getPreviousAbsoluteMidPoint().y + radius)) {
// Get the distance between the midpoints on the x axis
float xd = abs(ourMidPoint.x - theirMidPoint.x);
// If the distance between the two midpoints
// is greater than both of their radii together
// then they are too far away to collide
if(xd > radius+theirRadius) {
return false;
} else {
return true;
}
}
return false;
}
The problem is it will randomly detect collisions correctly, but other times does not detect it at all. It's not the if statement breaking away from the object loop because the objects do have different types. The closer the object is to the top of the screen, the better chance it has of collision getting detected correctly. Closer to the bottom of the screen, the less chance it has of getting detected correctly or even at all. However, these situations don't always occur. The diameter for the objects are massive (10 and 20) to see if that was the problem, but it doesn't help much at all.
EDIT - Updated Code
bool checkCollision(Object *other) {
float radius = mDiameter / 2.f;
float theirRadius = other->getDiameter() / 2.f;
Vector<float> ourMidPoint = getAbsoluteMidPoint();
Vector<float> theirMidPoint = other->getAbsoluteMidPoint();
// Find the distance between the two points from the center of the object
float a = theirMidPoint.x - ourMidPoint.x;
float b = theirMidPoint.y - ourMidPoint.y;
// Find the hypotenues
double c = (a*a)+(b*b);
double radii = pow(radius+theirRadius, 2.f);
// If the distance between the points is less than or equal to the radius
// then the circles intersect
if(c <= radii*radii) {
return true;
} else {
return false;
}
}
Two circular objects collide when the distance between their centers is small enough. You can use the following code to check this:
double distanceSquared =
pow(ourMidPoint.x - theirMidPoint.x, 2.0) +
pow(ourMidPoint.x - theirMidPoint.x, 2.0);
bool haveCollided = (distanceSquared <= pow(radius + theirRadius, 2.0));
In order to check whether there was a collision between two points in time, you can check for collision at the start of the time interval and at the end of it; however, if the objects move very fast, the collision detection can fail (i guess you have encountered this problem for falling objects that have the fastest speed at the bottom of the screen).
The following might make the collision detection more reliable (though still not perfect). Suppose the objects move with constant speed; then, their position is a linear function of time:
our_x(t) = our_x0 + our_vx * t;
our_y(t) = our_y0 + our_vy * t;
their_x(t) = their_x0 + their_vx * t;
their_y(t) = their_y0 + their_vy * t;
Now you can define the (squared) distance between them as a quadratic function of time. Find at which time it assumes its minimum value (i.e. its derivative is 0); if this time belongs to current time interval, calculate the minimum value and check it for collision.
This must be enough to detect collisions almost perfectly; if your application works heavily with free-falling objects, you might want to refine the movement functions to be quadratic:
our_x(t) = our_x0 + our_v0x * t;
our_y(t) = our_y0 + our_v0y * t + g/2 * t^2;
This logic is wrong:
if(std::min(getAbsoluteMidPoint().y - radius, getPreviousAbsoluteMidPoint().y - radius) <= theirMidPoint.y &&
theirMidPoint.y <= std::max(getAbsoluteMidPoint().y + radius, getPreviousAbsoluteMidPoint().y + radius))
{
// then a collision is possible, check x
}
(The logic inside the braces is wrong too, but that should produce false positives, not false negatives.) Checking whether a collision has occurred during a time interval can be tricky; I'd suggest checking for a collision at the present time, and getting that to work first. When you check for a collision (now) you can't check x and y independently, you must look at the distance between the object centers.
EDIT:
The edited code is still not quite right.
// Find the hypotenues
double c = (a*a)+(b*b); // actual hypotenuse squared
double radii = pow(radius+theirRadius, 2.f); // critical hypotenuse squared
if(c <= radii*radii) { // now you compare a distance^2 to a distance^4
return true; // collision
}
It should be either this:
double c2 = (a*a)+(b*b); // actual hypotenuse squared
double r2 = pow(radius+theirRadius, 2.f); // critical hypotenuse squared
if(c2 <= r2) {
return true; // collision
}
or this:
double c2 = (a*a)+(b*b); // actual hypotenuse squared
double c = pow(c2, 0.5); // actual hypotenuse
double r = radius + theirRadius; // critical hypotenuse
if(c <= r) {
return true; // collision
}
Your inner loop needs to start at mObjectList.begin() instead of iter.
The inner loop needs to iterate over the entire list otherwise you miss collision candidates the further you progress in the outer loop.