示例#1
0
        /// <summary>
        /// This works the same as retrieve(Tangible) but retrieves all the actors in
        /// neighbour nodes as well.
        /// </summary>
        /// <param name="actor"></param>
        /// <returns></returns>
        public List <Tangible> retrieveNeighbors(Tangible actor)
        {
            /** RightTop = 0, LeftTop = 1, LeftBottom = 2, RightBottom = 3 */
            int index = getIndex(actor);

            possibleCollisions.Clear();

            if (index != -1 && nodes[0] != null)
            {
                int neigbour1 = index - 1;
                int neigbour2 = index + 1;
                if (neigbour1 < 0)
                {
                    neigbour1 = 3;
                }
                if (neigbour2 > 3)
                {
                    neigbour2 = 0;
                }

                possibleCollisions.AddRange(nodes[neigbour1].retrieve(actor));
                possibleCollisions.AddRange(nodes[index].retrieve(actor));
                possibleCollisions.AddRange(nodes[neigbour2].retrieve(actor));
            }

            possibleCollisions.AddRange(tangibles);

            return(possibleCollisions);
        }
示例#2
0
        public virtual void update(GameTime gameTime, QuadTree quadTree)
        {
            /* Debugging */
            currentVelocity = playerShip.velocity;
            accel           = (currentVelocity - lastVelocity) / (float)gameTime.ElapsedGameTime.TotalSeconds;
            totalTime      += gameTime.ElapsedGameTime.TotalSeconds;

            if (playerShip.collideTarget != null)
            {
                target = playerShip.collideTarget;
            }
            /* Debugging */
        }
 /// <summary>
 /// Since collisions are added as the original updater being tangible1, any overlaps are likely
 /// to have tangible2 being the key, therefore tangible2 is checked first in each && statement
 /// </summary>
 /// <param name="tangible1"></param>
 /// <param name="tangible2"></param>
 /// <returns>True if the collision already exists, false otherwise</returns>
 private bool collisionExists(Tangible tangible1, Tangible tangible2)
 {
     // If this collision already exists, dictionary has to contain one or the other as a key
     //if (!collisions.ContainsKey(tangible2) && !collisions.ContainsKey(tangible1)) {
     //	return false;
     //}
     // The collision may exist as key-value pair of <tangible1, tangible2> or <tangible2, tangible1>
     if (!collisions.ContainsValue(tangible2, tangible1) && !collisions.ContainsValue(tangible1, tangible2))
     {
         return(false);
     }
     return(true);
 }
 /// <summary>
 /// Add a collision to be handled.
 /// </summary>
 /// <param name="tangible1"></param>
 /// <param name="tangible2"></param>
 public void addCollision(Tangible tangible1, Tangible tangible2, GameTime gameTime)
 {
     // check to see if collision already is in dictionary to prevent a double calculation of collision
     if (!collisionExists(tangible1, tangible2))
     {
         collisions.Add(tangible1, tangible2);
         System.Console.WriteLine("new collision " + tangible1.GetType().Name + " with " + tangible2.GetType().Name + " at " + gameTime.TotalGameTime.TotalMilliseconds);
     }
     else
     {
         System.Console.WriteLine("Collision already exists at " + gameTime.TotalGameTime.TotalMilliseconds);
     }
 }
示例#5
0
        /// <summary>
        /// Return all objects close enough that could potentially collide with this actor.
        /// </summary>
        /// <param name="actor"></param>
        /// <returns></returns>
        public List <Tangible> retrieve(Tangible actor)
        {
            int index = getIndex(actor);

            possibleCollisions.Clear();

            if (index != -1 && nodes[0] != null)
            {
                possibleCollisions.AddRange(nodes[index].retrieve(actor));
            }

            possibleCollisions.AddRange(tangibles);

            return(possibleCollisions);
        }
        /// <summary>
        /// "Bounce" an object off of another. Not great.... :/
        /// @Written by Tristan with help fromXNA 4.0 Game Development by Example -Jaegers Packt(2010)
        /// </summary>
        public void reflect(Tangible tangible1, Tangible tangible2)
        {
            Vector2 combinedMassVel =             // if both masses stick together (inelastic collision) than the resulting velocity is combinedMassVel
                                      (tangible1.velocity + tangible2.velocity) / 2;

            Vector2 normal1 = tangible2.position - tangible1.position;

            normal1.Normalize();
            Vector2 normal2 = tangible1.position - tangible2.position;

            normal2.Normalize();

            tangible1.velocity -= combinedMassVel;
            tangible1.velocity  = Vector2.Reflect(tangible1.velocity, normal1);
            tangible1.velocity += combinedMassVel;

            tangible2.velocity -= combinedMassVel;
            tangible2.velocity  = Vector2.Reflect(tangible2.velocity, normal1);
            tangible2.velocity += combinedMassVel;
        }
示例#7
0
        /// <summary>
        /// Determine which node the object belongs to. -1 means
        /// object cannot completely fit within a child node and is part
        /// of the parent node.
        /// </summary>
        /// <param name="pRect"></param>
        /// <returns></returns>
        private int getIndex(Tangible tangible)
        {
            /** RightTop = 0, LeftTop = 1, LeftBottom = 2, RightBottom = 3 */
            int    index              = -1;
            double verticalMidpoint   = bounds.X + bounds.Width / 2;
            double horizontalMidpoint = bounds.Y + bounds.Height / 2;

            // Object can completely fit within the top quadrants
            bool topQuadrant = (tangible.position.X < horizontalMidpoint &&
                                tangible.position.Y + tangible.height < horizontalMidpoint);
            // Object can completely fit within the bottom quadrants
            bool bottomQuadrant = (tangible.position.Y > horizontalMidpoint);

            // Object can completely fit within the left quadrants
            if (tangible.position.X < verticalMidpoint && tangible.position.X + tangible.width < verticalMidpoint)
            {
                if (topQuadrant)
                {
                    index = 1;
                }
                else if (bottomQuadrant)
                {
                    index = 2;
                }
            }
            // Object can completely fit within the right quadrants
            else if (tangible.position.X > verticalMidpoint)
            {
                if (topQuadrant)
                {
                    index = 0;
                }
                else if (bottomQuadrant)
                {
                    index = 3;
                }
            }

            return(index);
        }
        /// <summary>
        /// An elastic collision that takes angle of contact into consideration but not mass.
        /// @Written by Tristan
        /// </summary>
        /// <param name="tangible1"></param>
        /// <param name="tangible2"></param>
        public void elasticCollision(Tangible tangible1, Tangible tangible2)
        {
            Vector2 v2 = tangible2.velocity;
            // Change frame of reference to tangible2
            Vector2 u1 = tangible1.velocity - v2;
            Vector2 u2 = Vector2.Zero;

            // Find vector between center of masses
            Vector2 c = new Vector2(tangible2.position.X - tangible1.position.X, tangible2.position.Y - tangible1.position.Y);

            c.Normalize();

            // Find rotation for u1 to be aligned with y-axis and rotate c by that angle
            float rotation = (float)Math.Acos(u1.Y / u1.Length());


            Vector2 cR = Vector2.Transform(c, Matrix.CreateRotationZ(rotation));
            // Find angle of deflection
            float deflection = (float)Math.Acos(cR.Y / cR.Length());

            // Solve for u1prime and u2prime scalar values
            Vector2 u1prime = Vector2.Zero, u2prime = Vector2.Zero;
            float   u1primeLength = u1.Length() * (float)Math.Sin(deflection);
            float   u2primeLength = u1.Length() * (float)Math.Cos(deflection);

            // find c's parallel
            Vector2 p = new Vector2(-c.Y, c.X);

            // find u1prime & u2prime
            u1prime.X = u1primeLength * p.X;
            u1prime.Y = u1primeLength * p.Y;

            u2prime.X = u2primeLength * c.X;
            u2prime.Y = u2primeLength * c.Y;

            // Change back to lab frame and calculate final velocities
            tangible1.velocity = u1prime + v2;
            tangible2.velocity = u2prime + v2;
        }
示例#9
0
        /// <summary>
        /// A pixel-by-pixel collision detector. Useing texture.GetData(rawDataA) might be a little bit sketchy...
        /// Code from http://gamedev.stackexchange.com/questions/15191/is-there-a-good-way-to-get-pixel-perfect-collision-detection-in-xna
        /// Implemented by Tristan
        /// </summary>
        /// <param name="target"></param>
        /// <returns></returns>
        private bool fineCheck(Tangible target)
        {
            Color[] rawDataA = new Color[this.width * this.height];
            this.texture.GetData(rawDataA);
            Color[] rawDataB = new Color[target.width * target.height];
            target.texture.GetData(rawDataB);


            Rectangle thisRect   = this.getHitBox().getArray();
            Rectangle targetRect = target.getHitBox().getArray();

            // Find the bounds of the rectangle intersection
            int top    = Math.Max(thisRect.Top, targetRect.Top);
            int bottom = Math.Min(thisRect.Bottom, targetRect.Bottom);

            int left  = Math.Max(thisRect.Left, targetRect.Left);
            int right = Math.Min(thisRect.Right, targetRect.Right);

            // for each pixel in the intersecting rectangle
            for (int y = top; y < bottom; ++y)
            {
                for (int x = left; x < right; ++x)
                {
                    Color colorA = rawDataA[(x - thisRect.Left) + (y - thisRect.Top) * thisRect.Width];
                    Color colorB = rawDataB[(x - targetRect.Left) + (y - targetRect.Top) * targetRect.Width];


                    // if both colors are not transparent
                    if (colorA.A != 0 && colorB.A != 0)
                    {
                        //GUI.hitDetected = true;
                        return(true);
                    }
                }
            }
            //GUI.hitDetected = false;
            return(false);
        }
示例#10
0
        /// <summary>
        /// Inserts object into quadtree. If the node exceeds capacity it will
        /// split and add all objects to their corresponging nodes
        /// </summary>
        /// <param name="pRect"></param>
        public void insert(Tangible tangible)
        {
            if (nodes[0] != null)               // if child nodes exist
            {
                int index = getIndex(tangible); // into which node should this go?

                if (index != -1)
                {
                    nodes[index].insert(tangible);

                    return;
                }
            }

            tangibles.Add(tangible);

            if (tangibles.Count > MAX_OBJECTS && level < MAX_LEVELS)               // if this node is fulll
            {
                if (nodes[0] == null)
                {
                    split();                     // create new child nodes if not done already
                }

                //cycle through all objects in this node
                for (int i = tangibles.Count - 1; i >= 0; --i)
                {
                    Tangible tang  = tangibles[i];
                    int      index = getIndex(tang);

                    if (index != -1)                      // into which node should this go?
                    {
                        nodes[index].insert(tang);        // place object in proper child node
                        tangibles.Remove(tang);           // and remove from this one
                    }
                }
            }
        }
示例#11
0
        public virtual void update(GameTime gameTime, MouseState mouseState, Vector2 mousePos, QuadTree quadTree)
        {
            /* Debugging */
            mouseScreen = mouseState;
            mouseWorld  = mousePos;

            if (playerShip.position.X <= 7999)
            {
                currentVelocity = playerShip.velocity;

                accel = (currentVelocity - lastVelocity) / (float)gameTime.ElapsedGameTime.TotalSeconds;

                totalTime += gameTime.ElapsedGameTime.TotalSeconds;
            }

            nearBy = quadTree.retrieve(playerShip);

            if (playerShip.collideTarget != null)
            {
                target = playerShip.collideTarget;
            }

            /* Debugging */
        }
示例#12
0
 /// <summary>
 /// The actions to take when a collision occurs.
 /// @Written by Tristan
 /// </summary>
 /// <param name="target"></param>
 /// <param name="gameTime"></param>
 public abstract void collide(Tangible target, GameTime gameTime);
示例#13
0
 private void setTarget(float dist, ref float shortestDist, Tangible target)
 {
     shortestDist  = dist;
     willCollide   = true;
     collideTarget = target;
 }
示例#14
0
        /// <summary>
        /// An attempt at collision prediction using an array of rays
        /// </summary>
        protected void checkForCollision2(QuadTree quadTree, GameTime gameTime)
        {
            willCollide   = false;
            collideTarget = null;

            if (moveThisUpdate.Length() == 0)
            {
                return;
            }

            Vector2 move = new Vector2();

            Vector2.Normalize(ref moveThisUpdate, out move);

            List <Tangible> possibleCollisions = quadTree.retrieve(this);

            Ray2 ray0 = new Ray2(hitBox.topLeft, move);
            Ray2 ray1 = new Ray2(hitBox.bottomLeft, move);
            Ray2 ray2 = new Ray2(hitBox.bottomRight, move);
            Ray2 ray3 = new Ray2(hitBox.topRight, move);
            Ray2 ray4 = new Ray2(hitBox.position, move);

            float dist0, dist1, dist2, dist3, dist4;
            float velLength    = move.Length();
            float shortestDist = velLength;


            foreach (Tangible target in possibleCollisions)
            {
                if (target == this)
                {
                    continue;
                }

                bool r0, r1, r2, r3, r4;

                //note: it is necessary that each of these functions run
                r0 = ray0.intersectsToRange(target.getHitBox());
                r1 = ray1.intersectsToRange(target.getHitBox());
                r2 = ray2.intersectsToRange(target.getHitBox());
                r3 = ray3.intersectsToRange(target.getHitBox());
                r4 = ray4.intersectsToRange(target.getHitBox());

                if (!r0 && !r1 && !r2 && !r3 && !r4)                 // If no rays intersect
                {
                    continue;
                }



                dist0 = ray0.getDistance();
                dist1 = ray1.getDistance();
                dist2 = ray2.getDistance();
                dist3 = ray3.getDistance();
                dist4 = ray4.getDistance();

                //possible.Clear();

                if (0 <= dist0 && dist0 <= shortestDist)
                {
                    setTarget(dist0, ref shortestDist, target);
                }
                //possible.Add(dist0);
                if (0 <= dist1 && dist1 <= shortestDist)
                {
                    setTarget(dist1, ref shortestDist, target);
                }
                //possible.Add(dist1);
                if (0 <= dist2 && dist2 <= shortestDist)
                {
                    setTarget(dist2, ref shortestDist, target);
                }
                //possible.Add(dist2);
                if (0 <= dist3 && dist3 <= shortestDist)
                {
                    setTarget(dist3, ref shortestDist, target);
                }
                //possible.Add(dist3);
                if (0 <= dist4 && dist4 <= shortestDist)
                {
                    setTarget(dist4, ref shortestDist, target);
                }
                //possible.Add(dist4);

                //float temp = possible.Min();
                //if (temp < shortestDist) {
                //	shortestDist = temp;
                //	willCollide = true;
                //	collideTarget = target;
                //}
            }

            if (willCollide)
            {
                Vector2.Normalize(ref velocity, out moveThisUpdate);
                moveThisUpdate = moveThisUpdate * shortestDist;
            }
        }