Exemple #1
0
        /// <summary>
        /// Goes through the current level file and loads all of the collision objects, so that they can be returned and added to the list of active GameObjects. Note that all collision object must be on a layer
        /// named "collision" that is set to be an object layer, and not a normal tile layer (normal tiles don't have a position member).
        /// </summary>
        /// <returns></returns>
        public List <GameObject> getCollisionObjects()
        {
            List <GameObject> collisionObjects = new List <GameObject>();

            TiledMapObjectLayer objectLayer = currentMap.GetLayer <TiledMapObjectLayer>("collision"); //Get the collision layer to start with

            TiledMapLayer debugLayer = currentMap.GetLayer <TiledMapLayer>("collision");

            Console.WriteLine(debugLayer.ToString());

            GameObject tempObject; //Make an object reference to hold objects we'll construct later, and then add properties to

            try
            {
                foreach (TiledMapPolygonObject tile in objectLayer.Objects) //Go through all of the tiles in the map
                {
                    tempObject = new GameObject();
                    tempObject.transform.SetPosition(tile.Position); //Set the collision object's position

                    //Get the vertices of this collision object
                    Vector2[] vertices;
                    vertices = new Vector2[tile.Points.Count()]; //Set the vertices to be the same count as that of the tile object's
                    for (int i = 0; i < tile.Points.Count(); i++)
                    {
                        vertices[i] = new Vector2(tile.Points[i].X, tile.Points[i].Y); //The Points are already the displacement from an origin, so this will match the Hitbox constructor later
                    }
                    Hitbox hitbox = new Hitbox(vertices, tempObject);                  //Create a hitbox for this tile
                    tempObject.AddComponent(hitbox);                                   //Give the tile the hitbox
                    tempObject.AddComponent(new CollisionComponent(null, hitbox));     //Add collision to the tile with the given hitbox and no physics component

                    collisionObjects.Add(tempObject);                                  //Now that the tile object has collision and a hitbox mask, add it to the list of GameObjects that we want to return
                }
            }

            catch (Exception e) //In case the collision layer is null
            {
                Console.WriteLine("Error encountered in getCollisionObjects(): " + e.Message);
            }

            //DEBUG Let's make sure that it's correctly adding the tile objects
            Console.WriteLine("Number of collision objects = " + collisionObjects.Count);

            return(collisionObjects);
        }
 public CollisionComponent(GameObject parent, bool isSolid = false) : base()
 {
     this.physics = parent.GetComponent <PhysicsComponent>(); this.hitbox = parent.GetComponent <Hitbox>(); this.isSolid = isSolid; gameObject = parent; collidingObjects = new List <GameObject>();
 }                                                                                                                                                                                                                                                                            //This constructor should get relevant component references from its parent
 public CollisionComponent(PhysicsComponent physics, Hitbox hitbox) : base()
 {
     this.physics = physics; this.isSolid = true; this.hitbox = hitbox; collidingObjects = new List <GameObject>();
 }
        //***********************Collision checks************************

        //Checks for collision between hitbox1 and hitbox2, and returns the result. This will use the Separating Axis Theorem (SAT) to check for collision. Basically, we will take the normal to each edge
        //(Pair of vertices), and then project all the vertices of both shapes onto each normal. We can then check if there is overlap. If a single projection does not overlap, we know that the hitboxes
        //are not colliding.
        static bool checkCollision(Hitbox hitbox1, Hitbox hitbox2)
        {
            //DEBUG Finish implementing SAT
            float   minProjection1, minProjection2, maxProjection1, maxProjection2, tempScalar; //Used for checking overlap. Taking projection involves taking dot product between vectors, which will return a scalar. These will hold the 4 relevant scalars.
            Vector2 normalVector;                                                               //Vector normal to the edge currently being checked
            Vector2 point2;

            //Go through each hitbox
            for (int i = 0; i < hitbox1.vertices.Length; i++) //Project onto all of the sides in the first polygon
            {
                //Find the normal vector to the current edge being checked. All vectors will be relative to the current vertex being checked (Basically, it's like the origin)
                if (i == hitbox1.vertices.Length - 1) //If we're at the end of the vertices array, loop back around for the last pair
                {
                    point2 = hitbox1.vertices[0];
                }
                else
                {
                    point2 = hitbox1.vertices[i + 1];
                }

                normalVector = takeNormal(hitbox1.vertices[i], point2);

                //Now, project all of the points onto the normal
                minProjection1 = minProjection2 = 0xFFFFFFFF; //Set min to big number, max to small number, since (as far as I know), we can't operate on a spliced list, so optimization isn't really an option.
                maxProjection1 = maxProjection2 = -0xFFFFFFFF;

                foreach (Vector2 vertex in hitbox1.vertices)                              //Project for hitbox1/shape1
                {
                    tempScalar = Vector2.Dot(vertex - hitbox1.vertices[i], normalVector); //Taking dot product between vertex and normalVector should return projection length from origin (hitbox.vertices[i], for this)
                    if (tempScalar < minProjection1)                                      //If the scalar computed is the smallest one yet, set it to be the min of the projections for hitbox1
                    {
                        minProjection1 = tempScalar;
                    }
                    if (tempScalar > maxProjection1) //If the scalar computed is the greatest one yet, set it to be the max of the projections for hitbox1
                    {
                        maxProjection1 = tempScalar;
                    }
                }

                foreach (Vector2 vertex in hitbox2.vertices)                              //Project for hitbox2/shape2
                {
                    tempScalar = Vector2.Dot(vertex - hitbox1.vertices[i], normalVector); //Taking dot product between vertex and normalVector should return projection length from origin (hitbox.vertices[i], for this)
                    if (tempScalar < minProjection2)                                      //If the scalar computed is the smallest one yet, set it to be the min of the projections for hitbox2
                    {
                        minProjection2 = tempScalar;
                    }
                    if (tempScalar > maxProjection2) //If the scalar computed is the greatest one yet, set it to be the max of the projections for hitbox2
                    {
                        maxProjection2 = tempScalar;
                    }
                }

                //Finally, let's make sure the projections overlap. If they don't, we can bail out of the whole function, because these hitboxes don't collide.
                //Using negation of logic to check for collision (using DeMorgan's law) to find when it should be false
                if ((minProjection1 >= maxProjection2 || minProjection2 >= maxProjection1) && (minProjection2 >= maxProjection1 || minProjection1 >= maxProjection2))
                {
                    return(false);
                }
            }

            for (int i = 0; i < hitbox2.vertices.Length; i++) //Project onto all of the sides in the second polygon. Copy and pasted from above code
            {
                //Find the normal vector to the current edge being checked. All vectors will be relative to the current vertex being checked (Basically, it's like the origin)
                if (i == hitbox2.vertices.Length - 1) //If we're at the end of the vertices array, loop back around for the last pair
                {
                    point2 = hitbox2.vertices[0];
                }
                else
                {
                    point2 = hitbox2.vertices[i + 1];
                }

                normalVector = takeNormal(hitbox2.vertices[i], point2);

                //Now, project all of the points onto the normal
                minProjection1 = minProjection2 = 0xFFFFFFFF; //Set min to big number, max to small number, since (as far as I know), we can't operate on a spliced list, so optimization isn't really an option.
                maxProjection1 = maxProjection2 = -0xFFFFFFFF;

                foreach (Vector2 vertex in hitbox1.vertices)                              //Project for hitbox1/shape1
                {
                    tempScalar = Vector2.Dot(vertex - hitbox2.vertices[i], normalVector); //Taking dot product between vertex and normalVector should return projection length from origin (hitbox.vertices[i], for this)
                    if (tempScalar < minProjection1)                                      //If the scalar computed is the smallest one yet, set it to be the min of the projections for hitbox1
                    {
                        minProjection1 = tempScalar;
                    }
                    if (tempScalar > maxProjection1) //If the scalar computed is the greatest one yet, set it to be the max of the projections for hitbox1
                    {
                        maxProjection1 = tempScalar;
                    }
                }

                foreach (Vector2 vertex in hitbox2.vertices)                              //Project for hitbox2/shape2
                {
                    tempScalar = Vector2.Dot(vertex - hitbox2.vertices[i], normalVector); //Taking dot product between vertex and normalVector should return projection length from origin (hitbox.vertices[i], for this)
                    if (tempScalar < minProjection2)                                      //If the scalar computed is the smallest one yet, set it to be the min of the projections for hitbox2
                    {
                        minProjection2 = tempScalar;
                    }
                    if (tempScalar > maxProjection2) //If the scalar computed is the greatest one yet, set it to be the max of the projections for hitbox2
                    {
                        maxProjection2 = tempScalar;
                    }
                }

                //Finally, let's make sure the projections overlap. If they don't, we can bail out of the whole function, because these hitboxes don't collide.
                //Using negation of logic to check for collision (using DeMorgan's law) to find when it should be false
                if ((minProjection1 >= maxProjection2 || minProjection2 >= maxProjection1) && (minProjection2 >= maxProjection1 || minProjection1 >= maxProjection2))
                {
                    return(false);
                }
            }

            return(true);
        }