static void collideWith(MobileSpaceObject* object) { // check for collision with each mobile object for (typename std::list<Derived*>::iterator it = Derived::activeParticles_.begin(); it != Derived::activeParticles_.end(); ++it) { // don't check for self collision if (*it != object) { // get faster object MobileSpaceObject *source, *target; if (object->velocity() > (*it)->velocity()) { source = object; target = *it; } else { source = *it; target = object; } const float minDistSquared = std::pow(object->radius() + (*it)->radius(), 2); // if objects are moving if (source->velocity().lengthSquare() > 0) { const Vector2f velocitySourceNorm ( source->velocity().normalize()); const Vector2f velocitySourceOrtho (-velocitySourceNorm.y_, velocitySourceNorm.x_); const Vector2f centerDist ( velocitySourceOrtho * ((source->location() - target->location())*velocitySourceOrtho)); // if path of object crosses target object if (centerDist.lengthSquare() < minDistSquared) { const Vector2f lastFrameLocation = source->location() - source->velocity()*timer::frameTime()*0.6f; const Vector2f chordMidPoint = target->location() + centerDist; // if path of object has intersected with target within the last frame if ( ((source->location() - target->location() ).lengthSquare() < minDistSquared) || ((lastFrameLocation - target->location() ).lengthSquare() < minDistSquared) || ((chordMidPoint - source->location())*(chordMidPoint - lastFrameLocation) < 0.f)) { if (source->velocity()*(target->location() - lastFrameLocation) > 0) { const Vector2f impactLocation ((source->location() + target->location())*0.5f); const Vector2f impactDirection ((target->location() - source->location()).normalize()); // calculate velocity of objects in direction of impact before collision const Vector2f velocitySourceBefore = impactDirection * (source->velocity() * impactDirection); const Vector2f velocityTargetBefore = impactDirection * (target->velocity() * impactDirection); // calculate velocity of objects in direction of impact after collision const Vector2f velocitySourceAfter = (velocitySourceBefore*source->mass() + velocityTargetBefore*target->mass() - (velocitySourceBefore - velocityTargetBefore)*target->mass()) / (source->mass() + target->mass()); const Vector2f velocityTargetAfter = (velocitySourceBefore*source->mass() + velocityTargetBefore*target->mass() - (velocityTargetBefore - velocitySourceBefore)*source->mass()) / (source->mass() + target->mass()); // calculate collision result target->onCollision(source, impactLocation, impactDirection, velocitySourceBefore); source->onCollision(target, impactLocation, impactDirection, velocityTargetBefore); // add to orthongonal speed component of initial velocity // special case: Collision with rofle bullets is not physically correct, for improved gameplay if ((source->type() == spaceObjects::oAmmoROFLE) | (target->type() == spaceObjects::oAmmoROFLE)) target-> velocity() += (0.05f*source->velocity()*source->mass() + (velocityTargetAfter - velocityTargetBefore) * 0.6); else if (((source->type() == spaceObjects::oAmmoRocket) | (target->type() == spaceObjects::oAmmoRocket)) && ((source->type() != spaceObjects::oAmmoFist) | (target->type() != spaceObjects::oAmmoFist))) { source->velocity() += (velocitySourceAfter - velocitySourceBefore) * 0.8; target->velocity() += (velocityTargetAfter - velocityTargetBefore) * 0.1; } else { source->velocity() += (velocitySourceAfter - velocitySourceBefore) * 0.8; target->velocity() += (velocityTargetAfter - velocityTargetBefore) * 0.8; } } } } } } } }