예제 #1
0
        public Vector2 calculateCollisions(Vector2 velocity, Vector2 finalPos, Player player)
        {
            Vector2[] bBox          = broadPhase(player.Position, finalPos, new Vector2(player.Height, player.Width));
            Vector2[] finalPosVerts = new Vector2[4];
            for ()
            {
                CollisionPoly playerPoly = new CollisionPoly();
            }
            int currentTile;

            for (int i = (int)Math.Floor(bBox[0].X); i < (int)Math.Ceiling(bBox[1].X); i++)
            {
                for (int j = (int)Math.Floor(bBox[0].Y); j < (int)Math.Ceiling(bBox[1].Y); j++)
                {
                    currentTile = collisionArray[i, j];
                    if (currentTile == 0)
                    {
                        return(velocity);
                    }
                    else if (currentTile == 1)
                    {
                        if (isCollision(playerPoly, new CollisionPoly(new Vector2[] { new Vector2(i * tileSize, j * tileSize), new Vector2((i + 1) * tileSize, j * tileSize), new Vector2(i * tileSize, (j + 1) * tileSize), new Vector2((i + 1) * tileSize, (j + 1) * tileSize) })))
                        {
                        }
                    }
                }
            }
        }
예제 #2
0
        public static Boolean isCollision(CollisionPoly poly1, CollisionPoly poly2)
        {
            Vector2        direction = new Vector2();
            List <Vector2> simplex   = new List <Vector2>();

            while (true)
            {
                switch (simplex.Count)
                {
                case 0:
                    //direction in the direction of separation
                    direction = Vector2.Subtract(poly1.center(), poly2.center());
                    break;

                case 1:
                    //direction opposite direction of separation
                    direction = Vector2.Multiply(direction, -1);
                    break;

                case 2:
                    //direction orthogonal to the line segment generated by first two points and also
                    direction = tripleCrossProd(Vector2.Subtract(simplex[1], simplex[0]), Vector2.Multiply(simplex[0], -1), Vector2.Subtract(simplex[1], simplex[0]));
                    break;

                case 3:

                    Vector2 side1 = Vector2.Subtract(simplex[1], simplex[2]);
                    Vector2 side2 = Vector2.Subtract(simplex[0], simplex[2]);
                    //vector orthogonal to the 2nd line segment generated (vertex 2 -> vertex 1)
                    Vector2 orthogonal1 = tripleCrossProd(side2, side1, side1);
                    //vector orthogonal to third line segment generated (vertex 3 -> vertex 1)
                    Vector2 orthogonal2 = tripleCrossProd(side1, side2, side2);
                    if (Vector2.Dot(orthogonal1, Vector2.Multiply(simplex[2], -1)) > 0)
                    {
                        direction = orthogonal1;
                        simplex.RemoveAt(0);
                    }
                    else if (Vector2.Dot(orthogonal2, Vector2.Multiply(simplex[2], -1)) > 0)
                    {
                        direction = orthogonal2;
                        simplex.RemoveAt(1);
                    }
                    else
                    {
                        return(true);
                    }
                    break;
                }
                Vector2 nextVert = Vector2.Subtract(poly1.supportFunction(direction), poly2.supportFunction(Vector2.Multiply(direction, -1)));
                if (Vector2.Dot(direction, nextVert) > 0)
                {
                    simplex.Add(nextVert);
                }
                else
                {
                    return(false);
                }
            }
        }
예제 #3
0
        public float[,] calculateTimes(int initialX, int initialY, int finalX, int finalY, CollisionPoly initialPos, Vector2 velocity, int unitConversion)
        {
            int currentTile;

            float[,] collisionTimes = new float[finalY - initialY, finalX - initialX];
            CollisionPoly tilePoly;

            for (int i = initialY; i < finalY; i++)
            {
                for (int j = initialX; j < finalX; j++)
                {
                    //System.Diagnostics.Debug.WriteLine(i + " , " + j);
                    currentTile = collisionArray[i, j];

                    switch (currentTile)
                    {
                    case 0:
                        tilePoly = null;
                        break;

                    case 1:
                        tilePoly = new CollisionPoly(new Vector2[] { new Vector2(j * tileSize, i * tileSize), new Vector2((j + 1) * tileSize, i * tileSize), new Vector2((j + 1) * tileSize, (i + 1) * tileSize), new Vector2(j * tileSize, (i + 1) * tileSize) });
                        break;

                    case 2:
                        tilePoly = new CollisionPoly(new Vector2[] { new Vector2((j + 1) * tileSize, i * tileSize), new Vector2((j + 1) * tileSize, (i + 1) * tileSize), new Vector2(j * tileSize, (i + 1) * tileSize) });
                        break;

                    case 3:
                        tilePoly = new CollisionPoly(new Vector2[] { new Vector2(j * tileSize, i * tileSize), new Vector2((j + 1) * tileSize, (i + 1) * tileSize), new Vector2(j * tileSize, (i + 1) * tileSize) });
                        break;

                    default:
                        tilePoly = new CollisionPoly(new Vector2[4]);
                        break;
                    }
                    if (tilePoly != null)
                    {
                        collisionTimes[i - initialY, j - initialX] = calculateIntersection(initialPos, tilePoly, velocity).Length() / (velocity.Length() * unitConversion);
                    }
                    else
                    {
                        collisionTimes[i - initialY, j - initialX] = float.MaxValue;
                    }
                }
            }
            return(collisionTimes);
        }
예제 #4
0
        public static Vector2 calculateIntersection(CollisionPoly poly1, CollisionPoly poly2, Vector2?velocity)
        {
            //Constructs basic simplex
            Vector2        direction = Vector2.Subtract(poly1.center(), poly2.center());
            List <Vector2> simplex   = new List <Vector2>();

            simplex.Add(Vector2.Subtract(poly1.supportFunction(direction), poly2.supportFunction(Vector2.Multiply(direction, -1))));
            direction = Vector2.Multiply(direction, -1);
            simplex.Add(Vector2.Subtract(poly1.supportFunction(direction), poly2.supportFunction(Vector2.Multiply(direction, -1))));
            direction = tripleCrossProd(Vector2.Subtract(simplex[1], simplex[0]), Vector2.Multiply(simplex[0], -1), Vector2.Subtract(simplex[1], simplex[0]));
            simplex.Add(Vector2.Subtract(poly1.supportFunction(direction), poly2.supportFunction(Vector2.Multiply(direction, -1))));

            //Calculates distance inside/outside object
            if (velocity.HasValue)
            {
                while (true)
                {
                    Edge    closestEdge = closestEdgeAlongVector(simplex, (Vector2)velocity);
                    Vector2 support     = Vector2.Subtract(poly1.supportFunction(closestEdge.normal), poly2.supportFunction(Vector2.Negate(closestEdge.normal)));
                    if (Math.Abs(Vector2.Dot(support, closestEdge.normal) - closestEdge.dist) <= 0.0001)
                    {
                        return(closestEdge.toOrigin);
                    }
                    else
                    {
                        simplex.Insert(closestEdge.index, support);
                    }
                }
            }
            else
            {
                while (true)
                {
                    Edge    closestEdge = closestEdgeToOrigin(simplex);
                    Vector2 support     = Vector2.Subtract(poly1.supportFunction(closestEdge.normal), poly2.supportFunction(Vector2.Negate(closestEdge.normal)));
                    if (Math.Abs(Vector2.Dot(support, closestEdge.normal) - closestEdge.dist) <= 0.00001)
                    {
                        return(Vector2.Multiply(closestEdge.normal, Vector2.Dot(support, closestEdge.normal)));
                    }
                    else
                    {
                        simplex.Insert(closestEdge.index, support);
                    }
                }
            }
        }
예제 #5
0
        public Vector2 calculateCollisions(Vector2 velocity, Vector2 initialPos, Player player, float elapsedTime, int unitConversion)
        {
            while (true)
            {
                Vector2[]     bBox            = broadPhase(initialPos, player.Position, new Vector2(player.Width, player.Height));
                CollisionPoly tilePoly        = new CollisionPoly(new Vector2[4]);
                CollisionPoly playerPoly      = new CollisionPoly(player.Verts);
                CollisionPoly initialPosVerts = new CollisionPoly(new Vector2[] {
                    initialPos,
                    new Vector2(initialPos.X + player.Width, initialPos.Y),
                    new Vector2(initialPos.X + player.Width, initialPos.Y + player.Height),
                    new Vector2(initialPos.X, initialPos.Y + player.Height)
                });
                float[,] collisionTimes = calculateTimes((int)Math.Floor(bBox[0].X), (int)Math.Floor(bBox[0].Y), (int)Math.Ceiling(bBox[1].X), (int)Math.Ceiling(bBox[1].Y), initialPosVerts, velocity, unitConversion);

                //System.Diagnostics.Debug.WriteLine("(" + bBox[0].X + "," + bBox[0].Y + ") ; (" + bBox[1].X + "," + bBox[1].Y + ")");
                //calculates index/indicies with the lowest collisionTime
                List <int[]> lowestIndices = new List <int[]>();
                float        currentLowest = float.MaxValue;
                for (int i = 0; i < collisionTimes.GetLength(0); i++)
                {
                    for (int j = 0; j < collisionTimes.GetLength(1); j++)
                    {
                        if (collisionTimes[i, j] < currentLowest)
                        {
                            currentLowest = collisionTimes[i, j];
                        }
                    }
                }
                for (int i = 0; i < collisionTimes.GetLength(0); i++)
                {
                    for (int j = 0; j < collisionTimes.GetLength(1); j++)
                    {
                        //fake epsilon lol
                        if (Math.Abs(collisionTimes[i, j] - currentLowest) < 0.00000000001)
                        {
                            lowestIndices.Add(new int[] { i + (int)Math.Floor(bBox[0].Y), j + (int)Math.Floor(bBox[0].X) });
                        }
                    }
                }
                //System.Diagnostics.Debug.WriteLine(currentLowest);

                if (currentLowest < (elapsedTime / 1000))
                {
                    int tile;
                    //System.Diagnostics.Debug.Write(currentLowest);
                    Vector2 collisionPos = Vector2.Subtract(initialPos, Vector2.Multiply(velocity, currentLowest));
                    //System.Diagnostics.Debug.WriteLine(collisionPos);
                    foreach (int[] index in lowestIndices)
                    {
                        int i = index[0];
                        int j = index[1];
                        tile = collisionArray[i, j];
                        System.Diagnostics.Debug.WriteLine(tile);
                        switch (tile)
                        {
                        case 1:
                            tilePoly = new CollisionPoly(new Vector2[] { new Vector2(i * tileSize, j * tileSize), new Vector2((i + 1) * tileSize, (j) * tileSize), new Vector2((i + 1) * tileSize, (j + 1) * tileSize), new Vector2((i) * tileSize, (j + 1) * tileSize) });
                            break;

                        case 2:
                            tilePoly = new CollisionPoly(new Vector2[] { new Vector2((i + 1) * tileSize, j * tileSize), new Vector2((i + 1) * tileSize, (j + 1) * tileSize), new Vector2(i * tileSize, (j + 1) * tileSize) });
                            break;

                        case 3:
                            tilePoly = new CollisionPoly(new Vector2[] { new Vector2(i * tileSize, j * tileSize), new Vector2((i + 1) * tileSize, (j + 1) * tileSize), new Vector2(i * tileSize, (j + 1) * tileSize) });
                            break;

                        default:
                            tilePoly = new CollisionPoly(new Vector2[4]);
                            break;
                        }
                        playerPoly = new CollisionPoly(player.Verts);
                        //System.Diagnostics.Debug.WriteLine(player.Position);
                        System.Diagnostics.Debug.Write(calculateIntersection(playerPoly, tilePoly, null));
                        System.Diagnostics.Debug.Write("calculating tile " + i + ", " + j + ")");
                        player.Position = Vector2.Subtract(player.Position, calculateIntersection(playerPoly, tilePoly, null));
                        //System.Diagnostics.Debug.WriteLine(player.Position);
                        velocity = Vector2.Divide(Vector2.Subtract(player.Position, collisionPos), elapsedTime / (1000) * unitConversion);
                        //System.Diagnostics.Debug.WriteLine(velocity);
                        //player.Position = Vector2.Add(player.Position, unitConversion * velocity * (elapsedTime - currentLowest) / (1000));
                        //System.Diagnostics.Debug.Write(player.Position);
                        initialPos = player.Position;
                    }
                    //System.Diagnostics.Debug.Write(isCollision(playerPoly, tilePoly));
                }
                else
                {
                    //System.Diagnostics.Debug.WriteLine(Vector2.Divide(Vector2.Subtract(player.Position, initialPos), elapsedTime / (1000)).X + "," + Vector2.Divide(Vector2.Subtract(player.Position, initialPos), elapsedTime / (1000)).Y);

                    return(velocity);
                }
            }



            /*
             * //int i = (int)Math.Floor(bBox[0].X);
             * //int j = (int)Math.Floor(bBox[0].Y);
             * Vector2[] bBox = broadPhase(initialPos, player.Position, new Vector2(player.Width, player.Height));
             * Vector2 finalPos = Vector2.Add(initialPos,velocity);
             * Vector2[] finalPosVerts = Enumerable.ToArray<Vector2>(from vert in player.Verts select Vector2.Add(vert, velocity));
             * CollisionPoly playerPoly = new CollisionPoly(finalPosVerts);
             * int currentTile;
             * int i = (int)Math.Floor(bBox[0].X);
             * int j = (int)Math.Floor(bBox[0].Y);
             *
             * while (i < (int)Math.Ceiling(bBox[1].X))
             * {
             *
             *  while (j < (int)Math.Ceiling(bBox[1].Y))
             *  {
             *      currentTile = collisionArray[j, i];
             *
             *      switch (currentTile)
             *      {
             *          case 0:
             *              break;
             *          case 1:
             *              CollisionPoly collisionBox = new CollisionPoly(new Vector2[] { new Vector2(i * tileSize, j * tileSize), new Vector2((i + 1) * tileSize, j * tileSize), new Vector2((i + 1) * tileSize, (j + 1) * tileSize), new Vector2(i * tileSize, (j + 1) * tileSize) });
             *              if (isCollision(playerPoly, collisionBox))
             *              {
             *                  float collisionTime = calculateIntersection(playerPoly, collisionBox, velocity).Length() / velocity.Length();
             *                  //player.Position = Vector2.Add(player.Position, Vector2.Multiply(velocity, collisionTime));
             *
             *                  System.Diagnostics.Debug.Write(calculateIntersection(playerPoly, collisionBox, null));
             *                  System.Diagnostics.Debug.Write("calculating tile " + i + ", " + j + ")");
             *                  finalPos = Vector2.Subtract(finalPos, calculateIntersection(playerPoly, collisionBox, null));
             *                  finalPosVerts = Enumerable.ToArray<Vector2>(from vert in finalPosVerts select Vector2.Subtract(finalPos, calculateIntersection(playerPoly, collisionBox, null)));
             *                  playerPoly.vert = finalPosVerts;
             *                  velocity = Vector2.Subtract(finalPos, player.Position);
             *                  bBox = broadPhase(player.Position, finalPos, new Vector2(player.Height, player.Width));
             *                  playerPoly = new CollisionPoly(player.Verts);
             *                  i = (int)Math.Floor(bBox[0].X);
             *                  j = (int)Math.Floor(bBox[0].Y);
             *
             *              }
             *              break;
             *          case 2:
             *              CollisionPoly collisionTriangleL = new CollisionPoly(new Vector2[] { new Vector2((i + 1) * tileSize, j * tileSize), new Vector2((i + 1) * tileSize, (j + 1) * tileSize), new Vector2(i * tileSize, (j + 1) * tileSize) });
             *              if (isCollision(playerPoly, collisionTriangleL))
             *              {
             *                  float collisionTime = calculateIntersection(playerPoly, collisionTriangleL, velocity).Length() / velocity.Length();
             *                  player.Position = Vector2.Subtract(player.Position, Vector2.Multiply(velocity, collisionTime));
             *
             *                  //System.Diagnostics.Debug.Write(calculateIntersection(playerPoly, collisionBox, null));
             *                  finalPos = Vector2.Subtract(finalPos, calculateIntersection(playerPoly, collisionTriangleL, null));
             *                  finalPosVerts = Enumerable.ToArray<Vector2>(from vert in finalPosVerts select Vector2.Subtract(finalPos, calculateIntersection(playerPoly, collisionTriangleL, null)));
             *                  playerPoly.vert = finalPosVerts;
             *                  velocity = Vector2.Subtract(finalPos, player.Position);
             *                  bBox = broadPhase(player.Position, finalPos, new Vector2(player.Height, player.Width));
             *                  playerPoly = new CollisionPoly(player.Verts);
             *                  i = (int)Math.Floor(bBox[0].X);
             *                  j = (int)Math.Floor(bBox[0].Y);
             *              }
             *              break;
             *          case 3:
             *              CollisionPoly collisionTriangleR = new CollisionPoly(new Vector2[] { new Vector2(i * tileSize, j * tileSize), new Vector2((i + 1) * tileSize, (j + 1) * tileSize), new Vector2(i * tileSize, (j + 1) * tileSize) });
             *              if (isCollision(playerPoly, collisionTriangleR))
             *              {
             *                  float collisionTime = calculateIntersection(playerPoly, collisionTriangleR, velocity).Length() / velocity.Length();
             *                  player.Position = Vector2.Subtract(player.Position, Vector2.Multiply(velocity, collisionTime));
             *
             *                  //System.Diagnostics.Debug.Write(calculateIntersection(playerPoly, collisionBox, null));
             *                  finalPos = Vector2.Subtract(finalPos, calculateIntersection(playerPoly, collisionTriangleR, null));
             *                  finalPosVerts = Enumerable.ToArray<Vector2>(from vert in finalPosVerts select Vector2.Subtract(finalPos, calculateIntersection(playerPoly, collisionTriangleR, null)));
             *                  playerPoly.vert = finalPosVerts;
             *                  velocity = Vector2.Subtract(finalPos, player.Position);
             *                  bBox = broadPhase(player.Position, finalPos, new Vector2(player.Height, player.Width));
             *                  playerPoly = new CollisionPoly(player.Verts);
             *                  i = (int)Math.Floor(bBox[0].X);
             *                  j = (int)Math.Floor(bBox[0].Y);
             *              }
             *              break;
             *      }
             *      j++;
             *  }
             *  i++;
             *  j = (int)Math.Floor(bBox[0].Y);
             * }
             * player.Position = finalPos;
             * return velocity;
             */
        }