/// <summary> /// Checks if this rectangle intersects another rectangle /// </summary> /// <param name="otherRect">The rectangle to check</param> /// <returns>Whether or not this rectangle intersects or touches the other</returns> public bool IntersectsOrTouches(FRect otherRect) { return(!(Bottom < otherRect.Top || Top > otherRect.Bottom || Right < otherRect.Left || Left > otherRect.Right)); }
/// <summary> /// Returns all items (not nodes) that intersect with the given area. /// </summary> /// <param name="area"></param> /// <returns></returns> public List <T> GetItemsWithinArea(FRect area) { List <T> items = new List <T>(); RootNode.GetItemsWithinArea(ref items, ref area, false); return(items); }
/// <summary> /// Checks if this rectangle intersects another rectangle /// </summary> /// <param name="otherRect">The rectangle to check</param> /// <returns>Whether or not this rectangle intersects the other</returns> public bool Intersects(FRect otherRect) { return(!(Bottom <= otherRect.Top || Top >= otherRect.Bottom || Right <= otherRect.Left || Left >= otherRect.Right)); }
/// <summary> /// Modified code from the XNA platformer starter kit 4.0 /// </summary> /// <param name="rectA"></param> /// <param name="rectB"></param> /// <returns></returns> public Vector2 GetIntersectionDepth(FRect rectB) { // If we are not intersecting at all, return (0, 0). if (!Intersects(rectB)) { return(Vector2.Zero); } // Calculate half sizes. float halfWidthA = Width / 2.0f; float halfHeightA = Height / 2.0f; float halfWidthB = rectB.Width / 2.0f; float halfHeightB = rectB.Height / 2.0f; // Calculate centers. Vector2 centerA = CenterLoc; // new Vector2(Left + halfWidthA, Top + halfHeightA); Vector2 centerB = rectB.CenterLoc; //new Vector2(rectB.Left + halfWidthB, rectB.Top + halfHeightB); // Calculate current and minimum-non-intersecting distances between centers. float distanceX = centerA.X - centerB.X; float distanceY = centerA.Y - centerB.Y; float minDistanceX = halfWidthA + halfWidthB; float minDistanceY = halfHeightA + halfHeightB; // Calculate and return intersection depths. float depthX = distanceX > 0 ? minDistanceX - distanceX : -minDistanceX - distanceX; float depthY = distanceY > 0 ? minDistanceY - distanceY : -minDistanceY - distanceY; return(new Vector2(depthX, depthY)); }
/// <summary> /// DOES NOT WORK. WIP. probably because the additems() doesnt work correctly. /// </summary> /// <param name="items"></param> /// <param name="area"></param> /// <param name="skipChecks"></param> public void GetItemsWithinArea(ref List <T> items, ref FRect area, bool skipChecks) { if (skipChecks || AABB.Intersects(area)) { // When the area if entirely within the Cell then skip collision checks on the child nodes if (area.FullyEncloses(AABB)) { skipChecks = true; } foreach (T item in items) { if (skipChecks || item.AABB.Intersects(area)) { items.Add(item); } } if (!IsLeaf) { TopLeft.GetItemsWithinArea(ref items, ref area, skipChecks); TopRight.GetItemsWithinArea(ref items, ref area, skipChecks); BottomLeft.GetItemsWithinArea(ref items, ref area, skipChecks); BottomRight.GetItemsWithinArea(ref items, ref area, skipChecks); } } }
public static Vector2 GetIntersectionDepth(this Rectangle rectA, FRect rectB) { // Calculate half sizes. float halfWidthA = rectA.Width / 2.0f; float halfHeightA = rectA.Height / 2.0f; float halfWidthB = rectB.Width / 2.0f; float halfHeightB = rectB.Height / 2.0f; // Calculate centers. Vector2 centerA = new Vector2(rectA.Left + halfWidthA, rectA.Top + halfHeightA); Vector2 centerB = new Vector2(rectB.Left + halfWidthB, rectB.Top + halfHeightB); // Calculate current and minimum-non-intersecting distances between centers. float distanceX = centerA.X - centerB.X; float distanceY = centerA.Y - centerB.Y; float minDistanceX = halfWidthA + halfWidthB; float minDistanceY = halfHeightA + halfHeightB; // If we are not intersecting at all, return (0, 0). if (Math.Abs(distanceX) >= minDistanceX || Math.Abs(distanceY) >= minDistanceY) { return(Vector2.Zero); } // Calculate and return intersection depths. float depthX = distanceX > 0 ? minDistanceX - distanceX : -minDistanceX - distanceX; float depthY = distanceY > 0 ? minDistanceY - distanceY : -minDistanceY - distanceY; return(new Vector2(depthX, depthY)); }
/// <summary> /// Root node constructor /// </summary> /// <param name="AABB"></param> /// <param name="maxItems"></param> public QuadTreeNode(FRect AABB, int maxItems) { ParentNode = null; // Rootnode this.AABB = AABB; MaxItems = maxItems; m_depth = 0; }
/// <summary> /// Regular constructor /// </summary> /// <param name="parentNode"></param> /// <param name="AABB"></param> /// <param name="maxItems"></param> public QuadTreeNode(QuadTreeNode <T> parentNode, FRect AABB, int maxItems) { ParentNode = parentNode; this.AABB = AABB; MaxItems = maxItems; m_depth = parentNode.Depth + 1; }
/// <summary> /// Determines if a circle intersects a rectangle. /// </summary> /// <returns>True if the circle and rectangle overlap. False otherwise. /// Returns false when the circle is completely inside the rectangle (not tested)</returns> public bool Overlaps(FRect rectangle) { Vector2 v = new Vector2(MathHelper.Clamp(Center.X, rectangle.Left, rectangle.Right), MathHelper.Clamp(Center.Y, rectangle.Top, rectangle.Bottom)); Vector2 direction = Center - v; float distanceSquared = direction.LengthSquared(); return((distanceSquared > 0) && (distanceSquared < Radius * Radius)); }
/// <summary> /// Make sure that Rect1 & Rect2 intersect /// Source ZiggyWare (now defunct) /// </summary> /// <param name="Rect1"></param> /// <param name="Rect2"></param> /// <returns></returns> /// <example> /// if (Player.PlayerCollisionRect.Intersects(VolcanoBorderRect)) /// { /// //Since our rectangles are colliding, we need to seperate them. This provides our seperation amount once they have collided. /// Vector2 displacement = GameplayScreen.CalcualteMinimumTranslationDistance(Player.PlayerCollisionRect, VolcanoBorderRect); /// Player.PlayerPos += displacement; //Move player with seperation amount /// } /// </example> public static Vector2 CalculateMinimumTranslationDistance(FRect Rect1, FRect Rect2) { Vector2 result = Vector2.Zero; float difference = 0.0f; float minimumTranslationDistance = 0.0f; //The absolute minimum distance we'll need to separate our colliding object. int axis = 0; // Axis stores the value of X or Y. X = 0, Y = 1. int side = 0; // Side stores the value of left (-1) or right (+1). // Left difference = Rect1.Right - Rect2.Left; minimumTranslationDistance = difference; axis = 0; side = -1; // Right difference = Rect2.Right - Rect1.Left; if (difference < minimumTranslationDistance) { minimumTranslationDistance = difference; axis = 0; side = 1; } // Down difference = Rect1.Bottom - Rect2.Top; if (difference < minimumTranslationDistance) { minimumTranslationDistance = difference; axis = 1; side = -1; } // Up difference = Rect2.Bottom - Rect1.Top; if (difference < minimumTranslationDistance) { minimumTranslationDistance = difference; axis = 1; side = 1; } if (axis == 1) //Y Axis { result.Y = (float)side * minimumTranslationDistance; } else { //X Axis result.X = (float)side * minimumTranslationDistance; } //result = new Vector2((float)side * minimumTranslationDistance, (float)side * minimumTranslationDistance); return(result); }
// perhaps see: http://stackoverflow.com/questions/8307834/fastest-algorithm-to-edge-detect-between-two-simple-rectangles for an extensive touching example. /// <summary> /// ONLY tests for touching rectangles. So if rect A contains rectB they do NOT touch! /// </summary> /// <param name="rectA"></param> /// <param name="rectB"></param> /// <param name="allowedDifference"></param> /// <returns></returns> public static bool AreOnlyTouching(this FRect rectA, FRect rectB, float allowedDifference) { // They are at the same point if (rectA.X == rectB.X && rectA.Y == rectB.Y) { return(true); } // A's right side touches B's left side if ( (Math.Abs(rectA.Right - rectB.Left) <= allowedDifference) && // X-axis ((rectA.Top - allowedDifference) <= rectB.Bottom && // Y-axis rectA.Bottom >= (rectB.Top - allowedDifference)) // Y-axis ) { return(true); } // A's left side touches B's right side if ( (Math.Abs(rectA.Left - rectB.Right) <= allowedDifference) && // X-axis ((rectA.Top - allowedDifference) <= rectB.Bottom && // Y-axis rectA.Bottom >= (rectB.Top - allowedDifference)) // Y-axis ) { return(true); } // A's bottom touches B's top if ( (Math.Abs(rectA.Bottom - rectB.Top) <= allowedDifference) && // Y-axis ((rectA.Left + allowedDifference) <= rectB.Right && // X-axis rectA.Right >= (rectB.Left - allowedDifference)) // X-axis ) { return(true); } // A's top touches B's bottom // A's left side touches B's right side if ( (Math.Abs(rectA.Top - rectB.Bottom) <= allowedDifference) && // Y-axis ((rectA.Left + allowedDifference) <= rectB.Right && // X-axis rectA.Right >= (rectB.Left - allowedDifference)) // X-axis ) { return(true); } return(false); }
/// <summary> /// /// </summary> /// <param name="otherRect"></param> /// <returns>The overlapping area or FRect.Empty when no collision</returns> public FRect Overlap(FRect otherRect) { if (!Intersects(otherRect)) { return(FRect.Empty); } FRect result = FRect.Empty; result.Left = Math.Max(Left, otherRect.Left); result.Top = Math.Max(Top, otherRect.Top); result.Width = Math.Min(Right, otherRect.Right) - result.Left; result.Height = Math.Min(Bottom, otherRect.Bottom) - result.Top; return(result); }
/// <summary> /// Check for collision between a circle and a FRectangle /// </summary> /// <param name="centerPoint"></param> /// <param name="radius"></param> /// <param name="rectangle"></param> /// <returns></returns> public static bool Intersects(Vector2 circleCenterLoc, float radius, FRect rectangle) { if (Collision.PointIsInRect(circleCenterLoc, rectangle)) { return(true); } Vector2 v = new Vector2(MathHelper.Clamp(circleCenterLoc.X, rectangle.Left, rectangle.Right), MathHelper.Clamp(circleCenterLoc.Y, rectangle.Top, rectangle.Bottom)); Vector2 direction = circleCenterLoc - v; float distanceSquared = direction.LengthSquared(); return((distanceSquared > 0) && (distanceSquared < radius * radius)); }
public HexGrid(Vector2 topLeft, int width, int height, int tileWidth, int tileHeight, string defaultTileTexture) { TopLeft = topLeft; Width = width; Height = height; ArrayWidth = width / tileWidth - 1; // -1 because otherwise the last tile in the odd rows would overlap with 50%. ArrayHeight = (int)(height / (tileHeight * 0.75f)); TileArray = new HexTile[ArrayWidth, ArrayHeight]; m_GridArea = new FRect(topLeft, width, height); DefaultTileTex = Common.str2Tex(defaultTileTexture); TileWidth = tileWidth; TileHeight = tileHeight; Create(); SetNeigbours(); }
/// <summary> /// Author: Napoleon. /// Tested and works. /// Only apply this to non-rotated rectangles. /// Touching rectangles don't count in this function /// </summary> /// <param name="movingRect">Usually the player or moving object.</param> /// <param name="staticRect">Usually the wall or something. The collided sides are the sides from this rectangle</param> /// <returns></returns> /// <example> /// if ((collidedSides & Collision.RectSide.Top) == Collision.RectSide.Top) /// // Top side was hit, do something here /// </example> public static RectSide CollidedSidesNoTouch(this FRect movingRect, FRect staticRect) { RectSide result = RectSide.None; if (!movingRect.Intersects(staticRect)) { return(result); // No intersection at all } if (movingRect == staticRect) { return(RectSide.Equal); } // Left if (movingRect.Right > staticRect.Left && movingRect.Left < staticRect.Left) { result = (result | RectSide.Left); } // Top if (movingRect.Bottom > staticRect.Top && movingRect.Top < staticRect.Top) { result = (result | RectSide.Top); } // Right if (movingRect.Left < staticRect.Right && movingRect.Right > staticRect.Right) { result = (result | RectSide.Right); } // Bottom if (movingRect.Top < staticRect.Bottom && movingRect.Bottom > staticRect.Bottom) { result = (result | RectSide.Bottom); } if (result == RectSide.None) { return(RectSide.Inside); // moving rectangle is inside the static rectangle } return(result); }
/// <summary> /// Checks if this rectangle fully encloses a smaller rectangle within it. If one or more eges are touching then it does not count as a full overlap. /// </summary> /// <param name="rect"></param> /// <returns></returns> public bool FullyEncloses(FRect rect) { return(rect.Top > Top && rect.Right < Right && rect.Bottom < Bottom && rect.Left > Left); }
public static bool PointIsInRect(Vector2 point, FRect rectangle) { return(point.X >= rectangle.Left && point.X <= rectangle.Right && point.Y >= rectangle.Top && point.Y <= rectangle.Bottom); }
public bool Collide(FRect rectangle) { return(Overlaps(rectangle) || rectangle.Contains(Center)); }