Ejemplo n.º 1
0
        private CollisionInfo AABBvsAABB(AABB_Collider lhs, AABB_Collider rhs)
        {
            Vec2 lhsPos = new Vec2(lhs.transform.position.x, lhs.transform.position.y) + lhs.LocalOffset;
            Vec2 rhsPos = new Vec2(rhs.transform.position.x, rhs.transform.position.y) + rhs.LocalOffset;

            Vec2 lhsBottomLeft = lhs.BottomLeft + lhsPos;
            Vec2 lhsTopRight   = lhs.TopRight + lhsPos;
            Vec2 rhsBottomLeft = rhs.BottomLeft + rhsPos;
            Vec2 rhsTopRight   = rhs.TopRight + rhsPos;

            if (lhsBottomLeft.x < rhsTopRight.x &&
                lhsTopRight.x > rhsBottomLeft.x &&
                lhsTopRight.y > rhsBottomLeft.y &&
                lhsBottomLeft.y < rhsTopRight.y)
            {
                Vec2 vMult   = Vec2.One;
                Vec2 depth   = Vec2.Zero;
                Vec2 colNorm = Vec2.Zero;

                if (lhsPos.x > rhsPos.x)
                {
                    colNorm.x = -1f;
                    depth.x   = rhsTopRight.x - lhsBottomLeft.x;
                }
                else
                {
                    colNorm.x = 1f;
                    depth.x   = rhsBottomLeft.x - lhsTopRight.x;
                }
                if (lhsPos.y > rhsPos.y)
                {
                    colNorm.y = -1f;
                    depth.y   = rhsTopRight.y - lhsBottomLeft.y;
                }
                else
                {
                    colNorm.y = 1f;
                    depth.y   = rhsBottomLeft.y - lhsTopRight.y;
                }

                if (Mathf.Abs(depth.x) > Mathf.Abs(depth.y))
                {
                    colNorm.x = 0f;
                    depth.x   = 0f;
                    vMult.y   = 0f;
                }
                else
                {
                    colNorm.y = 0f;
                    depth.y   = 0f;
                    vMult.x   = 0f;
                }
                return(new CollisionInfo(true, depth, colNorm));
            }

            return(new CollisionInfo());
        }
Ejemplo n.º 2
0
        private CollisionInfo CIRCLEvsAABB(Circle_Collider lhs, AABB_Collider rhs, bool invertNormal)
        {
            // Vector from A to B
            Vector3 n = lhs.transform.position - rhs.transform.position;

            // Closest point on A to center of B
            Vector3 closest = n;

            // Calculate half extents along each axis
            float x_extent = rhs.Width * 0.5f;
            float y_extent = rhs.Height * 0.5f;

            // Clamp point to edges of the AABB
            closest.x = Mathf.Clamp(closest.x, -x_extent, x_extent);
            closest.y = Mathf.Clamp(closest.y, -y_extent, y_extent);

            bool inside = false;

            // Circle is inside the AABB, so we need to clamp the circle's center
            // to the closest edge
            if (n == closest)
            {
                inside = true;

                // Find closest axis
                if (Mathf.Abs(n.x) > Mathf.Abs(n.y))
                {
                    // Clamp to closest extent
                    if (closest.x > 0)
                    {
                        closest.x = x_extent;
                    }
                    else
                    {
                        closest.x = -x_extent;
                    }
                }

                // y axis is shorter
                else
                {
                    // Clamp to closest extent
                    if (closest.y > 0)
                    {
                        closest.y = y_extent;
                    }
                    else
                    {
                        closest.y = -y_extent;
                    }
                }
            }

            Vector3 normal      = n - closest;
            float   d           = normal.sqrMagnitude;
            float   r           = lhs.Radius;
            float   penetration = 0f;

            // Early out if the radius is shorter than distance to closest point and
            // Circle not inside the AABB
            if (d > r * r && !inside)
            {
                return(new CollisionInfo());
            }

            // Avoided sqrt until needed
            d = Mathf.Sqrt(d);

            // Collision normal needs to be flipped to point outside if circle was
            // inside the AABB
            if (inside)
            {
                normal = invertNormal ? -normal : normal;
            }
            else
            {
                normal = invertNormal ? normal : -normal;
            }

            penetration = r - d;
            Vec2 depth = new Vec2(normal.x, normal.y).Normalize();

            return(new CollisionInfo(true, depth * penetration, depth));
        }