Ejemplo n.º 1
0
        private void Events_InitialCollisionDetected(EntityCollidable sender, Collidable info, CollidablePairHandler pair, ContactData contact)
        {
            try
            {
                //var contact = pair.Contacts[0].Contact;

                //if(contact.PenetrationDepth>2f)
                //DebugSystem.Instance.DebugCommandUI.Echo(contact.PenetrationDepth.ToString());

                // Select collisionInformation for object in contact with instead of the ships own collisionInformation
                Collidable candidate = (pair.BroadPhaseOverlap.EntryA == racerEntity.CollisionInformation ? pair.BroadPhaseOverlap.EntryB : pair.BroadPhaseOverlap.EntryA) as Collidable;
                if (candidate.Equals(Physics.currentTrackFloor))
                {
                    ReactToTrackHit(contact);
                }
                else if (candidate.Equals(Physics.currentTrackWall))
                {
                    ReactToWallHit(contact);
                }
                else
                {
                    ReactToShipShipCollision(contact, candidate);
                }
            }
            catch (Exception e)
            {
                // System.Diagnostic.Debug.WriteLine("Unfound pair");
            }
        }
Ejemplo n.º 2
0
        private void ReactToShipShipCollision(ContactData contact, Collidable candidate)
        {
            foreach (Racer r in Race.currentRacers)
            {
                Entity collidedBody = r.shipPhysics.racerEntity;
                if (candidate.Equals(collidedBody.CollisionInformation))
                {
                    //Console.WriteLine("ship hit ship ");

                    Vector3 colVel = collidedBody.LinearVelocity;
                    r.raceTiming.previousSpeedOfCollidedBody = Math.Abs(colVel.Length());


                    //// Deal with on top collision (NOT TESTED)
                    //if (r.shipPhysics.shipRayToTrackTime < 23f && shipRayToTrackTime > 23f)
                    //{
                    //    Console.WriteLine("Landed on top");
                    //    float impulseLeft = Vector3.Dot(physicsBody.Position - r.shipPhysics.physicsBody.Position, physicsBody.WorldTransform.Left);
                    //    physicsBody.ApplyImpulse(physicsBody.Position, physicsBody.WorldTransform.Left * impulseLeft);

                    //}


                    /////////////////////////
                    //Find opponents quadrant
                    /////////////////////////
                    Vector3 opponentContactVector = contact.Position - collidedBody.Position;

                    //Find quarent
                    Quadrant oFL_BR = Quadrant.FrontLeft;
                    Quadrant oFR_BL = Quadrant.FrontRight;

                    //old line test was between (contactVector, collidedBody.OrientationMatrix.Forward)
                    Matrix3X3 oM = collidedBody.OrientationMatrix;//opponent Matrix
                    if (Vector3.Dot(opponentContactVector, oM.Backward + oM.Right) > 0)
                    {
                        oFL_BR = Quadrant.BackRight;
                    }
                    if (Vector3.Dot(opponentContactVector, oM.Backward + oM.Left) > 0)
                    {
                        oFR_BL = Quadrant.BackLeft;
                    }

                    //Quadrent? result = null;// '?' makes it nullable

                    if ((oFL_BR == Quadrant.FrontLeft) && (oFR_BL == Quadrant.FrontRight))
                    {
                        opponentQuadrant = Quadrant.Front;
                    }
                    else if ((oFL_BR == Quadrant.BackRight) && (oFR_BL == Quadrant.BackLeft))
                    {
                        opponentQuadrant = Quadrant.Back;
                    }
                    else if ((oFL_BR == Quadrant.FrontLeft) && (oFR_BL == Quadrant.BackLeft))
                    {
                        opponentQuadrant = Quadrant.Left;
                    }
                    else if ((oFL_BR == Quadrant.BackRight) && (oFR_BL == Quadrant.FrontRight))
                    {
                        opponentQuadrant = Quadrant.Right;
                    }

                    /////////////////////
                    //Find local quadrant
                    /////////////////////
                    Vector3 localContactVector = contact.Position - racerEntity.Position;

                    Vector3 contactVector = contact.Position - collidedBody.Position;

                    //Find quarent
                    Quadrant lFL_BR = Quadrant.FrontLeft;
                    Quadrant lFR_BL = Quadrant.FrontRight;

                    //old line test was between (contactVector, collidedBody.OrientationMatrix.Forward)
                    Matrix3X3 lM = collidedBody.OrientationMatrix;//opponent Matrix
                    if (Vector3.Dot(localContactVector, lM.Backward + lM.Right) > 0)
                    {
                        lFL_BR = Quadrant.BackRight;
                    }
                    if (Vector3.Dot(localContactVector, lM.Backward + lM.Left) > 0)
                    {
                        lFR_BL = Quadrant.BackLeft;
                    }

                    //Quadrent? result = null;// '?' makes it nullable

                    if ((lFL_BR == Quadrant.FrontLeft) && (lFR_BL == Quadrant.FrontRight))
                    {
                        localQuadrant = Quadrant.Front;
                    }
                    else if ((lFL_BR == Quadrant.BackRight) && (lFR_BL == Quadrant.BackLeft))
                    {
                        localQuadrant = Quadrant.Back;
                    }
                    else if ((lFL_BR == Quadrant.FrontLeft) && (lFR_BL == Quadrant.BackLeft))
                    {
                        localQuadrant = Quadrant.Left;
                    }
                    else if ((lFL_BR == Quadrant.BackRight) && (lFR_BL == Quadrant.FrontRight))
                    {
                        localQuadrant = Quadrant.Right;
                    }


                    //Console.WriteLine("Collision in quadrent " + result.ToString());

                    /////////////////////////////////////
                    /////////////////////////////////////
                    /////////////////////////////////////


                    Vector3 bounceVector = racerEntity.Position - collidedBody.Position;
                    bounceVector.Normalize();


                    float   shipVelocity_inShipBounceDirection = Vector3.Dot(racerEntity.LinearVelocity, bounceVector);                                                        // no need to divide by bounceVector.Length() as normalized
                    Vector3 relativeVelocity = collidedBody.LinearVelocity - racerEntity.LinearVelocity;
                    float   realtiveVelInShipBounceDirection = Vector3.Dot(racerEntity.LinearVelocity, bounceVector) - Vector3.Dot(collidedBody.LinearVelocity, bounceVector); // no need to divide by bounceVector.Length() as normalized

                    bool localQuadIsSide    = (localQuadrant == Quadrant.Left || localQuadrant == Quadrant.Right);
                    bool opponentQuadIsSide = (opponentQuadrant == Quadrant.Left || opponentQuadrant == Quadrant.Right);

                    if (localQuadrant == Quadrant.Front)
                    {
                        var frontPost = racerEntity.Position + Vector3.Transform(new Vector3(0f, 0f, -3.75f), racerEntity.Orientation);

                        Vector3 fusionVector = frontPost - collidedBody.Position;
                        Vector3 direction    = racerEntity.OrientationMatrix.Left;
                        if (Vector3.Dot(racerEntity.OrientationMatrix.Left, fusionVector) < 0)
                        {
                            //Bend to right
                            direction *= -1;
                        }

                        Vector3 a = collidedBody.Position - racerEntity.Position;
                        Vector3 b = racerEntity.OrientationMatrix.Forward;

                        var   tau         = Math.Sin(angleBetween(a, b)) / a.Length();
                        float scaleFactor = (float)Math.Abs(2f - tau);

                        racerEntity.ApplyImpulse(racerEntity.Position, direction * (200 * scaleFactor));
                    }


                    if (racerEntity.LinearVelocity.Length() < 50) //TODO: tweak
                    {
                        /////////////////
                        //Bounce in a similar way to when hitting walls

                        //Slow ship down in other components
                        racerEntity.LinearVelocity *= 0.94f;

                        //Get scale of bounce based on speed ship was moving towards the ship.
                        //Minimum bounce until 5 speed, max bounce after 100;
                        float minmaxV = Math.Min(50, Math.Max(10, (Math.Abs(shipVelocity_inShipBounceDirection))));
                        //float bounceScale = minmaxV / 20;//scale velocity down so max bounce is 5 times as strong as bounce at 20mph, and 20mph bounce is unscaled
                        racerEntity.LinearVelocity -= bounceVector * shipVelocity_inShipBounceDirection;

                        //Apply a bounce impulse
                        racerEntity.ApplyImpulse(racerEntity.Position, bounceVector * 25 * minmaxV);
                    }


                    else if (localQuadIsSide && opponentQuadIsSide)
                    {
                        /////////////////
                        //Bounce in a similar way to when hitting walls

                        //Slow ship down in other components
                        racerEntity.LinearVelocity *= 0.94f;

                        //Get scale of bounce based on speed ship was moving towards the ship.
                        //Minimum bounce until 5 speed, max bounce after 100;
                        float minmaxV = Math.Min(100, Math.Max(5, (Math.Abs(shipVelocity_inShipBounceDirection))));
                        //float bounceScale = minmaxV / 20;//scale velocity down so max bounce is 5 times as strong as bounce at 20mph, and 20mph bounce is unscaled
                        racerEntity.LinearVelocity -= bounceVector * shipVelocity_inShipBounceDirection;

                        //Apply a bounce impulse
                        racerEntity.ApplyImpulse(racerEntity.Position, bounceVector * 15 * minmaxV);
                    }

                    else if ((localQuadrant == Quadrant.Front) && opponentQuadrant == Quadrant.Back)
                    {
                        /////////////////
                        //Create ramming effect


                        //var worldCoordinates = racerEntity.Position + Vector3.Transform(backPosLeft, racerEntity.Orientation);

                        racerEntity.LinearVelocity -= bounceVector * realtiveVelInShipBounceDirection;


                        // Dampens both ships' speeds
                        if (localQuadrant == Quadrant.Front)
                        {
                            racerEntity.LinearVelocity *= 0.98f;
                        }
                        else
                        {
                            racerEntity.LinearVelocity *= 0.92f;
                        }

                        //Create ramming effect by speeding up front ship and slowing down back ship
                        float skewfactor = 7 / 8;
                        if (localQuadrant == Quadrant.Front)
                        {
                            skewfactor = 1 / 9;
                        }

                        //physicsBody.LinearVelocity = skewfactor * physicsBody.LinearVelocity + (1 - skewfactor) * collidedBody.LinearVelocity;
                        if (racerEntity.LinearVelocity.Length() != 0)
                        {
                            Vector3 normalisedVel = racerEntity.LinearVelocity;
                            normalisedVel.Normalize();
                            racerEntity.LinearVelocity = normalisedVel * (skewfactor * racerEntity.LinearVelocity.Length() + (1 - skewfactor) * collidedBody.LinearVelocity.Length());
                        }

                        //float minmaxV = Math.Min(100, Math.Max(5, (Math.Abs(realtiveVelInShipBounceDirection))));
                        //physicsBody.ApplyImpulse(physicsBody.Position, -bounceVector * 5 * minmaxV);// * angleModifier);
                    }

                    //else if () //FrontFront, BackBack, BackLeft, BackSide, FrontSide
                    //{



                    //}
                    else
                    {
                        /////////////////
                        //Bounce in a similar way to when hitting walls, but less violently than side to sides

                        //Slow ship down in other components
                        //if (localQuadrant == Quadrant.Front) physicsBody.LinearVelocity *= 0.98f;
                        //else
                        racerEntity.LinearVelocity *= 0.92f;

                        //Get scale of bounce based on speed ship was moving towards the ship.
                        //Minimum bounce until 5 speed, max bounce after 100;
                        float minmaxV = Math.Min(100, Math.Max(25, (Math.Abs(shipVelocity_inShipBounceDirection))));
                        //float bounceScale = minmaxV / 20;//scale velocity down so max bounce is 5 times as strong as bounce at 20mph, and 20mph bounce is unscaled
                        racerEntity.LinearVelocity -= bounceVector * shipVelocity_inShipBounceDirection;

                        //Apply a bounce impulse
                        racerEntity.ApplyImpulse(racerEntity.Position, bounceVector * 12 * minmaxV);
                    }



                    //Console.WriteLine("Collision in quadrent " + result.ToString());

                    /////////////////////////////////
                    ////Remove ships velocity towards the other ship
                    ////by setting velocity component in direction of bounce to 0
                    //float shipVelocity_inShipBounceDirection = Vector3.Dot(physicsBody.LinearVelocity, bounceVector);// no need to divide by bounceVector.Length() as normalized

                    ////Get scale of bounce based on speed ship was moving towards the ship.
                    ////Minimum bounce until 5 speed, max bounce after 100;
                    //float minmaxV = Math.Min(100, Math.Max(5, (Math.Abs(shipVelocity_inShipBounceDirection))));
                    ////float bounceScale = minmaxV / 20;//scale velocity down so max bounce is 5 times as strong as bounce at 20mph, and 20mph bounce is unscaled

                    ////Apply a bounce impulse
                    //physicsBody.ApplyImpulse(physicsBody.Position, bounceVector * 25 * minmaxV);
                    /////////////////////////////////

                    //float bounceVal = 2000f;
                    //if (!((Vector3.Dot(collidedBody.Position - contact.Position, collidedBody.OrientationMatrix.Left) < 0)))
                    //{
                    //    bounceVal = -bounceVal;
                    //    Console.Out.WriteLine("Bounce Inverted");
                    //}
                    //else
                    //    Console.Out.WriteLine("Bounce Normal");

                    //Keep the slower ship still, while pushing the other ship around it
                    if (racerEntity.LinearVelocity.Length() > collidedBody.LinearVelocity.Length())
                    {
                        //Bounce the ship to the left
                        //physicsBody.ApplyImpulse(physicsBody.Position, collidedBody.OrientationMatrix.Left * 2000);
                    }
                    r.lastCollisionPoint = contact.Position;
                    //Initiate controller vibration
                    r.isColliding = true;
                    if (r.GetType() == typeof(RacerHuman))
                    {
                        SoundManager.Collision();
                    }
                    //Vector3 relativeVelocity = collidedBody.LinearVelocity - physicsBody.LinearVelocity;

                    //float realtiveVelInShipBounceDirection = Vector3.Dot(physicsBody.LinearVelocity, bounceVector) - Vector3.Dot(collidedBody.LinearVelocity, bounceVector);// no need to divide by bounceVector.Length() as normalized

                    //float shipWidth = 5f;//TODO:don't set manually //TODO: optimize
                    //float shipLength = 7.5f;//TODO:don't set manually
                    //Vector3 backPosRight = new Vector3(shipWidth / 2, 0f, shipLength / 2);//x+-
                    //Vector3 backPosLeft = new Vector3(-shipWidth / 2, 0f, shipLength / 2);
                    //var worldCoordinates = physicsBody.Position + Vector3.Transform(backPosLeft, physicsBody.Orientation);

                    //Vector3.tran
                    ////Front stabilizers, not as far out as physicsBody is not that wide
                    //stabilizerRaycastList.Add(new Vector3(shipWidth / 4, 0f, -shipLength / 2));
                    //stabilizerRaycastList.Add(new Vector3(-shipWidth / 4, 0f, -shipLength / 2));

                    ////Back stabilizers
                    //stabilizerRaycastList.Add(new Vector3(shipWidth / 2, 0f, shipLength / 2));
                    //stabilizerRaycastList.Add(new Vector3(-shipWidth / 2, 0f, shipLength / 2));


                    //physicsBody.LinearVelocity -= bounceVector * realtiveVelInShipBounceDirection;


                    // Dampens both ships' speeds
                    //physicsBody.LinearVelocity *= 0.94f;

                    //Create ramming effect by speeding up front ship and slowing down back ship
                    //float skewfactor = 7 / 8;
                    //physicsBody.LinearVelocity = skewfactor * physicsBody.LinearVelocity + (1 - skewfactor) * collidedBody.LinearVelocity;
                    //if (physicsBody.LinearVelocity.Length() != 0)
                    //{
                    //    Vector3 normalisedVel = physicsBody.LinearVelocity;
                    //    normalisedVel.Normalize();
                    //    physicsBody.LinearVelocity = normalisedVel * (skewfactor * physicsBody.LinearVelocity.Length() + (1 - skewfactor) * collidedBody.LinearVelocity.Length());
                    //}
                    ////else move slightly in direction of bounce vector from other ship

                    //float minmaxV = Math.Min(100, Math.Max(5, (Math.Abs(realtiveVelInShipBounceDirection))));

                    //physicsBody.ApplyImpulse(physicsBody.Position, -bounceVector * 5 * minmaxV);// * angleModifier);

                    //TODO: fire off crap on collision
                    //BeatShift.emitter = new ParticleEmitter((Func<Vector3>)delegate { return contacts[0].Position; }, BeatShift.settingsb, BeatShift.pEffect);
                }
                //}
            }
        }