bool PhysicsProcessor::collidedCircleCircleDirection(Vector2d<float> pos1, float r1,Vector2d<float> pos2, float r2) { // We check if the circle has collided if(collidedCircleCircle(pos1,r1,pos2,r2)) { // If it has we do further calculations Vector2d<float> diff = pos2-pos1; Vector2d<float> cp = diff; cp.normalise(); //lastCollisionA.contactPoint = pos1 + (cp * r1); //lastCollisionA.ticks = timer->getTicks(); // If it has we do further calculations diff = pos1 - pos2; cp = diff; cp.normalise(); //lastCollisionB.contactPoint = pos2 + (cp * r2); //lastCollisionB.ticks = lastCollisionA.ticks; return true; } //return lastCollisionA.hasCollided; return false; }
int CollisionDetector::detect(std::vector<Sprite*>& sprites, int spacesPerMetre) { std::vector<collision> collisions; size_t n = sprites.size(); for(size_t i=0; i<n; ++i) for(size_t j=i+1; j<n; ++j) { float dx, dy; dx = sprites[i]->getPos().getx() - sprites[j]->getPos().getx(); dy = sprites[i]->getPos().gety() - sprites[j]->getPos().gety(); Vector2d normal; if(fabs(dx)*spacesPerMetre < (sprites[i]->getWidth() + sprites[j]->getWidth())/2 && fabs(dy)*spacesPerMetre < (sprites[i]->getHeight() + sprites[j]->getHeight())/2) { normal.setx(dx); normal.sety(dy); normal.normalise(); collisions.push_back({i,j,normal}); } } //resolve collisions for(size_t i=0; i<collisions.size(); ++i) { Vector2d relVel = sprites[collisions[i].a]->getVel(); relVel -= sprites[collisions[i].b]->getVel(); float sepVel = relVel * collisions[i].normal; if(sepVel > 0) continue; float newSep = -sepVel * (sprites[collisions[i].a]->getBounce()*sprites[collisions[i].b]->getBounce()/2.f); float deltaVel = newSep -sepVel; float totInvMass = sprites[collisions[i].a]->getInverseMass() + sprites[collisions[i].b]->getInverseMass(); float impulse = deltaVel / totInvMass; Vector2d impPerIMass = collisions[i].normal * impulse; sprites[collisions[i].a]->setVel(sprites[collisions[i].a]->getVel() + impPerIMass * sprites[collisions[i].a]->getInverseMass()); sprites[collisions[i].b]->setVel(sprites[collisions[i].b]->getVel() + impPerIMass * -sprites[collisions[i].b]->getInverseMass()); } return collisions.size(); }
/// Point Collisions // Check if a point is on a Line bool PhysicsProcessor::collidedPointLine(Vector2d<float> point,Vector2d<float> lineStart, Vector2d<float> lineEnd) { // Check if the point is actually lineStart or lineEnd if(point == lineStart or point == lineEnd) { /* lastCollisionA.contactPoint = point; lastCollisionA.hasCollided = true; lastCollisionA.ticks = timer->getTicks();*/ return true; } // Check if line is horizontal or vertical // Then we can make quick checks if(lineStart.x == lineEnd.x == point.x) { // Line vertical if(point.y >= lineStart.y and point.y <= lineEnd.y) { /*lastCollisionA.contactPoint = point; lastCollisionA.hasCollided = true; lastCollisionA.ticks = timer->getTicks();*/ return true; } } else if(lineStart.y == lineEnd.y == point.y) { // line horizontal if(point.x >= lineStart.x and point.x <= lineEnd.x) { /*lastCollisionA.contactPoint = point; lastCollisionA.hasCollided = true; lastCollisionA.ticks = timer->getTicks();*/ return true; } } Vector2d<float> AB = lineEnd-lineStart; Vector2d<float> AC = point-lineStart; float magAB = AB.lengthSquared(); float magAC = AC.lengthSquared(); // If one vector is greater in magnitude than the other, then point is not on the line. if(magAC > magAB) { /*lastCollisionA.contactPoint = point; lastCollisionA.hasCollided = false; lastCollisionA.ticks = timer->getTicks();*/ return false; } // Now take unit vectors and see if the directions match AB.normalise(); AC.normalise(); AB = AC - AB; // Same direction so collision has occurred if(AB.lengthSquared() == 0) { /*lastCollisionA.contactPoint = point; lastCollisionA.hasCollided = true; lastCollisionA.ticks = timer->getTicks();*/ return true; } /*lastCollisionA.contactPoint = point; lastCollisionA.hasCollided = false; lastCollisionA.ticks = timer->getTicks();*/ return false; }
bool Span::OnSpan(const Point& p, double* t)const { // FAST OnSpan test - assumes that p lies ON the unbounded span #if _DEBUG if(this->returnSpanProperties == false) { FAILURE(L"OnSpan - properties no set, incorrect calling code"); } #endif #if 0 if(NullSpan) { *t = 0.0; return (p == p0); } if(p == p0) { *t = 0.0; return true; } if(p == p1) { *t = 1.0; return true; } #endif bool ret; // if(p == this->p0 || p == this->p1) return true; if(dir == LINEAR) { #if 1 #if _DEBUG // check p is on line CLine cl(*this); double d = fabs(cl.Dist(p)); if( d > geoff_geometry::TOLERANCE) { FAILURE(L"OnSpan - point not on linear span, incorrect calling code"); } #endif #endif Vector2d v0(p0, p); *t = vs * v0; // ret = (*t > - geoff_geometry::TOLERANCE && *t < length + geoff_geometry::TOLERANCE); *t = *t / length; ret = (*t >= 0 && *t <= 1.0 ); } else { // true if p lies on arc span sp (p must be on circle of span) #if 1 #if _DEBUG // check that p lies on the arc double d = p.Dist(pc); if(FNE(d, radius, geoff_geometry::TOLERANCE)) { FAILURE(L"OnSpan - point not on circular span, incorrect calling code"); } #endif #endif #if 0 // alt method (faster, but doesn't provide t) Vector2d v0(p0, p); Vector2d v1(p0, p1); // check angle to point from start double cp; ret = ((cp = (dir * (v0 ^ v1))) > 0); *t = 0.0;// incorrect !!! #else Vector2d v = ~Vector2d(pc, p); v.normalise(); if(dir == CW) v = -v; double ang = IncludedAngle(vs, v, dir); *t = ang / angle; ret = (*t >= 0 && *t <= 1.0); #endif } return ret; }