Inheritance: ICollidable
Exemplo n.º 1
0
 public void Add(CollisionRect[] walls, byte mi, int x, int y)
 {
     Walls[x, y]            = new CollisionRect[walls.Length];
     WallInformation[x, y] |= mi;
     if (x > 0 && y > 0 && !CanMoveTo(new Point(x, y), Direction.XNZN))
     {
         WallInformation[x - 1, y - 1] |= Direction.XPZP;
     }
     if (x < numCells.X - 1 && y > 0 && !CanMoveTo(new Point(x, y), Direction.XPZN))
     {
         WallInformation[x + 1, y - 1] |= Direction.XNZP;
     }
     if (x > 0 && y < numCells.Y - 1 && !CanMoveTo(new Point(x, y), Direction.XNZP))
     {
         WallInformation[x - 1, y + 1] |= Direction.XPZN;
     }
     if (x < numCells.X - 1 && y < numCells.Y - 1 && !CanMoveTo(new Point(x, y), Direction.XPZP))
     {
         WallInformation[x + 1, y + 1] |= Direction.XNZN;
     }
     Array.Copy(walls, Walls[x, y], Walls[x, y].Length);
 }
Exemplo n.º 2
0
        public CollisionGrid(int w, int h)
        {
            cellSize = RTSConstants.CGRID_SIZE;
            numCells = new Point(w, h);
            size     = new Vector2(w, h) * cellSize;

            EDynamic = new List <RTSUnit> [numCells.X, numCells.Y];
            EStatic  = new RTSBuilding[numCells.X, numCells.Y];
            for (int x = 0; x < numCells.X; x++)
            {
                for (int y = 0; y < numCells.Y; y++)
                {
                    EDynamic[x, y] = new List <RTSUnit>();
                }
            }
            ActiveGrids     = new List <Point>();
            Fog             = new uint[numCells.X, numCells.Y];
            Collision       = new bool[numCells.X, numCells.Y];
            Walls           = new CollisionRect[numCells.X, numCells.Y][];
            WallInformation = new byte[numCells.X, numCells.Y];
            Array.Clear(WallInformation, 0, WallInformation.Length);
            heights = new HeightTile[numCells.X, numCells.Y];
        }
Exemplo n.º 3
0
        private static void HandleCollision(CollisionRect rect1, CollisionRect rect2)
        {
            if(rect1.IsStatic && rect2.IsStatic)
                return;

            // bottom1 means the bottom Y coordinate of rect1
            // left2 means the left X coordinate of rect2
            float bottom1 = rect1.Center.Y - rect1.Depth / 2;
            float bottom2 = rect2.Center.Y - rect2.Depth / 2;
            float top1 = rect1.Center.Y + rect1.Depth / 2;
            float top2 = rect2.Center.Y + rect2.Depth / 2;
            float left1 = rect1.Center.X - rect1.Width / 2;
            float left2 = rect2.Center.X - rect2.Width / 2;
            float right1 = rect1.Center.X + rect1.Width / 2;
            float right2 = rect2.Center.X + rect2.Width / 2;

            // If two rectangles collide
            if(top1 > bottom2 && top2 > bottom1 && left1 < right2 && left2 < right1) {
                // If two rectangle centers completely overlap,
                // slightly move one of the object's center so they don't completely overlap
                Vector2 d = rect2.Center - rect1.Center;
                if(d.Length() == 0) {
                    d.X = r.Next(-200, 201);
                    d.Y = r.Next(-200, 201);
                    if(d != Vector2.Zero) {
                        d.Normalize();
                        d *= 0.1f;
                    }
                    if(rect1.IsStatic)
                        rect2.Center += d;
                    else
                        rect1.Center += d;
                    HandleCollision(rect1, rect2);
                }

                Vector2 pushAmount = new Vector2();
                // If rect2 is on the right of rect1
                if(d.X > 0) {
                    // If rect2 is below rect1
                    if(d.Y < 0) {
                        if(right1 - left2 > top2 - bottom1)
                            pushAmount.Y = top2 - bottom1 + OFFSET; // rect1 pushed up
                        else
                            pushAmount.X = left2 - right1 - OFFSET; // rect1 pushed left
                    }
                    // If rect2 is above rect1
                    else {
                        if(right1 - left2 > top1 - bottom2)
                            pushAmount.Y = bottom2 - top1 - OFFSET; // rect1 pushed down
                        else
                            pushAmount.X = left2 - right1 - OFFSET; // rect1 pushed left
                    }
                }
                // If rect2 is on the left of rect1
                else {
                    // If rect2 is below rect1
                    if(d.Y < 0) {
                        if(right2 - left1 > top2 - bottom1)
                            pushAmount.Y = top2 - bottom1 + OFFSET; // rect1 pushed up
                        else
                            pushAmount.X = right2 - left1 + OFFSET; // rect1 pushed right
                    }
                    // If rect2 is above rect1
                    else {
                        if(right2 - left1 > top1 - bottom2)
                            pushAmount.Y = bottom2 - top1 - OFFSET; // rect1 pushed down
                        else
                            pushAmount.X = right2 - left1 + OFFSET; // rect1 pushed right
                    }
                }
                // Push apart rectangles that are non-static
                if(rect1.IsStatic)
                    rect2.Center -= pushAmount;
                else if(rect2.IsStatic)
                    rect1.Center += pushAmount;
                else {
                    rect1.Center += pushAmount / 2;
                    rect2.Center -= pushAmount / 2;
                }
            }
        }
Exemplo n.º 4
0
        private static void HandleCollision(CollisionCircle circle, CollisionRect rect)
        {
            if(circle.IsStatic && rect.IsStatic)
                return;

            // Reference: stackoverflow.com/questions/401847/circle-rectangle-collision-detection-intersection/402010#402010
            Vector2 d = circle.Center - rect.Center;
            d = new Vector2(Math.Abs(d.X), Math.Abs(d.Y));
            Vector2 cd = new Vector2(d.X - rect.Width * 0.5f, d.Y - rect.Depth * 0.5f);
            float cornerDistSqr = cd.LengthSquared();

            // If circle and rectangle collide
            if(d.X <= rect.Width / 2 + circle.Radius && d.Y <= rect.Depth / 2 + circle.Radius
                || cornerDistSqr <= circle.Radius * circle.Radius) {
                // If circle and rectangle centers completely overlap,
                // slightly move one of the object's center so they don't completely overlap
                if(d.Length() == 0) {
                    d.X = r.Next(-200, 201);
                    d.Y = r.Next(-200, 201);
                    if(d != Vector2.Zero) {
                        d.Normalize();
                        d *= 0.1f;
                    }
                    if(circle.IsStatic)
                        rect.Center += d;
                    else
                        circle.Center += d;
                    HandleCollision(circle, rect);
                }

                // Create a collision boundary around the rectangle, in which collision occurs
                float top = rect.Center.Y + rect.Depth / 2 + circle.Radius;
                float bottom = rect.Center.Y - rect.Depth / 2 - circle.Radius;
                float left = rect.Center.X - rect.Width / 2 - circle.Radius;
                float right = rect.Center.X + rect.Width / 2 + circle.Radius;
                float distToTop = Math.Abs(circle.Center.Y - top);
                float distToBottom = Math.Abs(circle.Center.Y - bottom);
                float distToLeft = Math.Abs(circle.Center.X - left);
                float distToRight = Math.Abs(circle.Center.X - right);

                // Choose the closest distance to the collision boundary as the pushing direction
                Vector2 pushAmount = new Vector2(); // How much should be pushed relative to circle
                float min = Math.Min(Math.Min(Math.Min(distToTop, distToBottom), distToLeft), distToRight);
                pushAmount.Y += min == distToTop ? distToTop + OFFSET : 0;
                pushAmount.Y += min == distToBottom ? -distToBottom - OFFSET : 0;
                pushAmount.X += min == distToLeft ? -distToLeft - OFFSET : 0;
                pushAmount.X += min == distToRight ? distToRight + OFFSET : 0;

                // Only move the non-static object
                if(rect.IsStatic)
                    circle.Center += pushAmount;
                else if(circle.IsStatic)
                    rect.Center -= pushAmount;
                else {
                    circle.Center += pushAmount / 2;
                    rect.Center -= pushAmount / 2;
                }

            }
        }
Exemplo n.º 5
0
        private static void HandleCollision(CollisionRect rect1, CollisionRect rect2)
        {
            if (rect1.IsStatic && rect2.IsStatic)
            {
                return;
            }

            // bottom1 means the bottom Y coordinate of rect1
            // left2 means the left X coordinate of rect2
            float bottom1 = rect1.Center.Y - rect1.Depth / 2;
            float bottom2 = rect2.Center.Y - rect2.Depth / 2;
            float top1    = rect1.Center.Y + rect1.Depth / 2;
            float top2    = rect2.Center.Y + rect2.Depth / 2;
            float left1   = rect1.Center.X - rect1.Width / 2;
            float left2   = rect2.Center.X - rect2.Width / 2;
            float right1  = rect1.Center.X + rect1.Width / 2;
            float right2  = rect2.Center.X + rect2.Width / 2;

            // If two rectangles collide
            if (top1 > bottom2 && top2 > bottom1 && left1 < right2 && left2 < right1)
            {
                // If two rectangle centers completely overlap,
                // slightly move one of the object's center so they don't completely overlap
                Vector2 d = rect2.Center - rect1.Center;
                if (d.Length() == 0)
                {
                    d.X = r.Next(-200, 201);
                    d.Y = r.Next(-200, 201);
                    if (d != Vector2.Zero)
                    {
                        d.Normalize();
                        d *= 0.1f;
                    }
                    if (rect1.IsStatic)
                    {
                        rect2.Center += d;
                    }
                    else
                    {
                        rect1.Center += d;
                    }
                    HandleCollision(rect1, rect2);
                }

                Vector2 pushAmount = new Vector2();
                // If rect2 is on the right of rect1
                if (d.X > 0)
                {
                    // If rect2 is below rect1
                    if (d.Y < 0)
                    {
                        if (right1 - left2 > top2 - bottom1)
                        {
                            pushAmount.Y = top2 - bottom1 + OFFSET; // rect1 pushed up
                        }
                        else
                        {
                            pushAmount.X = left2 - right1 - OFFSET; // rect1 pushed left
                        }
                    }
                    // If rect2 is above rect1
                    else
                    {
                        if (right1 - left2 > top1 - bottom2)
                        {
                            pushAmount.Y = bottom2 - top1 - OFFSET; // rect1 pushed down
                        }
                        else
                        {
                            pushAmount.X = left2 - right1 - OFFSET; // rect1 pushed left
                        }
                    }
                }
                // If rect2 is on the left of rect1
                else
                {
                    // If rect2 is below rect1
                    if (d.Y < 0)
                    {
                        if (right2 - left1 > top2 - bottom1)
                        {
                            pushAmount.Y = top2 - bottom1 + OFFSET; // rect1 pushed up
                        }
                        else
                        {
                            pushAmount.X = right2 - left1 + OFFSET; // rect1 pushed right
                        }
                    }
                    // If rect2 is above rect1
                    else
                    {
                        if (right2 - left1 > top1 - bottom2)
                        {
                            pushAmount.Y = bottom2 - top1 - OFFSET; // rect1 pushed down
                        }
                        else
                        {
                            pushAmount.X = right2 - left1 + OFFSET; // rect1 pushed right
                        }
                    }
                }
                // Push apart rectangles that are non-static
                if (rect1.IsStatic)
                {
                    rect2.Center -= pushAmount;
                }
                else if (rect2.IsStatic)
                {
                    rect1.Center += pushAmount;
                }
                else
                {
                    rect1.Center += pushAmount / 2;
                    rect2.Center -= pushAmount / 2;
                }
            }
        }
Exemplo n.º 6
0
        private static void HandleCollision(CollisionCircle circle, CollisionRect rect)
        {
            if (circle.IsStatic && rect.IsStatic)
            {
                return;
            }

            // Reference: stackoverflow.com/questions/401847/circle-rectangle-collision-detection-intersection/402010#402010
            Vector2 d = circle.Center - rect.Center;

            d = new Vector2(Math.Abs(d.X), Math.Abs(d.Y));
            Vector2 cd            = new Vector2(d.X - rect.Width * 0.5f, d.Y - rect.Depth * 0.5f);
            float   cornerDistSqr = cd.LengthSquared();

            // If circle and rectangle collide
            if (d.X <= rect.Width / 2 + circle.Radius && d.Y <= rect.Depth / 2 + circle.Radius ||
                cornerDistSqr <= circle.Radius * circle.Radius)
            {
                // If circle and rectangle centers completely overlap,
                // slightly move one of the object's center so they don't completely overlap
                if (d.Length() == 0)
                {
                    d.X = r.Next(-200, 201);
                    d.Y = r.Next(-200, 201);
                    if (d != Vector2.Zero)
                    {
                        d.Normalize();
                        d *= 0.1f;
                    }
                    if (circle.IsStatic)
                    {
                        rect.Center += d;
                    }
                    else
                    {
                        circle.Center += d;
                    }
                    HandleCollision(circle, rect);
                }

                // Create a collision boundary around the rectangle, in which collision occurs
                float top          = rect.Center.Y + rect.Depth / 2 + circle.Radius;
                float bottom       = rect.Center.Y - rect.Depth / 2 - circle.Radius;
                float left         = rect.Center.X - rect.Width / 2 - circle.Radius;
                float right        = rect.Center.X + rect.Width / 2 + circle.Radius;
                float distToTop    = Math.Abs(circle.Center.Y - top);
                float distToBottom = Math.Abs(circle.Center.Y - bottom);
                float distToLeft   = Math.Abs(circle.Center.X - left);
                float distToRight  = Math.Abs(circle.Center.X - right);

                // Choose the closest distance to the collision boundary as the pushing direction
                Vector2 pushAmount = new Vector2(); // How much should be pushed relative to circle
                float   min        = Math.Min(Math.Min(Math.Min(distToTop, distToBottom), distToLeft), distToRight);
                pushAmount.Y += min == distToTop ? distToTop + OFFSET : 0;
                pushAmount.Y += min == distToBottom ? -distToBottom - OFFSET : 0;
                pushAmount.X += min == distToLeft ? -distToLeft - OFFSET : 0;
                pushAmount.X += min == distToRight ? distToRight + OFFSET : 0;

                // Only move the non-static object
                if (rect.IsStatic)
                {
                    circle.Center += pushAmount;
                }
                else if (circle.IsStatic)
                {
                    rect.Center -= pushAmount;
                }
                else
                {
                    circle.Center += pushAmount / 2;
                    rect.Center   -= pushAmount / 2;
                }
            }
        }
Exemplo n.º 7
0
        public void AddWalls(int x, int y, byte directions)
        {
            byte mi = 0x00;

            CollisionRect[] pWalls = new CollisionRect[4];
            int             c      = 0;

            if ((directions & Direction.XN) != 0 && pWalls[0] == null)
            {
                mi       |= Direction.XN | Direction.XNZN | Direction.XNZP;
                pWalls[0] = new CollisionRect(
                    RTSConstants.CGRID_WALL_SIZE,
                    RTSConstants.CGRID_SIZE,
                    new Vector2(
                        x * RTSConstants.CGRID_SIZE + RTSConstants.CGRID_WALL_SIZE * 0.5f,
                        y * RTSConstants.CGRID_SIZE + RTSConstants.CGRID_SIZE * 0.5f
                        ),
                    true
                    );
                c++;
            }
            if ((directions & Direction.XP) != 0 && pWalls[1] == null)
            {
                mi       |= Direction.XP | Direction.XPZN | Direction.XPZP;
                pWalls[1] = new CollisionRect(
                    RTSConstants.CGRID_WALL_SIZE,
                    RTSConstants.CGRID_SIZE,
                    new Vector2(
                        (x + 1) * RTSConstants.CGRID_SIZE - RTSConstants.CGRID_WALL_SIZE * 0.5f,
                        y * RTSConstants.CGRID_SIZE + RTSConstants.CGRID_SIZE * 0.5f
                        ),
                    true
                    );
                c++;
            }
            if ((directions & Direction.ZN) != 0 && pWalls[2] == null)
            {
                mi       |= Direction.ZN | Direction.XNZN | Direction.XPZN;
                pWalls[2] = new CollisionRect(
                    RTSConstants.CGRID_SIZE,
                    RTSConstants.CGRID_WALL_SIZE,
                    new Vector2(
                        x * RTSConstants.CGRID_SIZE + RTSConstants.CGRID_SIZE * 0.5f,
                        y * RTSConstants.CGRID_SIZE + RTSConstants.CGRID_WALL_SIZE * 0.5f
                        ),
                    true
                    );
                c++;
            }
            if ((directions & Direction.ZP) != 0 && pWalls[3] == null)
            {
                mi       |= Direction.ZP | Direction.XNZP | Direction.XPZP;
                pWalls[3] = new CollisionRect(
                    RTSConstants.CGRID_SIZE,
                    RTSConstants.CGRID_WALL_SIZE,
                    new Vector2(
                        x * RTSConstants.CGRID_SIZE + RTSConstants.CGRID_SIZE * 0.5f,
                        (y + 1) * RTSConstants.CGRID_SIZE - RTSConstants.CGRID_WALL_SIZE * 0.5f
                        ),
                    true
                    );
                c++;
            }
            CollisionRect[] walls = new CollisionRect[c];
            c = 0;
            if (pWalls[0] != null)
            {
                walls[c++] = pWalls[0];
            }
            if (pWalls[1] != null)
            {
                walls[c++] = pWalls[1];
            }
            if (pWalls[2] != null)
            {
                walls[c++] = pWalls[2];
            }
            if (pWalls[3] != null)
            {
                walls[c++] = pWalls[3];
            }
            Add(walls, mi, x, y);
        }