Ejemplo n.º 1
0
        public override void InitialCollisionDetected(EntityCollidable sender, Collidable other, CollidablePairHandler collisionPair)
        {
            base.InitialCollisionDetected(sender, other, collisionPair);

            //Console.WriteLine(other.Tag + " " + mRunTimer);
            if ((other.Tag is CharacterSynchronizer || other.Tag is PhysicsProp) && mRunTimer > 0.0f)
            {
                float totalImpulse = 0;
                foreach (ContactInformation c in collisionPair.Contacts)
                {
                    totalImpulse += c.NormalImpulse;
                }

                //Console.WriteLine(totalImpulse);

                int damage = 0;
                if (totalImpulse > 150.0f)
                {
                    damage = 2;
                }
                else if (totalImpulse > 45.0f)
                {
                    damage = 1;
                }

                Entity hitEntity;
                if (other.Tag is CharacterSynchronizer)
                {
                    hitEntity = (other.Tag as CharacterSynchronizer).body;
                }
                else
                {
                    hitEntity = (other.Tag as PhysicsProp).Entity;
                }

                Vector3 impulseVector = Vector3.Zero;
                Vector3 impulseDirection = hitEntity.Position - Creature.Position;
                if (impulseDirection != Vector3.Zero)
                {
                    impulseVector = Vector3.Normalize(impulseDirection);
                }

                impulseVector.Y = 0.45f;
                impulseVector.Normalize();
                impulseVector *= damage * DamageImpulseMultiplier;
                hitEntity.ApplyLinearImpulse(ref impulseVector);

                if (other.Tag is CharacterSynchronizer)
                {
                    ((other.Tag as CharacterSynchronizer).body.Tag as Creature).Damage(damage, Creature);
                    ((other.Tag as CharacterSynchronizer).body.Tag as Creature).AllowImpulse();
                }
            }
        }
Ejemplo n.º 2
0
        public static Boolean Detect(BasicModel shot, Collidable item, Boolean isPigeon)
        {
            Vector3 boundingBox = item.GetBoundingBox();
            Vector3 itemPos = item.GetPosition();

            //get the shot's position, rotation and scale
            Matrix shotMat = shot.GetWorld();
            Vector3 shotPos;
            Quaternion shotRotation;
            Vector3 shotScale;
            shotMat.Decompose(out shotScale, out shotRotation, out shotPos);

            //offset to compensate for the camera location not being at the origin.
            //camera loc is 0,0,100
            itemPos.Z -= 100;
            shotPos.Z -= 100;

            //calculate the shot's distance from the origin
            double shotDistance = Math.Sqrt(Math.Pow(shotPos.X, 2) + Math.Pow(shotPos.Y, 2) + Math.Pow(shotPos.Z, 2));

            //normalize the shot's position vector so the distance is equal to 1.0
            Vector3 shotNormalizedPos = new Vector3(shotPos.X / (float)shotDistance, shotPos.Y / (float)shotDistance, shotPos.Z / (float)shotDistance);

            //don't try to check collision detection for shots that have already passed the target in depth
            if ((item.GetDistance()+boundingBox.Z - shotDistance < 0) && isPigeon)
                return false;

            //laser gun effect
            //multiply the normalized shot vector by the target's distance. The effect of this operation is that the shot's distance becomes equal to that of the target's,
            //allowing us to simply check whether the shot is contained inside the target's bounding box to detect a hit.
            shotNormalizedPos *= (float)Math.Sqrt(Math.Pow(itemPos.X, 2) + Math.Pow(itemPos.Y, 2) + Math.Pow(itemPos.Z, 2));

            float xDiff = itemPos.X - shotNormalizedPos.X;
            float yDiff = itemPos.Y - shotNormalizedPos.Y;
            float zDiff = itemPos.Z - shotNormalizedPos.Z;

            //hack to get the shot's vector to face the right way, since shots quickly gain a negative Z value while pidgeons always stay positive
            if (isPigeon) zDiff = (zDiff < 0) ? -zDiff : zDiff;

            //check to see if the shot is inside the bounding box
             if (boundingBox.X / 2 > xDiff && (0 - (boundingBox.X / 2)) < xDiff &&
                boundingBox.Y / 2 > yDiff && (0 - (boundingBox.Y / 2)) < yDiff)
            {
                if (isPigeon && boundingBox.Z / 2 > zDiff && (0 - (boundingBox.Z / 2)) < zDiff)
                    return true;

                else if (!isPigeon)
                    return true;
            }
            return false;
        }
Ejemplo n.º 3
0
    public bool doesCollide(Collidable other)
    {
        //Validate
        if (other == null) return false;

        //Check
        if (getTop() < other.getBottom())	return false;
        if (getLeft() > other.getRight())	return false;
        if (getRight() < other.getLeft())	return false;
        if (getBottom() > other.getTop())	return false;

        //Otherwise, colliding
        return true;
    }
Ejemplo n.º 4
0
 public override bool Collide(Collidable c)
 {
     if (c is Bibble)
     {
         Bibble b = (Bibble) c;
         if (b.IsDead || Owner == b) return false;
         b.Damage(Damage);
         BibbleGame g = Game as BibbleGame;
         if (g != null)
             g.Explosion(Position, 0.1f, false);
         return true;
     }
     else // bounce of, if stil bouncing
     {
         mRebounds--;
         Owner = null;
     }
     return mRebounds < 0;
 }
Ejemplo n.º 5
0
 internal EventStoragePairTouched(Collidable other, CollidablePairHandler pair)
 {
     this.other = other;
     this.pair = pair;
 }
Ejemplo n.º 6
0
 internal EventStorageContactRemoved(Collidable other, CollidablePairHandler pair, ref ContactData contactData)
 {
     this.other = other;
     this.pair = pair;
     this.contactData = contactData;
 }
Ejemplo n.º 7
0
        ///<summary>
        /// Updates the time of impact for the pair.
        ///</summary>
        ///<param name="requester">Collidable requesting the update.</param>
        ///<param name="dt">Timestep duration.</param>
        public override void UpdateTimeOfImpact(Collidable requester, float dt)
        {
            var collidableA = CollidableA as ConvexCollidable;
            var collidableB = CollidableB as ConvexCollidable;
            var modeA = collidableA.entity == null ? PositionUpdateMode.Discrete : collidableA.entity.PositionUpdateMode;
            var modeB = collidableB.entity == null ? PositionUpdateMode.Discrete : collidableB.entity.PositionUpdateMode;

            var overlap = BroadPhaseOverlap;
            if (
                    (overlap.entryA.IsActive || overlap.entryB.IsActive) && //At least one has to be active.
                    (
                        (
                            modeA == PositionUpdateMode.Continuous &&   //If both are continuous, only do the process for A.
                            modeB == PositionUpdateMode.Continuous &&
                            overlap.entryA == requester
                        ) ||
                        (
                            modeA == PositionUpdateMode.Continuous ^   //If only one is continuous, then we must do it.
                            modeB == PositionUpdateMode.Continuous
                        )

                    )
                )
            {
                //Only perform the test if the minimum radii are small enough relative to the size of the velocity.
                //Discrete objects have already had their linear motion integrated, so don't use their velocity.
                Vector3 velocity;
                if (modeA == PositionUpdateMode.Discrete)
                {
                    //CollidableA is static for the purposes of this continuous test.
                    velocity = collidableB.entity.linearVelocity;
                }
                else if (modeB == PositionUpdateMode.Discrete)
                {
                    //CollidableB is static for the purposes of this continuous test.
                    Vector3.Negate(ref collidableA.entity.linearVelocity, out velocity);
                }
                else
                {
                    //Both objects are moving.
                    Vector3.Subtract(ref collidableB.entity.linearVelocity, ref collidableA.entity.linearVelocity, out velocity);
                }
                Vector3.Multiply(ref velocity, dt, out velocity);
                float velocitySquared = velocity.LengthSquared();

                var minimumRadiusA = collidableA.Shape.minimumRadius * MotionSettings.CoreShapeScaling;
                timeOfImpact = 1;
                if (minimumRadiusA * minimumRadiusA < velocitySquared)
                {
                    //Spherecast A against B.
                    RayHit rayHit;
                    if (GJKToolbox.CCDSphereCast(new Ray(collidableA.worldTransform.Position, -velocity), minimumRadiusA, collidableB.Shape, ref collidableB.worldTransform, timeOfImpact, out rayHit))
                        timeOfImpact = rayHit.T;
                }

                var minimumRadiusB = collidableB.Shape.minimumRadius * MotionSettings.CoreShapeScaling;
                if (minimumRadiusB * minimumRadiusB < velocitySquared)
                {
                    //Spherecast B against A.
                    RayHit rayHit;
                    if (GJKToolbox.CCDSphereCast(new Ray(collidableB.worldTransform.Position, velocity), minimumRadiusB, collidableA.Shape, ref collidableA.worldTransform, timeOfImpact, out rayHit))
                        timeOfImpact = rayHit.T;
                }

                //If it's intersecting, throw our hands into the air and give up.
                //This is generally a perfectly acceptable thing to do, since it's either sitting
                //inside another object (no ccd makes sense) or we're still in an intersecting case
                //from a previous frame where CCD took place and a contact should have been created
                //to deal with interpenetrating velocity.  Sometimes that contact isn't sufficient,
                //but it's good enough.
                if (timeOfImpact == 0)
                    timeOfImpact = 1;
            }

        }
Ejemplo n.º 8
0
        protected bool Collide(Collidable toTest, Vector2 positionOffset)
        {
            Rectangle shiftedBoundingBox = boundingBox;
            shiftedBoundingBox.Offset((int)positionOffset.X, (int)positionOffset.Y);

            if (shiftedBoundingBox.Intersects(toTest.BoundingBox))
                return true;
            return false;
        }
Ejemplo n.º 9
0
 void Events_ContactCreated(EntityCollidable sender, Collidable other, BEPUphysics.NarrowPhaseSystems.Pairs.CollidablePairHandler pair, ContactData contact)
 {
     this.Collided.Execute(other, pair.Contacts);
 }
Ejemplo n.º 10
0
 /// <summary>
 /// Computes the intersection, if any, between a ray and the objects in the character's bounding box.
 /// </summary>
 /// <param name="ray">Ray to test.</param>
 /// <param name="length">Length of the ray to use in units of the ray's length.</param>
 /// <param name="earliestHit">Earliest intersection location and information.</param>
 /// <param name="hitObject">Collidable intersected by the ray, if any.</param>
 /// <returns>Whether or not the ray hit anything.</returns>
 public bool RayCast(Ray ray, float length, out RayHit earliestHit, out Collidable hitObject)
 {
     earliestHit = new RayHit();
     earliestHit.T = float.MaxValue;
     hitObject = null;
     foreach (var collidable in character.Body.CollisionInformation.OverlappedCollidables)
     {
         //Check to see if the collidable is hit by the ray.
         float? t = ray.Intersects(collidable.BoundingBox);
         if (t != null && t < length)
         {
             //Is it an earlier hit than the current earliest?
             RayHit hit;
             if (collidable.RayCast(ray, length, SupportRayFilter, out hit) && hit.T < earliestHit.T)
             {
                 earliestHit = hit;
                 hitObject = collidable;
             }
         }
     }
     if (earliestHit.T == float.MaxValue)
         return false;
     return true;
 }
Ejemplo n.º 11
0
 /// <summary>
 /// Removes a collidable from the group.
 /// </summary>
 /// <param name="collidable">Collidable to remove.</param>
 public void Remove(Collidable collidable)
 {
     CollidableTree.Remove(collidable);
     OnShapeChanged();
 }
Ejemplo n.º 12
0
 /// <summary>
 /// Adds a new collidable to the group.
 /// </summary>
 /// <param name="collidable">Collidable to remove.</param>
 public void Add(Collidable collidable)
 {
     CollidableTree.Add(collidable);
     OnShapeChanged();
 }
Ejemplo n.º 13
0
        ///<summary>
        /// Updates the time of impact for the pair.
        ///</summary>
        ///<param name="requester">Collidable requesting the update.</param>
        ///<param name="dt">Timestep duration.</param>
        public override void UpdateTimeOfImpact(Collidable requester, float dt)
        {
            //TODO: This conditional early outing stuff could be pulled up into a common system, along with most of the pair handler.
            if (convex.IsActive && convex.entity.PositionUpdateMode == PositionUpdateMode.Continuous)
            {
                //TODO: This system could be made more robust by using a similar region-based rejection of edges.
                //CCD events are awfully rare under normal circumstances, so this isn't usually an issue.

                //Only perform the test if the minimum radii are small enough relative to the size of the velocity.
                Vector3 velocity;
                Vector3.Multiply(ref convex.entity.linearVelocity, dt, out velocity);
                float velocitySquared = velocity.LengthSquared();

                var minimumRadius = convex.Shape.minimumRadius * MotionSettings.CoreShapeScaling;
                timeOfImpact = 1;
                if (minimumRadius * minimumRadius < velocitySquared)
                {
                    var triangle = Resources.GetTriangle();
                    triangle.collisionMargin = 0;
                    Vector3 terrainUp = new Vector3(terrain.worldTransform.LinearTransform.M21, terrain.worldTransform.LinearTransform.M22, terrain.worldTransform.LinearTransform.M23);
                    //Spherecast against all triangles to find the earliest time.
                    for (int i = 0; i < TerrainManifold.overlappedTriangles.count; i++)
                    {
                        terrain.Shape.GetTriangle(ref TerrainManifold.overlappedTriangles.Elements[i], ref terrain.worldTransform, out triangle.vA, out triangle.vB, out triangle.vC);
                        //Put the triangle into 'localish' space of the convex.
                        Vector3.Subtract(ref triangle.vA, ref convex.worldTransform.Position, out triangle.vA);
                        Vector3.Subtract(ref triangle.vB, ref convex.worldTransform.Position, out triangle.vB);
                        Vector3.Subtract(ref triangle.vC, ref convex.worldTransform.Position, out triangle.vC);

                        RayHit rayHit;
                        if (GJKToolbox.CCDSphereCast(new Ray(Toolbox.ZeroVector, velocity), minimumRadius, triangle, ref Toolbox.RigidIdentity, timeOfImpact, out rayHit) &&
                            rayHit.T > Toolbox.BigEpsilon)
                        {
                            Vector3 AB, AC;
                            Vector3.Subtract(ref triangle.vB, ref triangle.vA, out AB);
                            Vector3.Subtract(ref triangle.vC, ref triangle.vA, out AC);
                            Vector3 normal;
                            Vector3.Cross(ref AC, ref AB, out normal);
                            float dot;
                            Vector3.Dot(ref normal, ref terrainUp, out dot);
                            if (dot < 0)
                            {
                                Vector3.Dot(ref normal, ref rayHit.Normal, out dot);
                            }
                            else
                            {
                                Vector3.Dot(ref normal, ref rayHit.Normal, out dot);
                                dot = -dot;
                            }
                            //Only perform sweep if the object is in danger of hitting the object.
                            //Triangles can be one sided, so check the impact normal against the triangle normal.
                            if (dot < 0)
                            {
                                timeOfImpact = rayHit.T;
                            }
                        }
                    }
                    Resources.GiveBack(triangle);
                }
            }
        }
Ejemplo n.º 14
0
 /// <summary>
 /// Finds a supporting entity, the contact location, and the contact normal.
 /// </summary>
 /// <param name="location">Contact point between the wheel and the support.</param>
 /// <param name="normal">Contact normal between the wheel and the support.</param>
 /// <param name="suspensionLength">Length of the suspension at the contact.</param>
 /// <param name="supportCollidable">Collidable supporting the wheel, if any.</param>
 /// <param name="entity">Entity supporting the wheel, if any.</param>
 /// <param name="material">Material of the support.</param>
 /// <returns>Whether or not any support was found.</returns>
 protected internal abstract bool FindSupport(out Vector3 location, out Vector3 normal, out float suspensionLength, out Collidable supportCollidable, out Entity entity, out Material material);
Ejemplo n.º 15
0
        /// <summary>
        /// Computes representative support information based on the character's current traction contacts, support contacts, and ray contacts.
        /// </summary>
        /// <param name="down">Down direction of the character.</param>
        private void UpdateSupportData(ref Vector3 down)
        {
            //Choose which set of contacts to use.
            RawList <CharacterContact> contacts;

            if (tractionContacts.Count > 0)
            {
                contacts = tractionContacts;
            }
            else if (supportContacts.Count > 0)
            {
                contacts = supportContacts;
            }
            else
            {
                //No contacts provide support!
                //Fall back to the ray cast result.
                if (SupportRayData != null)
                {
                    supportData = new SupportData
                    {
                        Position      = SupportRayData.Value.HitData.Location,
                        Normal        = SupportRayData.Value.HitData.Normal,
                        Depth         = Vector3.Dot(down, SupportRayData.Value.HitData.Normal) * (BottomDistance - SupportRayData.Value.HitData.T),
                        SupportObject = SupportRayData.Value.HitObject
                    };
                }
                else
                {
                    supportData = new SupportData();
                }
                return;
            }

            //Compute a representative support from the set of contacts.

            supportData.Position = contacts.Elements[0].Contact.Position;
            supportData.Normal   = contacts.Elements[0].Contact.Normal;

            for (int i = 1; i < contacts.Count; i++)
            {
                Vector3.Add(ref supportData.Position, ref contacts.Elements[i].Contact.Position, out supportData.Position);
                Vector3.Add(ref supportData.Normal, ref contacts.Elements[i].Contact.Normal, out supportData.Normal);
            }
            if (contacts.Count > 1)
            {
                Vector3.Divide(ref supportData.Position, contacts.Count, out supportData.Position);
                float length = supportData.Normal.LengthSquared();
                if (length < Toolbox.Epsilon)
                {
                    //It's possible that the normals have cancelled each other out- that would be bad!
                    //Just use an arbitrary support's normal in that case.
                    supportData.Normal = contacts.Elements[0].Contact.Normal;
                }
                else
                {
                    Vector3.Multiply(ref supportData.Normal, 1 / (float)Math.Sqrt(length), out supportData.Normal);
                }
            }
            //Now that we have the normal, cycle through all the contacts again and find the deepest projected depth.
            //Use that object as our support too.
            float      depth         = -float.MaxValue;
            Collidable supportObject = null;

            for (int i = 0; i < contacts.Count; i++)
            {
                float dot;
                Vector3.Dot(ref contacts.Elements[i].Contact.Normal, ref supportData.Normal, out dot);
                dot = dot * contacts.Elements[i].Contact.PenetrationDepth;
                if (dot > depth)
                {
                    depth         = dot;
                    supportObject = contacts.Elements[i].Collidable;
                }
            }
            supportData.Depth         = depth;
            supportData.SupportObject = supportObject;
        }
Ejemplo n.º 16
0
 private void Events_DetectingInitialCollision(EntityCollidable sender, Collidable other, CollidablePairHandler pair)
 {
     _sound.Impact(sender.Entity);
 }
Ejemplo n.º 17
0
 private void Events_CollisionEnded(EntityCollidable sender, Collidable other, CollidablePairHandler pair)
 {
     _sound.RollStop();
 }
Ejemplo n.º 18
0
        ///<summary>
        /// Updates the time of impact for the pair.
        ///</summary>
        ///<param name="requester">Collidable requesting the update.</param>
        ///<param name="dt">Timestep duration.</param>
        public override void UpdateTimeOfImpact(Collidable requester, float dt)
        {
            var overlap = BroadPhaseOverlap;
            var meshMode = mobileMesh.entity == null ? PositionUpdateMode.Discrete : mobileMesh.entity.PositionUpdateMode;
            var convexMode = convex.entity == null ? PositionUpdateMode.Discrete : convex.entity.PositionUpdateMode;

            if (
                    (mobileMesh.IsActive || convex.IsActive) && //At least one has to be active.
                    (
                        (
                            convexMode == PositionUpdateMode.Continuous &&   //If both are continuous, only do the process for A.
                            meshMode == PositionUpdateMode.Continuous &&
                            overlap.entryA == requester
                        ) ||
                        (
                            convexMode == PositionUpdateMode.Continuous ^   //If only one is continuous, then we must do it.
                            meshMode == PositionUpdateMode.Continuous
                        )
                    )
                )
            {
                //TODO: This system could be made more robust by using a similar region-based rejection of edges.
                //CCD events are awfully rare under normal circumstances, so this isn't usually an issue.

                //Only perform the test if the minimum radii are small enough relative to the size of the velocity.
                Vector3 velocity;
                if (convexMode == PositionUpdateMode.Discrete)
                {                    
                    //Convex is static for the purposes of CCD.
                    Vector3.Negate(ref mobileMesh.entity.linearVelocity, out velocity);
                }
                else if (meshMode == PositionUpdateMode.Discrete)
                {
                    //Mesh is static for the purposes of CCD.
                    velocity = convex.entity.linearVelocity;
                }
                else
                {
                    //Both objects can move.
                    Vector3.Subtract(ref convex.entity.linearVelocity, ref mobileMesh.entity.linearVelocity, out velocity);

                }
                Vector3.Multiply(ref velocity, dt, out velocity);
                float velocitySquared = velocity.LengthSquared();

                var minimumRadius = convex.Shape.minimumRadius * MotionSettings.CoreShapeScaling;
                timeOfImpact = 1;
                if (minimumRadius * minimumRadius < velocitySquared)
                {
                    TriangleSidedness sidedness = mobileMesh.Shape.Sidedness;
                    Matrix3X3 orientation;
                    Matrix3X3.CreateFromQuaternion(ref mobileMesh.worldTransform.Orientation, out orientation);
                    var triangle = Resources.GetTriangle();
                    triangle.collisionMargin = 0;
                    //Spherecast against all triangles to find the earliest time.
                    for (int i = 0; i < MeshManifold.overlappedTriangles.count; i++)
                    {
                        MeshBoundingBoxTreeData data = mobileMesh.Shape.TriangleMesh.Data;
                        int triangleIndex = MeshManifold.overlappedTriangles.Elements[i];
                        data.GetTriangle(triangleIndex, out triangle.vA, out triangle.vB, out triangle.vC);
                        Matrix3X3.Transform(ref triangle.vA, ref orientation, out triangle.vA);
                        Matrix3X3.Transform(ref triangle.vB, ref orientation, out triangle.vB);
                        Matrix3X3.Transform(ref triangle.vC, ref orientation, out triangle.vC);
                        Vector3.Add(ref triangle.vA, ref mobileMesh.worldTransform.Position, out triangle.vA);
                        Vector3.Add(ref triangle.vB, ref mobileMesh.worldTransform.Position, out triangle.vB);
                        Vector3.Add(ref triangle.vC, ref mobileMesh.worldTransform.Position, out triangle.vC);
                        //Put the triangle into 'localish' space of the convex.
                        Vector3.Subtract(ref triangle.vA, ref convex.worldTransform.Position, out triangle.vA);
                        Vector3.Subtract(ref triangle.vB, ref convex.worldTransform.Position, out triangle.vB);
                        Vector3.Subtract(ref triangle.vC, ref convex.worldTransform.Position, out triangle.vC);

                        RayHit rayHit;
                        if (GJKToolbox.CCDSphereCast(new Ray(Toolbox.ZeroVector, velocity), minimumRadius, triangle, ref Toolbox.RigidIdentity, timeOfImpact, out rayHit) &&
                            rayHit.T > Toolbox.BigEpsilon)
                        {

                            if (sidedness != TriangleSidedness.DoubleSided)
                            {
                                Vector3 AB, AC;
                                Vector3.Subtract(ref triangle.vB, ref triangle.vA, out AB);
                                Vector3.Subtract(ref triangle.vC, ref triangle.vA, out AC);
                                Vector3 normal;
                                Vector3.Cross(ref AB, ref AC, out normal);
                                float dot;
                                Vector3.Dot(ref normal, ref rayHit.Normal, out dot);
                                //Only perform sweep if the object is in danger of hitting the object.
                                //Triangles can be one sided, so check the impact normal against the triangle normal.
                                if (sidedness == TriangleSidedness.Counterclockwise && dot < 0 ||
                                    sidedness == TriangleSidedness.Clockwise && dot > 0)
                                {
                                    timeOfImpact = rayHit.T;
                                }
                            }
                            else
                            {
                                timeOfImpact = rayHit.T;
                            }
                        }
                    }
                    Resources.GiveBack(triangle);
                }



            }

        }
 protected void onCollision(EntityCollidable sender, Collidable other, CollidablePairHandler pair)
 {
     modelList[0].Ent.CollisionInformation.Events.PairTouching -= onCollision;
     GameManager.Space.DuringForcesUpdateables.Starting += update;
 }
Ejemplo n.º 20
0
        ///<summary>
        /// Updates the time of impact for the pair.
        ///</summary>
        ///<param name="requester">Collidable requesting the update.</param>
        ///<param name="dt">Timestep duration.</param>
        public override void UpdateTimeOfImpact(Collidable requester, float dt)
        {
            //TODO: This conditional early outing stuff could be pulled up into a common system, along with most of the pair handler.
            var overlap    = BroadPhaseOverlap;
            var convexMode = convex.entity == null ? PositionUpdateMode.Discrete : convex.entity.PositionUpdateMode;

            if (
                (mobileMesh.IsActive || (convex.entity == null ? false : convex.entity.activityInformation.IsActive)) &&     //At least one has to be active.
                (
                    (
                        convexMode == PositionUpdateMode.Continuous &&       //If both are continuous, only do the process for A.
                        mobileMesh.entity.PositionUpdateMode == PositionUpdateMode.Continuous &&
                        overlap.entryA == requester
                    ) ||
                    (
                        convexMode == PositionUpdateMode.Continuous ^       //If only one is continuous, then we must do it.
                        mobileMesh.entity.PositionUpdateMode == PositionUpdateMode.Continuous
                    )
                )
                )
            {
                //TODO: This system could be made more robust by using a similar region-based rejection of edges.
                //CCD events are awfully rare under normal circumstances, so this isn't usually an issue.

                //Only perform the test if the minimum radii are small enough relative to the size of the velocity.
                Vector3 velocity;
                if (convex.entity != null)
                {
                    Vector3.Subtract(ref convex.entity.linearVelocity, ref mobileMesh.entity.linearVelocity, out velocity);
                }
                else
                {
                    Vector3.Negate(ref mobileMesh.entity.linearVelocity, out velocity);
                }
                Vector3.Multiply(ref velocity, dt, out velocity);
                float velocitySquared = velocity.LengthSquared();

                var minimumRadius = convex.Shape.minimumRadius * MotionSettings.CoreShapeScaling;
                timeOfImpact = 1;
                if (minimumRadius * minimumRadius < velocitySquared)
                {
                    TriangleSidedness sidedness = mobileMesh.Shape.Sidedness;
                    Matrix3X3         orientation;
                    Matrix3X3.CreateFromQuaternion(ref mobileMesh.worldTransform.Orientation, out orientation);
                    var triangle = Resources.GetTriangle();
                    triangle.collisionMargin = 0;
                    //Spherecast against all triangles to find the earliest time.
                    for (int i = 0; i < MeshManifold.overlappedTriangles.count; i++)
                    {
                        MeshBoundingBoxTreeData data = mobileMesh.Shape.TriangleMesh.Data;
                        int triangleIndex            = MeshManifold.overlappedTriangles.Elements[i];
                        data.GetTriangle(triangleIndex, out triangle.vA, out triangle.vB, out triangle.vC);
                        Matrix3X3.Transform(ref triangle.vA, ref orientation, out triangle.vA);
                        Matrix3X3.Transform(ref triangle.vB, ref orientation, out triangle.vB);
                        Matrix3X3.Transform(ref triangle.vC, ref orientation, out triangle.vC);
                        Vector3.Add(ref triangle.vA, ref mobileMesh.worldTransform.Position, out triangle.vA);
                        Vector3.Add(ref triangle.vB, ref mobileMesh.worldTransform.Position, out triangle.vB);
                        Vector3.Add(ref triangle.vC, ref mobileMesh.worldTransform.Position, out triangle.vC);
                        //Put the triangle into 'localish' space of the convex.
                        Vector3.Subtract(ref triangle.vA, ref convex.worldTransform.Position, out triangle.vA);
                        Vector3.Subtract(ref triangle.vB, ref convex.worldTransform.Position, out triangle.vB);
                        Vector3.Subtract(ref triangle.vC, ref convex.worldTransform.Position, out triangle.vC);

                        RayHit rayHit;
                        if (GJKToolbox.CCDSphereCast(new Ray(Toolbox.ZeroVector, velocity), minimumRadius, triangle, ref Toolbox.RigidIdentity, timeOfImpact, out rayHit) &&
                            rayHit.T > Toolbox.BigEpsilon)
                        {
                            if (sidedness != TriangleSidedness.DoubleSided)
                            {
                                Vector3 AB, AC;
                                Vector3.Subtract(ref triangle.vB, ref triangle.vA, out AB);
                                Vector3.Subtract(ref triangle.vC, ref triangle.vA, out AC);
                                Vector3 normal;
                                Vector3.Cross(ref AB, ref AC, out normal);
                                float dot;
                                Vector3.Dot(ref normal, ref rayHit.Normal, out dot);
                                //Only perform sweep if the object is in danger of hitting the object.
                                //Triangles can be one sided, so check the impact normal against the triangle normal.
                                if (sidedness == TriangleSidedness.Counterclockwise && dot < 0 ||
                                    sidedness == TriangleSidedness.Clockwise && dot > 0)
                                {
                                    timeOfImpact = rayHit.T;
                                }
                            }
                            else
                            {
                                timeOfImpact = rayHit.T;
                            }
                        }
                    }
                    Resources.GiveBack(triangle);
                }
            }
        }
Ejemplo n.º 21
0
 /// <summary>
 /// Raises the appropriate ParentObject collision events depending on its CollisionType value
 /// </summary>
 /// <param name="sender">The current ISpaceObject instance</param>
 /// <param name="other">The ISpaceObject instance which collided</param>
 /// <param name="pair"/>
 private void OnStaticMeshCollisionDetected(StaticMesh sender, Collidable other, CollidablePairHandler pair)
 {
     OnCollisionDetected(sender, other, pair);
 }
Ejemplo n.º 22
0
        //TODO: At the time of writing this, the default project configuration for the Xbox360 didn't allow optional parameters.  Could compress this.

        protected void TryToAdd(Collidable a, Collidable b)
        {
            TryToAdd(a, b, null, null);
        }
Ejemplo n.º 23
0
        ///<summary>
        /// Updates the time of impact for the pair.
        ///</summary>
        ///<param name="requester">Collidable requesting the update.</param>
        ///<param name="dt">Timestep duration.</param>
        public override void UpdateTimeOfImpact(Collidable requester, float dt)
        {
            var overlap = BroadPhaseOverlap;
            var triangleMode = triangle.entity == null ? PositionUpdateMode.Discrete : triangle.entity.PositionUpdateMode;
            var convexMode = convex.entity == null ? PositionUpdateMode.Discrete : convex.entity.PositionUpdateMode;
            if (
                    (overlap.entryA.IsActive || overlap.entryB.IsActive) && //At least one has to be active.
                    (
                        (
                            convexMode == PositionUpdateMode.Continuous &&   //If both are continuous, only do the process for A.
                            triangleMode == PositionUpdateMode.Continuous &&
                            overlap.entryA == requester
                        ) ||
                        (
                            convexMode == PositionUpdateMode.Continuous ^   //If only one is continuous, then we must do it.
                            triangleMode == PositionUpdateMode.Continuous
                        )
                    )
                )
            {


                //Only perform the test if the minimum radii are small enough relative to the size of the velocity.
                Vector3 velocity;
                if (convexMode == PositionUpdateMode.Discrete)
                {
                    //Triangle is static for the purposes of this continuous test.
                    velocity = triangle.entity.linearVelocity;
                }
                else if (triangleMode == PositionUpdateMode.Discrete)
                {
                    //Convex is static for the purposes of this continuous test.
                    Vector3.Negate(ref convex.entity.linearVelocity, out velocity);
                }
                else
                {
                    //Both objects are moving.
                    Vector3.Subtract(ref triangle.entity.linearVelocity, ref convex.entity.linearVelocity, out velocity);
                }
                Vector3.Multiply(ref velocity, dt, out velocity);
                float velocitySquared = velocity.LengthSquared();

                var minimumRadiusA = convex.Shape.minimumRadius * MotionSettings.CoreShapeScaling;
                timeOfImpact = 1;
                if (minimumRadiusA * minimumRadiusA < velocitySquared)
                {
                    //Spherecast A against B.
                    RayHit rayHit;
                    if (GJKToolbox.CCDSphereCast(new Ray(convex.worldTransform.Position, -velocity), minimumRadiusA, triangle.Shape, ref triangle.worldTransform, timeOfImpact, out rayHit))
                    {
                        if (triangle.Shape.sidedness != TriangleSidedness.DoubleSided)
                        {                
                            //Only perform sweep if the object is in danger of hitting the object.
                            //Triangles can be one sided, so check the impact normal against the triangle normal.
                            Vector3 AB, AC;
                            Vector3.Subtract(ref triangle.Shape.vB, ref triangle.Shape.vA, out AB);
                            Vector3.Subtract(ref triangle.Shape.vC, ref triangle.Shape.vA, out AC);
                            Vector3 normal;
                            Vector3.Cross(ref AB, ref AC, out normal);

                            float dot;
                            Vector3.Dot(ref rayHit.Normal, ref normal, out dot);
                            if (triangle.Shape.sidedness == TriangleSidedness.Counterclockwise && dot < 0 ||
                                triangle.Shape.sidedness == TriangleSidedness.Clockwise && dot > 0)
                            {
                                timeOfImpact = rayHit.T;
                            }
                        }
                        else
                        {
                            timeOfImpact = rayHit.T;
                        }
                    }
                }

                //TECHNICALLY, the triangle should be casted too.  But, given the way triangles are usually used and their tiny minimum radius, ignoring it is usually just fine.
                //var minimumRadiusB = triangle.minimumRadius * MotionSettings.CoreShapeScaling;
                //if (minimumRadiusB * minimumRadiusB < velocitySquared)
                //{
                //    //Spherecast B against A.
                //    RayHit rayHit;
                //    if (GJKToolbox.SphereCast(new Ray(triangle.entity.position, velocity), minimumRadiusB, convex.Shape, ref convex.worldTransform, 1, out rayHit) &&
                //        rayHit.T < timeOfImpact)
                //    {
                //        if (triangle.Shape.sidedness != TriangleSidedness.DoubleSided)
                //        {
                //            float dot;
                //            Vector3.Dot(ref rayHit.Normal, ref normal, out dot);
                //            if (dot > 0)
                //            {
                //                timeOfImpact = rayHit.T;
                //            }
                //        }
                //        else
                //        {
                //            timeOfImpact = rayHit.T;
                //        }
                //    }
                //}

                //If it's intersecting, throw our hands into the air and give up.
                //This is generally a perfectly acceptable thing to do, since it's either sitting
                //inside another object (no ccd makes sense) or we're still in an intersecting case
                //from a previous frame where CCD took place and a contact should have been created
                //to deal with interpenetrating velocity.  Sometimes that contact isn't sufficient,
                //but it's good enough.
                if (timeOfImpact == 0)
                    timeOfImpact = 1;
            }

        }
Ejemplo n.º 24
0
 protected void TryToAdd(Collidable a, Collidable b, Material materialA)
 {
     TryToAdd(a, b, materialA, null);
 }
Ejemplo n.º 25
0
 public abstract bool Collide(Collidable b);
Ejemplo n.º 26
0
        public virtual void onCollide(Collidable entity, IWall wall)
        {
            CollisionEvent args = new CollisionEvent(entity, wall);

            Colliders(this, args);
        }
Ejemplo n.º 27
0
 protected void AddToCollideList(Collidable c)
 {
     collidablesToAdd.Add(c);
 }
Ejemplo n.º 28
0
 public void Subscribe(EventHandler <CollisionEvent> handler, Collidable entity)
 {
     Colliders += handler;
     AllCollidables.Add(entity);
 }
Ejemplo n.º 29
0
 internal EventStorageInitialCollisionDetected(Collidable other, CollidablePairHandler pair)
 {
     this.pair = pair;
     this.other = other;
 }
Ejemplo n.º 30
0
 public void unSubscribe(EventHandler <CollisionEvent> handler, Collidable entity)
 {
     Colliders -= handler;
     AllCollidables.Remove(entity);
 }
Ejemplo n.º 31
0
 internal EventStorageCollisionEnded(Collidable other, CollidablePairHandler pair)
 {
     this.other = other;
     this.pair = pair;
 }
Ejemplo n.º 32
0
 ///<summary>
 /// Updates the time of impact for the pair.
 ///</summary>
 ///<param name="requester">Collidable requesting the update.</param>
 ///<param name="dt">Timestep duration.</param>
 public abstract void UpdateTimeOfImpact(Collidable requester, float dt);
Ejemplo n.º 33
0
 ///<summary>
 /// Updates the time of impact for the pair.
 ///</summary>
 ///<param name="requester">Collidable requesting the update.</param>
 ///<param name="dt">Timestep duration.</param>
 public abstract void UpdateTimeOfImpact(Collidable requester, float dt);
Ejemplo n.º 34
0
        ///<summary>
        /// Updates the time of impact for the pair.
        ///</summary>
        ///<param name="requester">Collidable requesting the update.</param>
        ///<param name="dt">Timestep duration.</param>
        public override void UpdateTimeOfImpact(Collidable requester, float dt)
        {
            var collidableA = CollidableA as ConvexCollidable;
            var collidableB = CollidableB as ConvexCollidable;
            var modeA       = collidableA.entity == null ? PositionUpdateMode.Discrete : collidableA.entity.PositionUpdateMode;
            var modeB       = collidableB.entity == null ? PositionUpdateMode.Discrete : collidableB.entity.PositionUpdateMode;

            var overlap = BroadPhaseOverlap;

            if (
                (overlap.entryA.IsActive || overlap.entryB.IsActive) &&     //At least one has to be active.
                (
                    (
                        modeA == PositionUpdateMode.Continuous &&       //If both are continuous, only do the process for A.
                        modeB == PositionUpdateMode.Continuous &&
                        overlap.entryA == requester
                    ) ||
                    (
                        modeA == PositionUpdateMode.Continuous ^       //If only one is continuous, then we must do it.
                        modeB == PositionUpdateMode.Continuous
                    )

                )
                )
            {
                //Only perform the test if the minimum radii are small enough relative to the size of the velocity.
                //Discrete objects have already had their linear motion integrated, so don't use their velocity.
                Vector3 velocity;
                if (modeA == PositionUpdateMode.Discrete)
                {
                    //CollidableA is static for the purposes of this continuous test.
                    velocity = collidableB.entity.linearVelocity;
                }
                else if (modeB == PositionUpdateMode.Discrete)
                {
                    //CollidableB is static for the purposes of this continuous test.
                    Vector3.Negate(ref collidableA.entity.linearVelocity, out velocity);
                }
                else
                {
                    //Both objects are moving.
                    Vector3.Subtract(ref collidableB.entity.linearVelocity, ref collidableA.entity.linearVelocity, out velocity);
                }
                Vector3.Multiply(ref velocity, dt, out velocity);
                float velocitySquared = velocity.LengthSquared();

                var minimumRadiusA = collidableA.Shape.minimumRadius * MotionSettings.CoreShapeScaling;
                timeOfImpact = 1;
                if (minimumRadiusA * minimumRadiusA < velocitySquared)
                {
                    //Spherecast A against B.
                    RayHit rayHit;
                    if (GJKToolbox.CCDSphereCast(new Ray(collidableA.worldTransform.Position, -velocity), minimumRadiusA, collidableB.Shape, ref collidableB.worldTransform, timeOfImpact, out rayHit))
                    {
                        timeOfImpact = rayHit.T;
                    }
                }

                var minimumRadiusB = collidableB.Shape.minimumRadius * MotionSettings.CoreShapeScaling;
                if (minimumRadiusB * minimumRadiusB < velocitySquared)
                {
                    //Spherecast B against A.
                    RayHit rayHit;
                    if (GJKToolbox.CCDSphereCast(new Ray(collidableB.worldTransform.Position, velocity), minimumRadiusB, collidableA.Shape, ref collidableA.worldTransform, timeOfImpact, out rayHit))
                    {
                        timeOfImpact = rayHit.T;
                    }
                }

                //If it's intersecting, throw our hands into the air and give up.
                //This is generally a perfectly acceptable thing to do, since it's either sitting
                //inside another object (no ccd makes sense) or we're still in an intersecting case
                //from a previous frame where CCD took place and a contact should have been created
                //to deal with interpenetrating velocity.  Sometimes that contact isn't sufficient,
                //but it's good enough.
                if (timeOfImpact == 0)
                {
                    timeOfImpact = 1;
                }
            }
        }
Ejemplo n.º 35
0
        public void InsertCollidable(Collidable c)
        {
            if (c.Spawning_Or_Hit) return;

            for (int piece_i = 0; piece_i < c.Rigid.Geometries.Count; piece_i++)
            {

                Grid_Query_Counter.Counter++;
                var piece = c.Rigid.Geometries[piece_i];

                var placement = piece.placement;
                if (placement.own_group >= 2)
                {
                    placement.row_width = 1; placement.col_width = 1;
                }
                int border = placement.own_group < 2 ? 1 : 0;

                for (int group_i = 0; group_i < placement.groups_it_hits.Length; group_i++)
                    for (int i = -border; i < placement.row_width + border; i++)//ta width xekinane me 1
                        for (int j = -border; j < placement.col_width + border; j++)
                        {

                            var list = grids[placement.groups_it_hits[group_i]].getBucket(placement.coords.col + j, placement.coords.row + i);

                            for (int u = 0; u < list.Count; u++)
                            {
                                if (!((list[u].row == placement.coords.row + i) && (list[u].col == placement.coords.col + j))) continue;
                                var other = list[u].g;

                                current_pair_element_1 = piece;
                                current_pair_element_2 = other;

                                if ((other.Coll.Ignore_In_Collisions_Cause_It_Got_Killed) || (other.Coll.Spawning_Or_Hit) || other.Coll == piece.Coll)
                                    continue;

                                if (other.Last_Query < Grid_Query_Counter.Counter)
                                {
                                    other.Last_Query = Grid_Query_Counter.Counter;

                                    var dispatcher = Dispatcher.Dispatch_array[piece.Collision_Type, other.Collision_Type];

                                    var coarse_test = dispatcher.Coarse_Test;
                                    if(coarse_test==null)
                                    {

                                        continue;
                                    }
                                    var check_coarse = dispatcher.rever_coarse?coarse_test(other, piece):coarse_test(piece, other);
                                    if(!check_coarse)
                                    {

                                        continue;
                                    }

                                    var test_call = dispatcher.Test;

                                    if (test_call != null)
                                    {
                                        var test_result = dispatcher.rever_test? test_call( other,piece): test_call(piece, other);
                                        if (test_result)
                                        {
                                            piece.Coll.Intersecting.Add(other.Coll);
                                            other.Coll.Intersecting.Add(piece.Coll);

                                            if (dispatcher.kill_first) piece.Ignore_In_Collisions_Cause_It_Got_Killed = true;
                                            if (dispatcher.kill_second) other.Ignore_In_Collisions_Cause_It_Got_Killed = true;
                                            if (dispatcher.kill_first) return;
                                            if (dispatcher.kill_second) continue;

                                        }
                                    }

                                    var intersect_call = dispatcher.I_Test;

                                    if (intersect_call != null)
                                    {
                                        var intersect_call_result = dispatcher.rever_intersect? intersect_call( other,piece): intersect_call(piece, other);
                                        if (intersect_call_result)
                                        {
                                            piece.Coll.Contacted.Add(other.Coll);
                                            other.Coll.Contacted.Add(piece.Coll);

                                        }
                                    }

                                }

                            }

                        }

                //do not store enemies in the grid, only test them against existing geometry
                if (placement.own_group < 2)
                    for (int i = -1; i < placement.row_width + 1; i++)
                        for (int j = -1; j < placement.col_width + 1; j++)
                        {

                            grids[placement.own_group].Insert(placement.coords.col + i, placement.coords.row + j, piece);

                        }

            }

            return;
        }
Ejemplo n.º 36
0
        ///<summary>
        /// Updates the time of impact for the pair.
        ///</summary>
        ///<param name="requester">Collidable requesting the update.</param>
        ///<param name="dt">Timestep duration.</param>
        public override void UpdateTimeOfImpact(Collidable requester, float dt)
        {
            //Notice that we don't test for convex entity null explicitly.  The convex.IsActive property does that for us.
            if (convex.IsActive && convex.entity.PositionUpdateMode == PositionUpdateMode.Continuous)
            {
                //TODO: This system could be made more robust by using a similar region-based rejection of edges.
                //CCD events are awfully rare under normal circumstances, so this isn't usually an issue.

                //Only perform the test if the minimum radii are small enough relative to the size of the velocity.
                Vector3f velocity;
                Vector3f.Multiply(ref convex.entity.linearVelocity, dt, out velocity);
                float velocitySquared = velocity.LengthSquared;

                var minimumRadius = convex.Shape.MinimumRadius * MotionSettings.CoreShapeScaling;
                timeOfImpact = 1;
                if (minimumRadius * minimumRadius < velocitySquared)
                {
                    var triangle = PhysicsThreadResources.GetTriangle();
                    triangle.collisionMargin = 0;
                    //Spherecast against all triangles to find the earliest time.
                    for (int i = 0; i < MeshManifold.overlappedTriangles.Count; i++)
                    {
                        MeshBoundingBoxTreeData data = instancedMesh.Shape.TriangleMesh.Data;
                        int triangleIndex            = MeshManifold.overlappedTriangles.Elements[i];
                        data.GetTriangle(triangleIndex, out triangle.vA, out triangle.vB, out triangle.vC);
                        AffineTransform.Transform(ref triangle.vA, ref instancedMesh.worldTransform, out triangle.vA);
                        AffineTransform.Transform(ref triangle.vB, ref instancedMesh.worldTransform, out triangle.vB);
                        AffineTransform.Transform(ref triangle.vC, ref instancedMesh.worldTransform, out triangle.vC);
                        //Put the triangle into 'localish' space of the convex.
                        Vector3f.Subtract(ref triangle.vA, ref convex.worldTransform.Position, out triangle.vA);
                        Vector3f.Subtract(ref triangle.vB, ref convex.worldTransform.Position, out triangle.vB);
                        Vector3f.Subtract(ref triangle.vC, ref convex.worldTransform.Position, out triangle.vC);

                        RayHit rayHit;
                        if (GJKToolbox.CCDSphereCast(new Ray(Toolbox.ZeroVector, velocity), minimumRadius, triangle, ref MathHelper.RigidIdentity, timeOfImpact, out rayHit) &&
                            rayHit.T > MathHelper.BigEpsilon)
                        {
                            if (instancedMesh.sidedness != TriangleSidedness.DoubleSided)
                            {
                                Vector3f AB, AC;
                                Vector3f.Subtract(ref triangle.vB, ref triangle.vA, out AB);
                                Vector3f.Subtract(ref triangle.vC, ref triangle.vA, out AC);
                                Vector3f normal;
                                Vector3f.Cross(ref AB, ref AC, out normal);
                                float dot;
                                Vector3f.Dot(ref normal, ref rayHit.Normal, out dot);
                                //Only perform sweep if the object is in danger of hitting the object.
                                //Triangles can be one sided, so check the impact normal against the triangle normal.
                                if (instancedMesh.sidedness == TriangleSidedness.Counterclockwise && dot < 0 ||
                                    instancedMesh.sidedness == TriangleSidedness.Clockwise && dot > 0)
                                {
                                    timeOfImpact = rayHit.T;
                                }
                            }
                            else
                            {
                                timeOfImpact = rayHit.T;
                            }
                        }
                    }
                    PhysicsThreadResources.GiveBack(triangle);
                }
            }
        }
Ejemplo n.º 37
0
 public override bool Collide(Collidable c)
 {
     //do nothing here
     return false;
 }
Ejemplo n.º 38
0
 public bool Collide(Collidable b)
 {
     //nothing happens to the line
     return false;
 }
 public void AddCollidable(Collidable c)
 {
     collidableEntities.Add(c);
 }
Ejemplo n.º 40
0
    protected bool checkPlatforms(Collidable[] platforms)
    {
        //Skip if no platforms
        bool Landed = false;
        if (platforms != null) {
            //For each platforms
            for (int i = 0; i < platforms.Length; i++) {
                //If collide
                if (doesCollide(platforms[i])) {
                    //If going down and still above
                    if (y - (m_Height / 4) > platforms[i].getTop() && m_SpeedY <= 0) {
                        //Check left and right
                        if (x < platforms[i].getRight()) {
                            //Set Y
                            y 		= platforms[i].getTop() + (m_Height / 2) - 1;
                            Landed 	= true;
                        }
                    }
                }
            }
        }

        //Return
        return Landed;
    }
 public void RemoveCollidable(Collidable c)
 {
     collidableEntities.Remove(c);
 }
Ejemplo n.º 42
0
 public virtual bool Collide(Collidable c)
 {
     if (c is Bibble)
     {
         Bibble b = (Bibble)c;
         switch (Type)
         {
             case ItemType.Acceleration: b.MaxAcceleration += Value; break;
             case ItemType.BulletDamage: b.BulletDamage += Value; break;
             case ItemType.BulletSpeed: b.BulletSpeed += Value; break;
             case ItemType.BulletSplit: b.SplitBulletMode += Value; break;
             case ItemType.Health: b.Health += Value; break;
             case ItemType.MineDamage: b.MineDamage += Value; break;
             case ItemType.MineOuterRadius: b.MineOuterRadius += Value; break;
             case ItemType.Speed: b.MaxSpeed += Value; break;
             case ItemType.Killer:
                 BibbleGame bg = Game as BibbleGame;
                 if (bg == null) break;
                 bg.Detonate(new Mine(Position, null, BibbleGame.Statics.MineTex, bg));
                 break;
         }
         BibbleGame.Statics.quack.Play(.1f, 0, 0);
         return true;
     }
     return false;
 }
Ejemplo n.º 43
0
 public Collider(Collidable owner, Rectangle bounds, ColliderType type)
 {
     this.owner = owner;
     this.bounds = new DoubleRect(bounds.X, bounds.Y, bounds.Width, bounds.Height);
     this.type = type;
 }
Ejemplo n.º 44
0
        public void Draw(Camera camera, Microsoft.Xna.Framework.Point playerPosition, Collidable.Collidable.Orientation orientation, Collidable.Collidable.MoveState moveState)
        {
            #region Toon
            //wallBig.ForEachEffect(EffectTranslator.Settings);
            //wallSmall.ForEachEffect(EffectTranslator.Settings);
            #endregion

            for (int i = 0; i < movableArea.GetLength(0); i++)
                for (int j = 0; j < movableArea.GetLength(1); j++)
                {
                    // 壁の描画領域を制限する(Gキーを押している間は制限しない)
                    if (!Input.Instance.DownKey(Microsoft.Xna.Framework.Input.Keys.G))
                    {
                        if ((i - playerPosition.Y) * (i - playerPosition.Y) + (j - playerPosition.X) * (j - playerPosition.X) > drawAreaRadius * drawAreaRadius)
                        {
                            continue;
                        }
                        else if (moveState != Collidable.Collidable.MoveState.TurnLeft && moveState != Collidable.Collidable.MoveState.TurnRight)
                        {
                            #region 後ろを描画制限
                            if (orientation == Collidable.Collidable.Orientation.North)
                            {
                                if (i - playerPosition.Y > 4)
                                {
                                    continue;
                                }
                            }
                            else if (orientation == Collidable.Collidable.Orientation.South)
                            {
                                if (playerPosition.Y - i > 4)
                                {
                                    continue;
                                }
                            }
                            else if (orientation == Collidable.Collidable.Orientation.West)
                            {
                                if (j - playerPosition.X > 4)
                                {
                                    continue;
                                }
                            }
                            else if (orientation == Collidable.Collidable.Orientation.East)
                            {
                                if (playerPosition.X - j > 4)
                                {
                                    continue;
                                }
                            }
                            #endregion
                        }
                    }
                    Matrix world = Matrix.CreateTranslation((float)(j / 2 * (wallDepth + wallWidth) + j % 2 * ((wallDepth + wallWidth) / 2)), 0, (float)(i / 2 * (wallDepth + wallWidth) + i % 2 * ((wallDepth + wallWidth) / 2)));
                    if (movableArea[i, j])
                    {
                        if ((i % 2) == 1 && (j % 2) == 1)
                        {
                            groundBig.Draw(world, camera.View, camera.Projection);
                        }
                        else if ((i % 2) == 1)
                            groundSmall.Draw(Matrix.CreateRotationY(MathHelper.PiOver2) * world, camera.View, camera.Projection);
                        else
                            groundSmall.Draw(world, camera.View, camera.Projection);

                        continue;
                    }

                    world = Matrix.CreateTranslation((float)(j / 2 * (wallDepth + wallWidth) + j % 2 * ((wallDepth + wallWidth) / 2)), 0, (float)(i / 2 * (wallDepth + wallWidth) + i % 2 * ((wallDepth + wallWidth) / 2)));
                    if (i % 2 == 0 && j % 2 == 0)
                        wallSmall.Draw(world, camera.View, camera.Projection);
                    else
                        if (i % 2 == 1)
                            wallBig.Draw(Matrix.CreateRotationY(MathHelper.PiOver2) * world, camera.View, camera.Projection);
                        else
                            wallBig.Draw(world, camera.View, camera.Projection);
                }
        }
        void IBeforeNarrowPhaseUpdateable.Update(float dt)
        {
            //Cast down to find the support.

            //In a 6DOF character, the starting transform will vary.
            //For now, just assume it's locked to Up.
            RigidTransform startingTransform = new RigidTransform();
            startingTransform.Position = Body.Position;
            startingTransform.Position.Y -= Body.Length * .5f;
            startingTransform.Orientation = Quaternion.Identity;

            //Compute the sweep direction.  This too will change in a 6DOF character (Body.OrientationMatrix.Down instead of Vector3.Down).
            //If the body had traction last frame, then do a full-length sweep; this will detect step-downs.
            //If it didn't have traction, just cast down by one step height to try and find a support.
            //The reason why Body.Radius is added is that the starting transform is embedded in the capsule.
            sweepLength = hasTraction ? StepHeight * 2 + Body.Radius : StepHeight + Body.Radius + supportMargin;
            sweep = new Vector3(0, -sweepLength, 0);

            //Cycle through every collidable and find the first time of impact for the convex cast.

            support = null;
            supportData = new RayHit() { T = float.MaxValue }; //Set the T value to an extremely high value to start with so that any result will be lower.
            foreach (var collidable in Body.CollisionInformation.OverlappedCollidables)
            {
                if (convexCastDownVolume.Intersects(collidable.BoundingBox))
                {
                    RayHit hit;
                    if (collidable.ConvexCast(castShape, ref startingTransform, ref sweep, out hit) && hit.T < supportData.T)
                    {
                        supportData = hit;
                        support = collidable;
                    }

                }
            }

            goalSupportT = (Body.Radius + StepHeight) / sweepLength;

            //If there's any support, analyze it.
            //Check the slope of the hit against the maximum.
            //This is a dot product of the normal against the body up vector (in this implementation, always {0, 1, 0}).
            //For a fixed up vector of {0,1,0}, the dot product result is just the Y component of the normal.
            //The following slope test is equivalent to MaximumTractionSlope > Math.Acos(Vector3.Dot(-firstHitData.Normal, Vector3.Up))
            hasTraction = support != null & cosMaximumTractionSlope < -supportData.Normal.Y;

            //Compute the relative velocity between the capsule and its support, if any.
            //The relative velocity will be updated as impulses are applied.
            Vector3 relativeVelocity = Body.LinearVelocity;
            if (IsSupported)
            {
                //Only entities has velocity.
                var entityCollidable = support as EntityCollidable;
                if (entityCollidable != null)
                {
                    Vector3 entityVelocity = Toolbox.GetVelocityOfPoint(supportData.Location, entityCollidable.Entity);
                    Vector3.Subtract(ref relativeVelocity, ref entityVelocity, out relativeVelocity);
                    //TODO: Multithreaded safety.  If characters are running in parallel, ensure that this operation will not corrupt anything.
                    if (entityCollidable.Entity.IsDynamic)
                        entityCollidable.Entity.ActivityInformation.Activate();
                }
            }

            //Attempt to jump.
            if (tryToJump)
            {
                //In the following, note that the jumping velocity changes are computed such that the separating velocity is specifically achieved,
                //rather than just adding some speed along an arbitrary direction.  This avoids some cases where the character could otherwise increase
                //the jump speed, which may not be desired.
                if (hasTraction)
                {
                    //The character has traction, so jump straight up.
                    float currentUpVelocity = Vector3.Dot(Body.OrientationMatrix.Up, relativeVelocity);
                    //Target velocity is JumpSpeed.
                    float velocityChange = JumpSpeed - currentUpVelocity;
                    ChangeVelocity(Body.OrientationMatrix.Up * velocityChange, ref relativeVelocity);
                }
                else if (IsSupported)
                {
                    //The character does not have traction, so jump along the surface normal instead.
                    float currentNormalVelocity = Vector3.Dot(supportData.Normal, relativeVelocity);
                    //Target velocity is JumpSpeed.
                    float velocityChange = SlidingJumpSpeed - currentNormalVelocity;
                    ChangeVelocity(supportData.Normal * -velocityChange, ref relativeVelocity);
                }
                hasTraction = false;
                support = null;
                tryToJump = false;
            }

            //Update the vertical motion of the character.
            if (hasTraction)
            {
                //Remove all velocity, penetrating or separating, along the contact normal if it is below a threshold.
                float separatingVelocity = -Vector3.Dot(relativeVelocity, supportData.Normal);
                if (separatingVelocity < GlueSpeed)
                {
                    ChangeVelocity(supportData.Normal * separatingVelocity, ref relativeVelocity);
                }
                else
                    hasTraction = false;

            }
            else if (IsSupported)
            {
                //The character has no traction, so just stop penetrating velocity.
                float dot = -Vector3.Dot(relativeVelocity, supportData.Normal);
                if (dot < 0)
                    ChangeVelocity(supportData.Normal * dot, ref relativeVelocity);

            }

            //Update the horizontal motion of the character.
            if (IsSupported)
            {
                //If the object has traction, it has a lot more control over its motion.  If it is sliding, then use the sliding coefficients.
                float accelerationToUse = hasTraction ? Acceleration : SlidingAcceleration;
                float decelerationToUse = hasTraction ? Deceleration : SlidingDeceleration;
                Vector3 velocityDirection;
                Vector3 violatingVelocity;
                if (MovementDirection.LengthSquared() > 0)
                {
                    //Project the movement direction onto the support plane defined by the support normal.
                    //This projection is NOT along the support normal to the plane; that would cause the character to veer off course when moving on slopes.
                    //Instead, project along the sweep direction to the plane.
                    //For a 6DOF character controller, the lineStart would be different; it must be perpendicular to the local up.
                    Vector3 lineStart = new Vector3(MovementDirection.X, 0, MovementDirection.Y);
                    Vector3 lineEnd;
                    Vector3.Add(ref lineStart, ref sweep, out lineEnd);
                    Plane plane = new Plane(supportData.Normal, 0);
                    float t;
                    //This method can return false when the line is parallel to the plane, but previous tests and the slope limit guarantee that it won't happen.
                    Toolbox.GetLinePlaneIntersection(ref lineStart, ref lineEnd, ref plane, out t, out velocityDirection);

                    //The origin->intersection line direction defines the horizontal velocity direction in 3d space.
                    velocityDirection.Normalize();

                    //Compare the current velocity to the goal velocity.
                    float currentVelocity;
                    Vector3.Dot(ref velocityDirection, ref relativeVelocity, out currentVelocity);

                    //Violating velocity is velocity which is not in the direction of the goal direction.
                    violatingVelocity = relativeVelocity - velocityDirection * currentVelocity;

                    //Compute the acceleration component.
                    float speedUpNecessary = Speed - currentVelocity;
                    float velocityChange = MathHelper.Clamp(speedUpNecessary, 0, accelerationToUse * dt);

                    //Apply the change.

                    ChangeVelocity(velocityDirection * velocityChange, ref relativeVelocity);

                }
                else
                {
                    velocityDirection = new Vector3();
                    violatingVelocity = relativeVelocity;
                }

                //Compute the deceleration component.
                float lengthSquared = violatingVelocity.LengthSquared();
                if (lengthSquared > 0)
                {
                    Vector3 violatingVelocityDirection;
                    float violatingVelocityMagnitude = (float)Math.Sqrt(lengthSquared);
                    Vector3.Divide(ref violatingVelocity, violatingVelocityMagnitude, out violatingVelocityDirection);

                    //We need to get rid of the violating velocity magnitude, but don't go under zero (that would cause nasty oscillations).
                    float velocityChange = -Math.Min(decelerationToUse * dt, violatingVelocityMagnitude);
                    //Apply the change.
                    ChangeVelocity(violatingVelocityDirection * velocityChange, ref relativeVelocity);
                }

            }
            else
            {
                //The character is in the air.  Still allow a little air control!
                //6DOF character controllers will likely completely replace this; if it doesn't,
                //use an oriented velocity direction instead of 2d movement direction.
                var velocityDirection = new Vector3(MovementDirection.X, 0, MovementDirection.Y);

                //Compare the current velocity to the goal velocity.
                float currentVelocity;
                Vector3.Dot(ref velocityDirection, ref relativeVelocity, out currentVelocity);

                //Compute the acceleration component.
                float speedUpNecessary = AirSpeed - currentVelocity;
                float velocityChange = MathHelper.Clamp(speedUpNecessary, 0, AirAcceleration * dt);

                //Apply the change.
                ChangeVelocity(velocityDirection * velocityChange, ref relativeVelocity);
            }
        }
 public override void OnRemovalFromSpace(ISpace oldSpace)
 {
     //Remove any supplements from the space too.
     oldSpace.Remove(Body);
     //This character controller requires the standard implementation of Space.
     ((Space)oldSpace).BoundingBoxUpdater.Finishing -= ExpandBoundingBox;
     support = null;
     supportData = new RayHit();
     hasTraction = false;
     Body.AngularVelocity = new Vector3();
     Body.LinearVelocity = new Vector3();
 }
Ejemplo n.º 47
0
        ///<summary>
        /// Updates the time of impact for the pair.
        ///</summary>
        ///<param name="requester">Collidable requesting the update.</param>
        ///<param name="dt">Timestep duration.</param>
        public override void UpdateTimeOfImpact(Collidable requester, float dt)
        {
            //Notice that we don't test for convex entity null explicitly.  The convex.IsActive property does that for us.
            if (convex.IsActive && convex.entity.PositionUpdateMode == PositionUpdateMode.Continuous)
            {
                //TODO: This system could be made more robust by using a similar region-based rejection of edges.
                //CCD events are awfully rare under normal circumstances, so this isn't usually an issue.

                //Only perform the test if the minimum radii are small enough relative to the size of the velocity.
                Vector3 velocity;
                Vector3.Multiply(ref convex.entity.linearVelocity, dt, out velocity);
                float velocitySquared = velocity.LengthSquared();

                var minimumRadius = convex.Shape.minimumRadius * MotionSettings.CoreShapeScaling;
                timeOfImpact = 1;
                if (minimumRadius * minimumRadius < velocitySquared)
                {
                    var triangle = Resources.GetTriangle();
                    triangle.collisionMargin = 0;
                    //Spherecast against all triangles to find the earliest time.
                    for (int i = 0; i < MeshManifold.overlappedTriangles.count; i++)
                    {
                        MeshBoundingBoxTreeData data = instancedMesh.Shape.TriangleMesh.Data;
                        int triangleIndex = MeshManifold.overlappedTriangles.Elements[i];
                        data.GetTriangle(triangleIndex, out triangle.vA, out triangle.vB, out triangle.vC);
                        AffineTransform.Transform(ref triangle.vA, ref instancedMesh.worldTransform, out triangle.vA);
                        AffineTransform.Transform(ref triangle.vB, ref instancedMesh.worldTransform, out triangle.vB);
                        AffineTransform.Transform(ref triangle.vC, ref instancedMesh.worldTransform, out triangle.vC);
                        //Put the triangle into 'localish' space of the convex.
                        Vector3.Subtract(ref triangle.vA, ref convex.worldTransform.Position, out triangle.vA);
                        Vector3.Subtract(ref triangle.vB, ref convex.worldTransform.Position, out triangle.vB);
                        Vector3.Subtract(ref triangle.vC, ref convex.worldTransform.Position, out triangle.vC);

                        RayHit rayHit;
                        if (GJKToolbox.CCDSphereCast(new Ray(Toolbox.ZeroVector, velocity), minimumRadius, triangle, ref Toolbox.RigidIdentity, timeOfImpact, out rayHit) &&
                            rayHit.T > Toolbox.BigEpsilon)
                        {

                            if (instancedMesh.sidedness != TriangleSidedness.DoubleSided)
                            {
                                Vector3 AB, AC;
                                Vector3.Subtract(ref triangle.vB, ref triangle.vA, out AB);
                                Vector3.Subtract(ref triangle.vC, ref triangle.vA, out AC);
                                Vector3 normal;
                                Vector3.Cross(ref AB, ref AC, out normal);
                                float dot;
                                Vector3.Dot(ref normal, ref rayHit.Normal, out dot);
                                //Only perform sweep if the object is in danger of hitting the object.
                                //Triangles can be one sided, so check the impact normal against the triangle normal.
                                if (instancedMesh.sidedness == TriangleSidedness.Counterclockwise && dot < 0 ||
                                    instancedMesh.sidedness == TriangleSidedness.Clockwise && dot > 0)
                                {
                                    timeOfImpact = rayHit.T;
                                }
                            }
                            else
                            {
                                timeOfImpact = rayHit.T;
                            }
                        }
                    }
                    Resources.GiveBack(triangle);
                }



            }

        }
Ejemplo n.º 48
0
        /// <summary>
        /// Finds a supporting entity, the contact location, and the contact normal.
        /// </summary>
        /// <param name="location">Contact point between the wheel and the support.</param>
        /// <param name="normal">Contact normal between the wheel and the support.</param>
        /// <param name="suspensionLength">Length of the suspension at the contact.</param>
        /// <param name="supportingCollidable">Collidable supporting the wheel, if any.</param>
        /// <param name="entity">Supporting object.</param>
        /// <param name="material">Material of the wheel.</param>
        /// <returns>Whether or not any support was found.</returns>
        protected internal override bool FindSupport(out Vector3 location, out Vector3 normal, out float suspensionLength, out Collidable supportingCollidable, out Entity entity, out Material material)
        {
            suspensionLength     = float.MaxValue;
            location             = Toolbox.NoVector;
            supportingCollidable = null;
            entity   = null;
            normal   = Toolbox.NoVector;
            material = null;

            Collidable testCollidable;
            RayHit     rayHit;

            bool hit = false;

            for (int i = 0; i < detector.CollisionInformation.pairs.Count; ++i)
            {
                var pair = detector.CollisionInformation.pairs[i];
                testCollidable = (pair.BroadPhaseOverlap.entryA == detector.CollisionInformation ? pair.BroadPhaseOverlap.entryB : pair.BroadPhaseOverlap.entryA) as Collidable;
                if (testCollidable != null)
                {
                    if (CollisionRules.CollisionRuleCalculator(this, testCollidable) == CollisionRule.Normal &&
                        testCollidable.RayCast(new Ray(wheel.suspension.worldAttachmentPoint, wheel.suspension.worldDirection), wheel.suspension.restLength, out rayHit) &&
                        rayHit.T < suspensionLength)
                    {
                        suspensionLength = rayHit.T;
                        EntityCollidable entityCollidable;
                        if ((entityCollidable = testCollidable as EntityCollidable) != null)
                        {
                            entity   = entityCollidable.Entity;
                            material = entityCollidable.Entity.Material;
                        }
                        else
                        {
                            entity = null;
                            supportingCollidable = testCollidable;
                            var materialOwner = testCollidable as IMaterialOwner;
                            if (materialOwner != null)
                            {
                                material = materialOwner.Material;
                            }
                        }
                        location = rayHit.Location;
                        normal   = rayHit.Normal;
                        hit      = true;
                    }
                }
            }
            if (hit)
            {
                if (suspensionLength > 0)
                {
                    normal.Normalize();
                }
                else
                {
                    Vector3.Negate(ref wheel.suspension.worldDirection, out normal);
                }
                return(true);
            }
            return(false);
        }