Exemplo n.º 1
0
        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;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }