Beispiel #1
0
        public override void Collide(CollisionEvent coll, PlayerPhysics physics)
        {
            var ball = coll.Ball;

            // make sure we process each ball/ball collision only once
            // (but if we are frozen, there won"t be a second collision event, so deal with it now!)
            if ((physics.SwapBallCollisionHandling && ball.Id >= _id ||
                 !physics.SwapBallCollisionHandling && ball.Id <= _id) && !_state.IsFrozen)
            {
                return;
            }

            // target ball to object ball delta velocity
            var vRel    = ball.Hit.Vel.Clone().Sub(Vel);
            var vNormal = coll.HitNormal;
            var dot     = vRel.Dot(vNormal);

            // correct displacements, mostly from low velocity, alternative to true acceleration processing
            if (dot >= -PhysicsConstants.LowNormVel)
            {
                // nearly receding ... make sure of conditions
                if (dot > PhysicsConstants.LowNormVel)
                {
                    // otherwise if clearly approaching .. process the collision
                    return;                     // is this velocity clearly receding (i.E must > a minimum)
                }

                //#ifdef PhysicsConstants.Embedded
                if (coll.HitDistance < -PhysicsConstants.Embedded)
                {
                    dot = -PhysicsConstants.EmbedShot;                     // has ball become embedded???, give it a kick
                }
                else
                {
                    return;
                }

                //#endif
            }

            // fixme script
            // send ball/ball collision event to script function
            // if (dot < -0.25f) {   // only collisions with at least some small true impact velocity (no contacts)
            //      g_pplayer->m_ptable->InvokeBallBallCollisionCallback(this, pball, -dot);
            // }

            //#ifdef PhysicsConstants.DispGain
            var eDist      = -PhysicsConstants.DispGain * coll.HitDistance;
            var normalDist = vNormal.Clone().MultiplyScalar(eDist);

            if (eDist > 1.0e-4)
            {
                if (eDist > PhysicsConstants.DispLimit)
                {
                    eDist = PhysicsConstants.DispLimit;                     // crossing ramps, delta noise
                }

                if (!_state.IsFrozen)
                {
                    // if the hit ball is not frozen
                    eDist *= 0.5f;
                }

                ball.State.Pos.Add(normalDist);                 // push along norm, back to free area
                // use the norm, but is not correct, but cheaply handled
            }

            eDist = -PhysicsConstants.DispGain * Coll.HitDistance;             // noisy value .... needs investigation
            if (!_state.IsFrozen && eDist > 1.0e-4)
            {
                if (eDist > PhysicsConstants.DispLimit)
                {
                    eDist = PhysicsConstants.DispLimit;                     // crossing ramps, delta noise
                }

                eDist *= 0.5f;
                _state.Pos.Sub(normalDist);                 // pull along norm, back to free area
            }
            //#endif

            var myInvMass = _state.IsFrozen ? 0.0f : InvMass;                      // frozen ball has infinite mass
            var impulse   = -(1.0f + 0.8f) * dot / (myInvMass + ball.Hit.InvMass); // resitution = 0.8

            if (!_state.IsFrozen)
            {
                Vel.Sub(vNormal.Clone().MultiplyScalar(impulse * myInvMass));
            }

            ball.Hit.Vel.Add(vNormal.Clone().MultiplyScalar(impulse * ball.Hit.InvMass));
        }