public static bool CheckAABB(Box b1, Box b2, ref float moveX, ref float moveY)
        {
            moveX = 0.0f;
            moveY = 0.0f;

            float l = b2.x - (b1.x + b1.w);
            float r = (b2.x + b2.w) - b1.x;
            float t = b2.y - (b1.y + b1.h);
            float b = (b2.y + b2.h) - b1.y;

            if (l > 0 || r < 0 || t > 0 || b < 0)
                return false;

            // lấy khoảng bị va chạm ngắn nhất, để cộng cho nhanh
            moveX = Math.Abs(l) < r ? l : r;
            moveY = Math.Abs(t) < b ? t : b;

            // lấy chiều có khoảng va chạm ngắn, nhất để cộng cho lẹ
            if (Math.Abs(moveX) < Math.Abs(moveY))
            {
                moveY = 0.0f;
            }
            else
            {
                moveX = 0.0f;
            }

            return true;
        }
        public static Box GetBroadPhaseBox(Box b)
        {
            Box BroadPhaseBox = new Box(0.0f, 0.0f, 0.0f, 0.0f);

            BroadPhaseBox.x = b.vx > 0 ? b.x : b.x + b.vx;
            BroadPhaseBox.y = b.vy > 0 ? b.y : b.y + b.vy;
            BroadPhaseBox.w = b.vx > 0 ? b.w + b.vx : b.w - b.vx;
            BroadPhaseBox.h = b.vy > 0 ? b.h + b.vy : b.h - b.vy;

            return BroadPhaseBox;
        }
 // chuyển từ Box sang Broadphase dùng để khoanh vùng đối tượng
 public Box BoxToBroadPhase(Box b)
 {
     return SweptAABB.GetBroadPhaseBox(b);
 }
        public static float Swept_AABB(Box b1, Box b2, ref float normalx, ref float normaly)
        {
            float xInvEntry, yInvEntry;
            float xInvExit, yInvExit;

            // find the distance between the objects on the near and far sides for both x and y
            if (b1.vx > 0.0f)
            {
                xInvEntry = b2.x - (b1.x + b1.w);
                xInvExit = (b2.x + b2.w) - b1.x;
            }
            else
            {
                xInvEntry = (b2.x + b2.w) - b1.x;
                xInvExit = b2.x - (b1.x + b1.w);
            }

            if (b1.vy > 0.0f)
            {
                yInvEntry = b2.y - (b1.y + b1.h);
                yInvExit = (b2.y + b2.h) - b1.y;
            }
            else
            {
                yInvEntry = (b2.y + b2.h) - b1.y;
                yInvExit = b2.y - (b1.y + b1.h);
            }

            // find time of collision and time of leaving for each axis (if statement is to prevent divide by zero)
            float xEntry, yEntry;
            float xExit, yExit;

            if (b1.vx == 0.0f)
            {
                xEntry = -float.PositiveInfinity;
                xExit = float.PositiveInfinity;
            }
            else
            {
                xEntry = xInvEntry / b1.vx;
                xExit = xInvExit / b1.vx;
            }

            if (b1.vy == 0.0f)
            {
                yEntry = -float.PositiveInfinity;
                yExit = float.PositiveInfinity;
            }
            else
            {
                yEntry = yInvEntry / b1.vy;
                yExit = yInvExit / b1.vy;
            }

            // find the earliest/latest times of collision
            float entryTime = Math.Max(xEntry, yEntry);
            float exitTime = Math.Min(xExit, yExit);

            // if there was no collision
            if (entryTime > exitTime || xEntry < 0.0f && yEntry < 0.0f || xEntry > 1.0f || yEntry > 1.0f)
            {
                normalx = 0.0f;
                normaly = 0.0f;
                return 1.0f;
            }
            else // if there was a collision
            {
                // calculate normal of collided surface
                if (xEntry > yEntry && (b1.y + b1.h + 1.0f != b2.y ))
                {
                    if (xInvEntry < 0.0f)
                    {
                        normalx = 1.0f;
                        normaly = 0.0f;
                    }
                    else
                    {
                        normalx = -1.0f;
                        normaly = 0.0f;
                    }
                }
                else
                {
                    if (yInvEntry < 0.0f)
                    {
                        normalx = 0.0f;
                        normaly = 1.0f;
                    }
                    else
                    {
                        normalx = 0.0f;
                        normaly = -1.0f;
                    }
                }

                // return the time of collision
                return entryTime;
            }
        }
Beispiel #5
0
        public static float Swept_AABB(Box b1, Box b2, ref float normalx, ref float normaly)
        {
            float xInvEntry, yInvEntry;
            float xInvExit, yInvExit;

            // find the distance between the objects on the near and far sides for both x and y
            if (b1.vx > 0.0f)
            {
                xInvEntry = b2.x - (b1.x + b1.w);
                xInvExit  = (b2.x + b2.w) - b1.x;
            }
            else
            {
                xInvEntry = (b2.x + b2.w) - b1.x;
                xInvExit  = b2.x - (b1.x + b1.w);
            }

            if (b1.vy > 0.0f)
            {
                yInvEntry = b2.y - (b1.y + b1.h);
                yInvExit  = (b2.y + b2.h) - b1.y;
            }
            else
            {
                yInvEntry = (b2.y + b2.h) - b1.y;
                yInvExit  = b2.y - (b1.y + b1.h);
            }

            // find time of collision and time of leaving for each axis (if statement is to prevent divide by zero)
            float xEntry, yEntry;
            float xExit, yExit;

            if (b1.vx == 0.0f)
            {
                xEntry = -float.PositiveInfinity;
                xExit  = float.PositiveInfinity;
            }
            else
            {
                xEntry = xInvEntry / b1.vx;
                xExit  = xInvExit / b1.vx;
            }

            if (b1.vy == 0.0f)
            {
                yEntry = -float.PositiveInfinity;
                yExit  = float.PositiveInfinity;
            }
            else
            {
                yEntry = yInvEntry / b1.vy;
                yExit  = yInvExit / b1.vy;
            }

            // find the earliest/latest times of collision
            float entryTime = Math.Max(xEntry, yEntry);
            float exitTime  = Math.Min(xExit, yExit);

            // if there was no collision
            if (entryTime > exitTime || xEntry < 0.0f && yEntry < 0.0f || xEntry > 1.0f || yEntry > 1.0f)
            {
                normalx = 0.0f;
                normaly = 0.0f;
                return(1.0f);
            }
            else // if there was a collision
            {
                // calculate normal of collided surface
                if (xEntry > yEntry && (b1.y + b1.h + 1.0f != b2.y))
                {
                    if (xInvEntry < 0.0f)
                    {
                        normalx = 1.0f;
                        normaly = 0.0f;
                    }
                    else
                    {
                        normalx = -1.0f;
                        normaly = 0.0f;
                    }
                }
                else
                {
                    if (yInvEntry < 0.0f)
                    {
                        normalx = 0.0f;
                        normaly = 1.0f;
                    }
                    else
                    {
                        normalx = 0.0f;
                        normaly = -1.0f;
                    }
                }

                // return the time of collision
                return(entryTime);
            }
        }