/// <summary>Creates a new instance of GridMananger.</summary> /// <param name="numCols">The number of rows in the grid.</param> /// <param name="numRows">The number of columns in the grid.</param> /// <param name="inWorld">The world that contains this grid.</param> /// <param name="initSquares">Whether or not to initialize the grid squares.</param> private GridManager(int numCols, int numRows, World inWorld, bool initSquares) { clear(); InWorld = inWorld; Squares = new GridSqr[numRows, numCols]; SqrWidth = inWorld.Width / (FInt)numCols; SqrHeight = inWorld.Height / (FInt)numRows; if (initSquares) { for (int row = 0; row < NumRows; row++) { for (int col = 0; col < NumCols; col++) { Squares[row, col] = new GridSqr(); } } } }
/// <summary>Refreshes the visibility of all objects in the specified grid square.</summary> /// <param name="sqr">The grid square to refresh.</param> /// <param name="array">An array that contains the upper-left corner and the lower-right corner of the area to search.</param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> private void gridRefreshVisibility(GridSqr sqr, object array, TimeSpan time, int opID) { VectorF topLeft = ((VectorF[])array)[0]; VectorF bottomRight = ((VectorF[])array)[1]; foreach (NodeSkel node in sqr.Nodes) { if (node.LastCheck == time && node.LastCheckNum == opID) continue; node.LastCheck = time; node.LastCheckNum = opID; if (node.Owner.Type == Player.PlayerType.Human || node.X - node.Radius > bottomRight.X || node.X + node.Radius < topLeft.X || node.Y - node.Radius > bottomRight.Y || node.Y + node.Radius < topLeft.Y) continue; node.Visible = HumanPlayer.Fog.isVisible(node); } foreach (SegmentSkel seg in sqr.Segments) { if (seg.LastCheck == time && seg.LastCheckNum == opID) continue; seg.LastCheck = time; seg.LastCheckNum = opID; if (seg.Owner.Type == Player.PlayerType.Human || Calc.Min(seg.EndLoc[0].X, seg.EndLoc[1].X) > bottomRight.X || Calc.Max(seg.EndLoc[0].X, seg.EndLoc[1].X) < topLeft.X || Calc.Min(seg.EndLoc[0].Y, seg.EndLoc[1].Y) > bottomRight.Y || Calc.Max(seg.EndLoc[0].Y, seg.EndLoc[1].Y) < topLeft.Y) continue; seg.Visible = HumanPlayer.Fog.isVisible(seg); } }
/// <summary>Search the specified grid square for a node that overlaps the specified point.</summary> /// <param name="sqr">The grid square to search.</param> /// <param name="array">An array containing the following values: the point to search, whether or not to test only active nodes, and the node, if found.</param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> private void gridNodeAtPoint(GridSqr sqr, object array, TimeSpan time, int opID) { object[] data = (object[])array; VectorF point = (VectorF)data[0]; bool activeOnly = (bool)data[1]; #if DEBUG if (data[2] != null) throw new Exception("The grid node was already found, but the operation was not cancelled."); #endif foreach (Node node in sqr.Nodes) { // make sure we haven't already tested this node if ((node.LastCheck != time || node.LastCheckNum != opID) && (node.Active || !activeOnly)) { VectorF pos = node.Pos; FInt xDiff = point.X - pos.X; FInt yDiff = point.Y - pos.Y; if (Calc.Sqrt((xDiff * xDiff) + (yDiff * yDiff)) <= node.Radius) { data[2] = node; Grid.CancelOperation = true; } node.LastCheck = time; node.LastCheckNum = opID; } } }
/// <summary>Search the specified grid square for a hotspot that overlaps the specified point.</summary> /// <param name="sqr">The grid square to search.</param> /// <param name="array">An array containing the following values: the point to search and the hotspot, if found.</param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> private void gridHotspotAtPoint(GridSqr sqr, object array, TimeSpan time, int opID) { object[] data = (object[])array; VectorF point = (VectorF)data[0]; #if DEBUG if (data[1] != null) throw new Exception("The grid hotspot was already found, but the operation was not cancelled."); #endif foreach (Hotspot hotspot in sqr.Hotspots) { // make sure we haven't already tested this hotspot if (hotspot.LastCheck != time || hotspot.LastCheckNum != opID) { VectorF pos = hotspot.Pos; FInt xDiff = point.X - pos.X; FInt yDiff = point.Y - pos.Y; if (Calc.Sqrt((xDiff * xDiff) + (yDiff * yDiff)) <= (FInt)50) // TODO: get rid of magic number { data[1] = hotspot; Grid.CancelOperation = true; } hotspot.LastCheck = time; hotspot.LastCheckNum = opID; } } }
/// <summary>Searches for specified grid square for the a geo vertex that overlaps the provided point.</summary> /// <param name="sqr">The grid square to search.</param> /// <param name="array">An array that contains the following values: the point to search, the geo (if found), and the vertex (if found).</param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> private void gridGeoVertexAtPoint(GridSqr sqr, object array, TimeSpan time, int opID) { VectorF point = (VectorF)((object[])array)[0]; // TODO: specify threshold FInt thresh = (FInt)10; foreach (Geo geo in sqr.Geos) { if (geo.LastCheck == time && geo.LastCheckNum == opID) continue; geo.LastCheck = time; geo.LastCheckNum = opID; // test bounding box if (point.X < geo.Left - thresh || point.X > geo.Right + thresh || point.Y < geo.Top - thresh || point.Y > geo.Bottom + thresh) { continue; } // test all vertices for (int i = 0; i < geo.Vertices.Length; i += 2) { if (point.X > geo.Vertices[i].X - thresh && point.X < geo.Vertices[i].X + thresh && point.Y > geo.Vertices[i].Y - thresh && point.Y < geo.Vertices[i].Y + thresh) { ((object[])array)[1] = geo; ((object[])array)[2] = i; Grid.CancelOperation = true; return; } } if (geo.Vertices.Length > 1) { // test last vertex int i = geo.Vertices.Length - 1; if (point.X > geo.Vertices[i].X - thresh && point.X < geo.Vertices[i].X + thresh && point.Y > geo.Vertices[i].Y - thresh && point.Y < geo.Vertices[i].Y + thresh) { ((object[])array)[1] = geo; ((object[])array)[2] = i; Grid.CancelOperation = true; return; } // test center if (geo.Vertices.Length > 2 && point.X > geo.Center.X - thresh && point.X < geo.Center.X + thresh && point.Y > geo.Center.Y - thresh && point.Y < geo.Center.Y + thresh) { ((object[])array)[1] = geo; ((object[])array)[2] = -1; Grid.CancelOperation = true; return; } } } }
/// <summary>Find all nodes in the specified grid square that collide with the specified circle based on spacing.</summary> /// <param name="sqr">The grid square to search.</param> /// <param name="array">An object array that contains the following fields: circle center, circle radius, circle spacing, whether to test against nodes' spacing as opposed to radius, nodes to ignore, a list to collect all colliding nodes, and whether to stop after first collision.</param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> private void gridNodeCollNodeSpacing(GridSqr sqr, object array, TimeSpan time, int opID) { VectorF point = (VectorF)((object[])array)[0]; FInt radius = (FInt)((object[])array)[1]; FInt spacing = (FInt)((object[])array)[2]; Player owner = (Player)((object[])array)[3]; List<NodeSkel> ignoreNode = (List<NodeSkel>)((object[])array)[4]; List<NodeSkel> nodeColls = (List<NodeSkel>)((object[])array)[5]; CollSrchType srchType = (CollSrchType)((object[])array)[6]; bool includeUnbuilt = (bool)((object[])array)[7]; // find circle bounding box FInt circLeft = point.X - radius - spacing; FInt circRight = point.X + radius + spacing; FInt circTop = point.Y - radius - spacing; FInt circBottom = point.Y + radius + spacing; foreach (NodeSkel node in sqr.Nodes) { if (node.LastCheck != time || node.LastCheckNum != opID) { node.LastCheck = time; node.LastCheckNum = opID; if (ignoreNode.Contains(node) || node.Owner != owner || (!includeUnbuilt && !node.Active)) continue; FInt minDist = radius + node.Radius + Calc.Max(spacing, node.Spacing); // first compare against bounds and then find intersection if (circLeft <= node.Pos.X + node.Radius + node.Spacing && circRight >= node.Pos.X - node.Radius - node.Spacing && circTop <= node.Pos.Y + node.Radius + node.Spacing && circBottom >= node.Pos.Y - node.Radius - node.Spacing && VectorF.DistanceApprox(node.Pos, point) < minDist * FInt.F3 && VectorF.Distance(node.Pos, point) < minDist) { nodeColls.Add(node); if (srchType == CollSrchType.DoesItCollide || srchType == CollSrchType.GetIntersection) { Grid.CancelOperation = true; break; } } } } }
/// <summary>Removes the provided node from the specified grid square.</summary> /// <param name="sqr">The grid square to remove the node from.</param> /// <param name="node">The node to remove from the grid square.</param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> public void gridRemoveNode(GridSqr sqr, object node, TimeSpan time, int opID) { ((Node)node).LastCheck = time; ((Node)node).LastCheckNum = opID; sqr.Nodes.Remove((Node)node); }
/// <summary>Removes the provided geometric obstacle from the specified grid square.</summary> /// <param name="sqr">The grid square to remove the geometric obstacle from.</param> /// <param name="geo">The geometric obstacle to remove from the grid square.</param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> public void gridRemoveGeo(GridSqr sqr, object geo, TimeSpan time, int opID) { ((Geo)geo).LastCheck = time; ((Geo)geo).LastCheckNum = opID; sqr.Geos.Remove((Geo)geo); }
/// <summary>Applies the visibility of all nodes in the provided grid square.</summary> /// <param name="sqr">The square to apply.</param> /// <param name="array"></param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> private void gridInvalidate(GridSqr sqr, object array, TimeSpan time, int opID) { foreach (Node node in sqr.Nodes) { if (node.LastCheck != time || node.LastCheckNum != opID) { applyVisibility(node); node.LastCheck = time; node.LastCheckNum = opID; } } }
/// <summary>Activates a single square on the grid</summary> /// <param name="sqr">The square to activate.</param> /// <param name="data">null</param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> private void ActivatePoint(GridSqr sqr, object data, TimeSpan time, int opID) { sqr.Active = true; }
/// <summary>Find all segments in the specified grid square that collide with the specified line.</summary> /// <param name="sqr">The grid square to search.</param> /// <param name="array">An object array that contains the following fields: line point1, line point 2, segments to ignore, a list to collect all colliding segments, and whether to stop after first collision.</param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> private void gridSegCollSeg(GridSqr sqr, object array, TimeSpan time, int opID) { VectorF point1 = (VectorF)((object[])array)[0]; VectorF point2 = (VectorF)((object[])array)[1]; List<SegmentSkel> ignoreSeg = (List<SegmentSkel>)((object[])array)[2]; List<SegmentSkel> segColls = (List<SegmentSkel>)((object[])array)[3]; CollSrchType srchType = (CollSrchType)((object[])array)[4]; bool includeUnbuilt = (bool)((object[])array)[5]; Player owner = includeUnbuilt ? (Player)((object[])array)[6] : null; SegmentSkel closestSeg = null; VectorF closestInt = VectorF.Zero; VectorF closestDist = VectorF.Zero; // find line bounds FInt lineLeft; FInt lineRight; FInt lineTop; FInt lineBottom; if (point1.X < point2.X) { lineLeft = point1.X; lineRight = point2.X; } else { lineLeft = point2.X; lineRight = point1.X; } if (point1.Y < point2.Y) { lineTop = point1.Y; lineBottom = point2.Y; } else { lineTop = point2.Y; lineBottom = point1.Y; } foreach (SegmentSkel seg in sqr.Segments) { if ((seg.LastCheck != time || seg.LastCheckNum != opID) && !ignoreSeg.Contains(seg)) { seg.LastCheck = time; seg.LastCheckNum = opID; // find endpoints VectorF end0; VectorF end1; if (includeUnbuilt && seg.Owner == owner) { if (seg.State[1] == SegmentSkel.SegState.Retracting) end0 = seg.EndLoc[0]; else end0 = ((Segment)seg).Nodes[0].Pos; if (seg.State[0] == SegmentSkel.SegState.Retracting) end1 = seg.EndLoc[1]; else end1 = ((Segment)seg).Nodes[1].Pos; } else { end0 = seg.EndLoc[0]; end1 = seg.EndLoc[1]; } // find segment bounds FInt segLeft; FInt segRight; FInt segTop; FInt segBottom; if (end1.X < end0.X) { segLeft = end1.X; segRight = end0.X; } else { segLeft = end0.X; segRight = end1.X; } if (end1.Y < end0.Y) { segTop = end1.Y; segBottom = end0.Y; } else { segTop = end0.Y; segBottom = end1.Y; } // first compare against bounds and then find intersection if (lineLeft <= segRight && lineRight >= segLeft && lineTop <= segBottom && lineBottom >= segTop) { if ((srchType == CollSrchType.GetAllCollisions || srchType == CollSrchType.DoesItCollide) && Calc.DoLinesIntersect(point1, point2, end1, end0)) { segColls.Add(seg); if (srchType == CollSrchType.DoesItCollide) { Grid.CancelOperation = true; break; } } else if (srchType == CollSrchType.GetIntersection) { VectorF? intersection = Calc.LineIntersectIfExists(point1, point2, end1, end0); if (intersection != null) { VectorF val = intersection.Value; if (closestSeg == null || Calc.Abs(val.Y - point1.Y) < closestDist.Y || Calc.Abs(val.X - point1.X) < closestDist.X) { closestSeg = seg; closestInt = val; closestDist = new VectorF(Calc.Abs(val.X - point1.X), Calc.Abs(val.Y - point1.Y)); } } } } } } if (srchType == CollSrchType.GetIntersection && closestSeg != null) { segColls.Add(closestSeg); ((object[])array)[7] = closestInt; } }
/// <summary>Find all nodes in the specified grid square that collide with the specified line.</summary> /// <param name="sqr">The grid square to search.</param> /// <param name="array">An object array that contains the following fields: line point1, line point 2, nodes to ignore, a list to collect all colliding nodes, and whether to stop after first collision.</param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> private void gridSegCollNode(GridSqr sqr, object array, TimeSpan time, int opID) { VectorF point1 = (VectorF)((object[])array)[0]; VectorF point2 = (VectorF)((object[])array)[1]; List<NodeSkel> ignoreNode = (List<NodeSkel>)((object[])array)[2]; List<NodeSkel> nodeColls = (List<NodeSkel>)((object[])array)[3]; CollSrchType srchType = (CollSrchType)((object[])array)[4]; bool includeUnbuilt = (bool)((object[])array)[5]; Player owner = includeUnbuilt ? (Player)((object[])array)[6] : null; // find line bounds FInt lineLeft; FInt lineRight; FInt lineTop; FInt lineBottom; if (point1.X < point2.X) { lineLeft = point1.X; lineRight = point2.X; } else { lineLeft = point2.X; lineRight = point1.X; } if (point1.Y < point2.Y) { lineTop = point1.Y; lineBottom = point2.Y; } else { lineTop = point2.Y; lineBottom = point1.Y; } foreach (NodeSkel node in sqr.Nodes) { if (node.LastCheck != time || node.LastCheckNum != opID) { node.LastCheck = time; node.LastCheckNum = opID; // first compare against bounds and then find intersection if ((node.Active || (includeUnbuilt && node.Owner == owner)) && !ignoreNode.Contains(node) && lineLeft <= node.Pos.X + node.Radius && lineRight >= node.Pos.X - node.Radius && lineTop <= node.Pos.Y + node.Radius && lineBottom >= node.Pos.Y - node.Radius && Calc.LinePointDistance(node.Pos, point1, point2) <= node.Radius) { nodeColls.Add(node); if (srchType == CollSrchType.DoesItCollide || srchType == CollSrchType.GetIntersection) { Grid.CancelOperation = true; break; } } } } }
/// <summary>Find all geos in the specified grid square that collide with the specified line.</summary> /// <param name="sqr">The grid square to search.</param> /// <param name="array">An object array that contains the following fields: line point1, line point 2, null, a list to collect all colliding geos, and whether to stop after first collision.</param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> private void gridSegCollGeo(GridSqr sqr, object array, TimeSpan time, int opID) { VectorF point1 = (VectorF)((object[])array)[0]; VectorF point2 = (VectorF)((object[])array)[1]; // array[2] is null List<GeoSkel> geoColls = (List<GeoSkel>)((object[])array)[3]; CollSrchType srchType = (CollSrchType)((object[])array)[4]; // find line bounds FInt lineLeft; FInt lineRight; FInt lineTop; FInt lineBottom; if (point1.X < point2.X) { lineLeft = point1.X; lineRight = point2.X; } else { lineLeft = point2.X; lineRight = point1.X; } if (point1.Y < point2.Y) { lineTop = point1.Y; lineBottom = point2.Y; } else { lineTop = point2.Y; lineBottom = point1.Y; } // test each geo foreach (GeoSkel geo in sqr.Geos) { if (geo.LastCheck == time && geo.LastCheckNum == opID) continue; // if bounding boxes overlap if (lineLeft <= geo.Right && lineTop <= geo.Bottom && lineRight >= geo.Left && lineBottom >= geo.Top) { for (int i = 0; i < geo.LineTopLeft.Length; i++) { // if line's bounding box overlaps if (geo.LineTopLeft[i].X <= lineRight && geo.LineTopLeft[i].Y <= lineBottom && geo.LineLowerRight[i].X >= lineLeft && geo.LineLowerRight[i].Y >= lineTop) { int vi; int vi1; if (i == geo.LineTopLeft.Length - 1 && geo.CloseLoop) { vi = geo.Vertices.Length - 1; vi1 = 0; } else { vi = i * 2; vi1 = vi + 1; } if (Calc.DoLinesIntersect(point1, point2, geo.Vertices[vi], geo.Vertices[vi1])) { geoColls.Add(geo); break; } } } } geo.LastCheck = time; geo.LastCheckNum = opID; // if only one collision was needed, exit out if (geoColls.Count != 0 && (srchType == CollSrchType.DoesItCollide || srchType == CollSrchType.GetIntersection)) { Grid.CancelOperation = true; break; } } }
/// <summary>Find all segments in the specified grid square that collide with the specified circle.</summary> /// <param name="sqr">The grid square to search.</param> /// <param name="array">An object array that contains the following fields: node center, circle radius, null, segments to ignore, a list to collect all colliding segments, and whether to stop after first collision.</param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> private void gridNodeCollSeg(GridSqr sqr, object array, TimeSpan time, int opID) { VectorF point = (VectorF)((object[])array)[0]; FInt radius = (FInt)((object[])array)[1]; List<SegmentSkel> ignoreSeg = (List<SegmentSkel>)((object[])array)[2]; List<SegmentSkel> segColls = (List<SegmentSkel>)((object[])array)[3]; CollSrchType srchType = (CollSrchType)((object[])array)[4]; bool includeUnbuilt = (bool)((object[])array)[5]; Player owner = includeUnbuilt ? (Player)((object[])array)[6] : null; // find circle bounding box FInt circLeft = point.X - radius; FInt circRight = point.X + radius; FInt circTop = point.Y - radius; FInt circBottom = point.Y + radius; foreach (SegmentSkel seg in sqr.Segments) { if ((seg.LastCheck != time || seg.LastCheckNum != opID) && !ignoreSeg.Contains(seg)) { seg.LastCheck = time; seg.LastCheckNum = opID; // find endpoints VectorF end0; VectorF end1; if (includeUnbuilt && seg.Owner == owner) { if (seg.State[1] == SegmentSkel.SegState.Retracting) end0 = seg.EndLoc[0]; else end0 = ((Segment)seg).Nodes[0].Pos; if (seg.State[0] == SegmentSkel.SegState.Retracting) end1 = seg.EndLoc[1]; else end1 = ((Segment)seg).Nodes[1].Pos; } else { end0 = seg.EndLoc[0]; end1 = seg.EndLoc[1]; } // find segment bounds FInt segLeft; FInt segRight; FInt segTop; FInt segBottom; if (end1.X < end0.X) { segLeft = end1.X; segRight = end0.X; } else { segLeft = end0.X; segRight = end1.X; } if (end1.Y < end0.Y) { segTop = end1.Y; segBottom = end0.Y; } else { segTop = end0.Y; segBottom = end1.Y; } // first compare against bounds and then test for collision if (circLeft <= segRight && circRight >= segLeft && circTop <= segBottom && circBottom >= segTop && Calc.LinePointDistance(point, end1, end0) <= radius) { segColls.Add(seg); if (srchType == CollSrchType.GetIntersection || srchType == CollSrchType.DoesItCollide) { Grid.CancelOperation = true; break; } } } } }
/// <summary>Search the specified grid square for a segment owned by the specified player that overlaps the specified point.</summary> /// <param name="sqr">The grid square to search.</param> /// <param name="array">An array containing the following values: the point to search, the owner of the segment (null if any), and the segment, if found.</param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> private void gridSegmentAtPoint(GridSqr sqr, object array, TimeSpan time, int opID) { VectorF point = (VectorF)((object[])array)[0]; Player owner = (Player)((object[])array)[1]; FInt top = new FInt(); FInt left = new FInt(); FInt right = new FInt(); FInt bottom = new FInt(); // TODO: specify threshold FInt thresh = (FInt)10; foreach (Segment seg in sqr.Segments) { if (seg.LastCheck != time || seg.LastCheckNum != opID) { seg.LastCheck = time; seg.LastCheckNum = opID; // get bounding box if (seg.EndLoc[0].X < seg.EndLoc[1].X) { left = seg.EndLoc[0].X; right = seg.EndLoc[1].X; } else { left = seg.EndLoc[1].X; right = seg.EndLoc[0].X; } if (seg.EndLoc[0].Y < seg.EndLoc[1].Y) { top = seg.EndLoc[0].Y; bottom = seg.EndLoc[1].Y; } else { top = seg.EndLoc[1].Y; bottom = seg.EndLoc[0].Y; } // test segment if ((seg.Owner == owner || owner == null) && point.X >= left - thresh && point.X <= right + thresh && point.Y >= top - thresh && point.Y <= bottom + thresh && seg.overlapsPoint(point)) { ((object[])array)[2] = seg; Grid.CancelOperation = true; break; } } } }
/// <summary>Adds the provided segment to the specified square.</summary> /// <param name="sqr">The grid square to add the segment to.</param> /// <param name="seg">The segment to add.</param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> public void gridAddSegment(GridSqr sqr, object seg, TimeSpan time, int opID) { ((SegmentSkel)seg).LastCheck = time; ((SegmentSkel)seg).LastCheckNum = opID; sqr.Segments.Add((SegmentSkel)seg); }
/// <summary>Search the specified grid square for a segment end that overlaps the specified point.</summary> /// <param name="sqr">The grid square to search.</param> /// <param name="array">An array containing the following values: the point to search, and the segment end, if found.</param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> private void gridSegmentEndAtPoint(GridSqr sqr, object array, TimeSpan time, int opID) { VectorF point = (VectorF)((object[])array)[0]; // TODO: specify threshold FInt thresh = (FInt)20; foreach (Segment seg in sqr.Segments) { if (seg.LastCheck != time || seg.LastCheckNum != opID) { seg.LastCheck = time; seg.LastCheckNum = opID; // test segment if (point.X >= seg.Nodes[0].X - thresh && point.X <= seg.Nodes[0].X + thresh && point.Y >= seg.Nodes[0].Y - thresh && point.Y <= seg.Nodes[0].Y + thresh && !Nodes.Contains(seg.Nodes[0]) && VectorF.Distance(point, seg.Nodes[0].Pos) <= thresh) { ((object[])array)[1] = seg.Nodes[0]; } else if (point.X >= seg.Nodes[1].X - thresh && point.X <= seg.Nodes[1].X + thresh && point.Y >= seg.Nodes[1].Y - thresh && point.Y <= seg.Nodes[1].Y + thresh && !Nodes.Contains(seg.Nodes[1]) && VectorF.Distance(point, seg.Nodes[1].Pos) <= thresh) { ((object[])array)[1] = seg.Nodes[1]; } else { continue; } break; } } if (((object[])array)[1] != null) Grid.CancelOperation = true; }
/// <summary>Adds the provided node to the specified square.</summary> /// <param name="sqr">The grid square to add the node to.</param> /// <param name="node">The node to add.</param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> private void gridAddNode(GridSqr sqr, object node, TimeSpan time, int opID) { ((NodeSkel)node).LastCheck = time; ((NodeSkel)node).LastCheckNum = opID; sqr.Nodes.Add((NodeSkel)node); }
/// <summary>Removes the provided hotspot from the specified grid square.</summary> /// <param name="sqr">The grid square to remove the hotspot from.</param> /// <param name="hotspot">The hotspot to remove the grid square from.</param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> public void gridRemoveHotspot(GridSqr sqr, object hotspot, TimeSpan time, int opID) { ((Hotspot)hotspot).LastCheck = time; ((Hotspot)hotspot).LastCheckNum = opID; sqr.Hotspots.Remove((Hotspot)hotspot); }
/// <summary>Searches for specified grid square for the a geo line that overlaps the provided point.</summary> /// <param name="sqr">The grid square to search.</param> /// <param name="array">An array that contains the following values: the point to search, the geo (if found), and the first vertex of the line (if found).</param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> private void gridGeoLineAtPoint(GridSqr sqr, object array, TimeSpan time, int opID) { VectorF point = (VectorF)((object[])array)[0]; // TODO: specify threshold FInt thresh = (FInt)10; foreach (Geo geo in sqr.Geos) { if (geo.LastCheck == time && geo.LastCheckNum == opID) continue; geo.LastCheck = time; geo.LastCheckNum = opID; // test bounding box if (geo.Vertices.Length < 2 || point.X < geo.Left - thresh || point.X > geo.Right + thresh || point.Y < geo.Top - thresh || point.Y > geo.Bottom + thresh) { continue; } // test all lines for (int i = 0, max = geo.Vertices.Length; i < max; i += 2) { int bi = i / 2; if (point.X > geo.LineTopLeft[bi].X - thresh && point.X < geo.LineLowerRight[bi].X + thresh && point.Y > geo.LineTopLeft[bi].Y - thresh && point.Y < geo.LineLowerRight[bi].Y + thresh && Calc.LinePointDistance(point, geo.Vertices[i], geo.Vertices[i + 1]) < thresh) { ((object[])array)[1] = geo; ((object[])array)[2] = i; Grid.CancelOperation = true; return; } } if (geo.CloseLoop) { int i = geo.Vertices.Length - 1; int bi = geo.LineLowerRight.Length - 1; if (point.X > geo.LineTopLeft[bi].X - thresh && point.X < geo.LineLowerRight[bi].X + thresh && point.Y > geo.LineTopLeft[bi].Y - thresh && point.Y < geo.LineLowerRight[bi].Y + thresh && Calc.LinePointDistance(point, geo.Vertices[i], geo.Vertices[0]) < thresh) { ((object[])array)[1] = geo; ((object[])array)[2] = i; Grid.CancelOperation = true; return; } } } }
/// <summary>Removes the provided segment from the specified grid square.</summary> /// <param name="sqr">The grid square to remove the segment from.</param> /// <param name="segment">The segment to remove from the grid square.</param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> public void gridRemoveSegment(GridSqr sqr, object segment, TimeSpan time, int opID) { ((Segment)segment).LastCheck = time; ((Segment)segment).LastCheckNum = opID; sqr.Segments.Remove((Segment)segment); }
/// <summary>Find all geos in the specified grid square that collide with the specified circle.</summary> /// <param name="sqr">The grid square to search.</param> /// <param name="array">An object array that contains the following fields: node center, circle radius, null, null, a list to collect all colliding geos, and whether to stop after first collision.</param> /// <param name="time">The current game time.</param> /// <param name="opID">The current operation id.</param> private void gridNodeCollGeo(GridSqr sqr, object array, TimeSpan time, int opID) { VectorF point = (VectorF)((object[])array)[0]; FInt radius = (FInt)((object[])array)[1]; // array[2] is null List<GeoSkel> geoColls = (List<GeoSkel>)((object[])array)[3]; CollSrchType srchType = (CollSrchType)((object[])array)[4]; // find circle bounding box FInt circLeft = point.X - radius; FInt circRight = point.X + radius; FInt circTop = point.Y - radius; FInt circBottom = point.Y + radius; // test each geo foreach (GeoSkel geo in sqr.Geos) { if (geo.LastCheck == time && geo.LastCheckNum == opID) continue; // if bounding boxes overlap if (circLeft <= geo.Right && circTop <= geo.Bottom && circRight >= geo.Left && circBottom >= geo.Top) { for (int i = 0; i < geo.LineTopLeft.Length; i++) { // if line's bounding box overlaps if (geo.LineTopLeft[i].X <= circRight && geo.LineTopLeft[i].Y <= circBottom && geo.LineLowerRight[i].X >= circLeft && geo.LineLowerRight[i].Y >= circTop) { int vi; int vi1; if (i == geo.LineTopLeft.Length - 1 && geo.CloseLoop) { vi = geo.Vertices.Length - 1; vi1 = 0; } else { vi = i * 2; vi1 = vi + 1; } if (Calc.LinePointDistance(point, geo.Vertices[vi], geo.Vertices[vi1]) <= radius) { geoColls.Add(geo); break; } } } } geo.LastCheck = time; geo.LastCheckNum = opID; // if only one collision was needed, exit out if (geoColls.Count != 0 && (srchType == CollSrchType.DoesItCollide || srchType == CollSrchType.GetIntersection)) { Grid.CancelOperation = true; break; } } }