public PathfinderNode(PathfinderNetwork ParentNetwork) { PathfinderLayer tmpLayer = default(PathfinderLayer); if ( ParentNetwork.NodeLayerCount == 0 ) { tmpLayer = new PathfinderLayer(ParentNetwork); } else { tmpLayer = ParentNetwork.NodeLayers[0]; } Layer = tmpLayer; tmpLayer.Node_Add(this); }
public void Resize(PathfinderNetwork NetworkForSize) { int NewSize = 0; if ( NetworkForSize.NodeLayerCount > 0 ) { NewSize = NetworkForSize.NodeLayers[0].NodeCount; } else { NewSize = 0; } if ( Size < NewSize ) { int Num = 0; Size = (int)(NewSize * SizeEnlargementRatio); Num = Size - 1; Nodes_Booleans = new bool[Num + 1]; Nodes_ValuesA = new float[Num + 1]; Nodes_ValuesB = new float[Num + 1]; Nodes_Booleans = new bool[Num + 1]; Nodes_Path.Nodes = new PathfinderNode[Num + 1]; Nodes_Nodes = new PathfinderNode[Num + 1]; } else { if ( Size > NewSize * SizeReductionRatio ) { int Num = 0; Size = (int)(NewSize * SizeEnlargementRatio); Num = Size - 1; Nodes_Booleans = new bool[Num + 1]; Nodes_ValuesA = new float[Num + 1]; Nodes_ValuesB = new float[Num + 1]; Nodes_Booleans = new bool[Num + 1]; Nodes_Path.Nodes = new PathfinderNode[Num + 1]; Nodes_Nodes = new PathfinderNode[Num + 1]; } } }
private PathfinderNode GetNearestNodeConnection(PathfinderNetwork Network, sXY_int Pos, int MinClearance, float MaxDistance) { int A = 0; PathfinderNode[] TravelNodes = new PathfinderNode[Network.get_GetNodeLayer(0).GetNodeCount * 10]; int TravelNodeCount = 0; float[] NodeTravelDists = new float[Network.get_GetNodeLayer(0).GetNodeCount]; int TravelNodeNum = 0; PathfinderNode CurrentNode = default(PathfinderNode); PathfinderNode OtherNode = default(PathfinderNode); PathfinderConnection tmpConnection = default(PathfinderConnection); PathfinderNode BestNode = null; float TravelDist = 0; bool Flag = default(bool); for ( A = 0; A <= Network.get_GetNodeLayer(0).GetNodeCount - 1; A++ ) { NodeTravelDists[A] = float.MaxValue; } TravelNodes[0] = GetNearestNode(Network, Pos, 1); if ( TravelNodes[0] == null ) { return null; } TravelNodeCount = 1; NodeTravelDists[TravelNodes[0].Layer_NodeNum] = 0.0F; while ( TravelNodeNum < TravelNodeCount ) { CurrentNode = TravelNodes[TravelNodeNum]; if ( CurrentNode.Clearance >= MinClearance ) { if ( BestNode == null ) { BestNode = CurrentNode; } else if ( NodeTravelDists[CurrentNode.Layer_NodeNum] < NodeTravelDists[BestNode.Layer_NodeNum] ) { BestNode = CurrentNode; } } for ( A = 0; A <= CurrentNode.GetConnectionCount - 1; A++ ) { tmpConnection = CurrentNode.get_GetConnection(A); OtherNode = tmpConnection.GetOtherNode(CurrentNode); TravelDist = NodeTravelDists[CurrentNode.Layer_NodeNum] + tmpConnection.GetValue; if ( BestNode == null ) { Flag = true; } else if ( TravelDist < NodeTravelDists[BestNode.Layer_NodeNum] ) { Flag = true; } else { Flag = false; } if ( Flag && TravelDist < NodeTravelDists[OtherNode.Layer_NodeNum] ) { NodeTravelDists[OtherNode.Layer_NodeNum] = TravelDist; TravelNodes[TravelNodeCount] = OtherNode; TravelNodeCount++; } } TravelNodeNum++; } return BestNode; }
//Public Structure sGenerateSide // Public Node As PathfinderNode // Public TopLink As PathfinderNode // Public TopRightLink As PathfinderNode // Public RightLink As PathfinderNode // Public BottomRightLink As PathfinderNode // Public BottomLink As PathfinderNode // Public BottomLeftLink As PathfinderNode // Public LeftLink As PathfinderNode // Public TopLeftLink As PathfinderNode //End Structure //Public Structure sGenerateRoadsArgs // Public RoadType As sPainter.clsRoad // Public MaxAlt As Byte // Public Terrain As sPainter.clsTerrain // Public MinLength As Integer // Public MaxLength As Integer // Public MinTurnRatio As Single // Public MaxTurnRatio As Single // Public Quantity As Integer //End Structure //Public Sub GenerateRoads( Args As sGenerateRoadsArgs) // Dim RoadPathMap As New PathfinderNetwork // Dim tmpNode As PathfinderNode // Dim NodeTag As clsNodeTag // For Y = 0 To Terrain.Size.Y // For X = 0 To Terrain.Size.X // GenerateTerrainVertex(X, Y).Node = New PathfinderNode(RoadPathMap) // NodeTag = New clsNodeTag // NodeTag.Pos = New sXY_int(X * 128, Y * 128) // GenerateTerrainVertex(X, Y).Node.Tag = NodeTag // Next // Next // For Y = 0 To Terrain.Size.Y // For X = 0 To Terrain.Size.X // tmpNodeA = GenerateTerrainVertex(X, Y).Node // If X > 0 Then // tmpNodeB = GenerateTerrainVertex(X - 1, Y).Node // GenerateTerrainVertex(X, Y).LeftLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)) // End If // If Y > 0 Then // If X > 0 Then // tmpNodeB = GenerateTerrainVertex(X - 1, Y - 1).Node // GenerateTerrainVertex(X, Y).TopLeftLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)) // End If // tmpNodeB = GenerateTerrainVertex(X, Y - 1).Node // GenerateTerrainVertex(X, Y).TopLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)) // If X < Terrain.Size.X Then // tmpNodeB = GenerateTerrainVertex(X + 1, Y - 1).Node // GenerateTerrainVertex(X, Y).TopRightLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)) // End If // End If // If X < Terrain.Size.X Then // tmpNodeB = GenerateTerrainVertex(X + 1, Y).Node // GenerateTerrainVertex(X, Y).RightLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)) // End If // If Y < Terrain.Size.Y Then // If X > 0 Then // tmpNodeB = GenerateTerrainVertex(X - 1, Y + 1).Node // GenerateTerrainVertex(X, Y).BottomLeftLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)) // End If // tmpNodeB = GenerateTerrainVertex(X, Y + 1).Node // GenerateTerrainVertex(X, Y).BottomLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)) // If X < Terrain.Size.X Then // tmpNodeB = GenerateTerrainVertex(X + 1, Y + 1).Node // GenerateTerrainVertex(X, Y).BottomRightLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)) // End If // End If // Next // Next // RoadPathMap.LargeArraysResize() // RoadPathMap.FindCalc() // RoadPathMap.Deallocate() //End Sub public void ClearLayout() { int A = 0; int B = 0; if ( TilePathMap != null ) { TilePathMap.Deallocate(); TilePathMap = null; } if ( VertexPathMap != null ) { VertexPathMap.Deallocate(); VertexPathMap = null; } for ( A = 0; A <= ConnectionCount - 1; A++ ) { Connections[A].PassageNodeA = null; Connections[A].PassageNodeB = null; Connections[A].Reflections = null; } ConnectionCount = 0; for ( A = 0; A <= PassageNodeCount - 1; A++ ) { for ( B = 0; B <= SymmetryBlockCount - 1; B++ ) { PassageNodes[B, A].Connections = null; } } PassageNodeCount = 0; NearestCount = 0; }
public PathfinderNode GetNearestNode(PathfinderNetwork Network, sXY_int Pos, int MinClearance) { int A = 0; double Dist = 0; PathfinderNode tmpNode = default(PathfinderNode); PathfinderNode BestNode = default(PathfinderNode); double BestDist = 0; clsNodeTag tmpNodeTag = default(clsNodeTag); BestDist = double.MaxValue; BestNode = null; for ( A = 0; A <= Network.get_GetNodeLayer(0).GetNodeCount - 1; A++ ) { tmpNode = Network.get_GetNodeLayer(0).get_GetNode(A); if ( tmpNode.GetClearance >= MinClearance ) { tmpNodeTag = (clsNodeTag)tmpNode.Tag; Dist = (tmpNodeTag.Pos - Pos).ToDoubles().GetMagnitude(); if ( Dist < BestDist ) { BestDist = Dist; BestNode = tmpNode; } } } return BestNode; }
public void GenerateTilePathMap() { clsNodeTag NodeTag = default(clsNodeTag); PathfinderNode tmpNodeA = default(PathfinderNode); PathfinderNode tmpNodeB = default(PathfinderNode); int X = 0; int Y = 0; TilePathMap = new PathfinderNetwork(); for ( Y = 0; Y <= Map.Terrain.TileSize.Y - 1; Y++ ) { for ( X = 0; X <= Map.Terrain.TileSize.X - 1; X++ ) { GenerateTerrainTiles[X, Y] = new GenerateTerrainTile(); GenerateTerrainTiles[X, Y].Node = new PathfinderNode(TilePathMap); NodeTag = new clsNodeTag(); NodeTag.Pos = new sXY_int((int)((X + 0.5D) * 128.0D), (int)((Y + 0.5D) * 128.0D)); GenerateTerrainTiles[X, Y].Node.Tag = NodeTag; } } for ( Y = 0; Y <= Map.Terrain.TileSize.Y - 1; Y++ ) { for ( X = 0; X <= Map.Terrain.TileSize.X - 1; X++ ) { tmpNodeA = GenerateTerrainTiles[X, Y].Node; if ( X > 0 ) { tmpNodeB = GenerateTerrainTiles[X - 1, Y].Node; GenerateTerrainTiles[X, Y].LeftLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)); } if ( Y > 0 ) { if ( X > 0 ) { tmpNodeB = GenerateTerrainTiles[X - 1, Y - 1].Node; GenerateTerrainTiles[X, Y].TopLeftLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)); } tmpNodeB = GenerateTerrainTiles[X, Y - 1].Node; GenerateTerrainTiles[X, Y].TopLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)); if ( X < Map.Terrain.TileSize.X - 1 ) { tmpNodeB = GenerateTerrainTiles[X + 1, Y - 1].Node; GenerateTerrainTiles[X, Y].TopRightLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)); } } if ( X < Map.Terrain.TileSize.X - 1 ) { tmpNodeB = GenerateTerrainTiles[X + 1, Y].Node; GenerateTerrainTiles[X, Y].RightLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)); } if ( Y < Map.Terrain.TileSize.Y - 1 ) { if ( X > 0 ) { tmpNodeB = GenerateTerrainTiles[X - 1, Y + 1].Node; GenerateTerrainTiles[X, Y].BottomLeftLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)); } tmpNodeB = GenerateTerrainTiles[X, Y + 1].Node; GenerateTerrainTiles[X, Y].BottomLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)); if ( X < Map.Terrain.TileSize.X - 1 ) { tmpNodeB = GenerateTerrainTiles[X + 1, Y + 1].Node; GenerateTerrainTiles[X, Y].BottomRightLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)); } } } } TilePathMap.LargeArraysResize(); TilePathMap.FindCalc(); }
public clsResult GenerateLayoutTerrain() { clsResult ReturnResult = new clsResult("Terrain heights"); clsNodeTag NodeTag = default(clsNodeTag); PathfinderNode tmpNodeA = default(PathfinderNode); PathfinderNode tmpNodeB = default(PathfinderNode); int A = 0; int B = 0; int C = 0; int D = 0; int X = 0; int Y = 0; sXY_int XY_int = new sXY_int(); double Dist = 0; double BestDist = 0; bool Flag = default(bool); Map = new clsMap(TileSize); GenerateTerrainTiles = new GenerateTerrainTile[Map.Terrain.TileSize.X, Map.Terrain.TileSize.Y]; GenerateTerrainVertices = new GenerateTerrainVertex[Map.Terrain.TileSize.X + 1, Map.Terrain.TileSize.Y + 1]; //set terrain heights VertexPathMap = new PathfinderNetwork(); for ( Y = 0; Y <= Map.Terrain.TileSize.Y; Y++ ) { for ( X = 0; X <= Map.Terrain.TileSize.X; X++ ) { GenerateTerrainVertices[X, Y] = new GenerateTerrainVertex(); GenerateTerrainVertices[X, Y].Node = new PathfinderNode(VertexPathMap); NodeTag = new clsNodeTag(); NodeTag.Pos = new sXY_int(X * 128, Y * 128); GenerateTerrainVertices[X, Y].Node.Tag = NodeTag; } } for ( Y = 0; Y <= Map.Terrain.TileSize.Y; Y++ ) { for ( X = 0; X <= Map.Terrain.TileSize.X; X++ ) { tmpNodeA = GenerateTerrainVertices[X, Y].Node; if ( X > 0 ) { tmpNodeB = GenerateTerrainVertices[X - 1, Y].Node; GenerateTerrainVertices[X, Y].LeftLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)); } if ( Y > 0 ) { if ( X > 0 ) { tmpNodeB = GenerateTerrainVertices[X - 1, Y - 1].Node; GenerateTerrainVertices[X, Y].TopLeftLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)); } tmpNodeB = GenerateTerrainVertices[X, Y - 1].Node; GenerateTerrainVertices[X, Y].TopLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)); if ( X < Map.Terrain.TileSize.X ) { tmpNodeB = GenerateTerrainVertices[X + 1, Y - 1].Node; GenerateTerrainVertices[X, Y].TopRightLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)); } } if ( X < Map.Terrain.TileSize.X ) { tmpNodeB = GenerateTerrainVertices[X + 1, Y].Node; GenerateTerrainVertices[X, Y].RightLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)); } if ( Y < Map.Terrain.TileSize.Y ) { if ( X > 0 ) { tmpNodeB = GenerateTerrainVertices[X - 1, Y + 1].Node; GenerateTerrainVertices[X, Y].BottomLeftLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)); } tmpNodeB = GenerateTerrainVertices[X, Y + 1].Node; GenerateTerrainVertices[X, Y].BottomLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)); if ( X < Map.Terrain.TileSize.X ) { tmpNodeB = GenerateTerrainVertices[X + 1, Y + 1].Node; GenerateTerrainVertices[X, Y].BottomRightLink = tmpNodeA.GetOrCreateConnection(tmpNodeB, GetNodePosDist(tmpNodeA, tmpNodeB)); } } } } VertexPathMap.LargeArraysResize(); VertexPathMap.FindCalc(); PathfinderLayer BaseLayer = VertexPathMap.get_GetNodeLayer(0); PathfinderLayer JitterLayer = VertexPathMap.get_GetNodeLayer(JitterScale); A = JitterLayer.GetNodeCount - 1; int[] NodeLevel = new int[A + 1]; clsBaseNodeLevels BaseNodeLevel = new clsBaseNodeLevels(); BaseNodeLevel.NodeLevels = new float[BaseLayer.GetNodeCount]; //set position of jitter layer nodes Position.XY_dbl XY_dbl = default(Position.XY_dbl); if ( A > 0 ) { for ( B = 0; B <= A; B++ ) { tmpNodeA = JitterLayer.get_GetNode(B); C = 0; XY_dbl.X = 0.0D; XY_dbl.Y = 0.0D; CalcNodePos(tmpNodeA, ref XY_dbl, ref C); NodeTag = new clsNodeTag(); NodeTag.Pos.X = (int)(XY_dbl.X / C); NodeTag.Pos.Y = (int)(XY_dbl.Y / C); tmpNodeA.Tag = NodeTag; } } //set node heights clsConnection BestConnection = default(clsConnection); clsPassageNode BestNode = default(clsPassageNode); for ( A = 0; A <= JitterLayer.GetNodeCount - 1; A++ ) { NodeTag = (clsNodeTag)(JitterLayer.get_GetNode(A).Tag); NodeLevel[A] = -1; BestDist = float.MaxValue; BestConnection = null; BestNode = null; for ( B = 0; B <= ConnectionCount - 1; B++ ) { //If Not (Connections(B).PassageNodeA.IsOnBorder Or Connections(B).PassageNodeB.IsOnBorder) Then if ( Connections[B].PassageNodeA.Level == Connections[B].PassageNodeB.Level ) { //only do this if the levels are the same //this is to make sure nodes that are connected are actually connected on the terrain XY_int = MathUtil.PointGetClosestPosOnLine(Connections[B].PassageNodeA.Pos, Connections[B].PassageNodeB.Pos, NodeTag.Pos); Dist = Convert.ToSingle((XY_int - NodeTag.Pos).ToDoubles().GetMagnitude()); if ( Dist < BestDist ) { BestDist = Dist; if ( (NodeTag.Pos - Connections[B].PassageNodeA.Pos).ToDoubles().GetMagnitude() <= (NodeTag.Pos - Connections[B].PassageNodeB.Pos).ToDoubles().GetMagnitude() ) { BestNode = Connections[B].PassageNodeA; } else { BestNode = Connections[B].PassageNodeB; } Flag = true; } } } for ( C = 0; C <= PassageNodeCount - 1; C++ ) { //If Not PassageNodesA(C).IsOnBorder Then for ( D = 0; D <= SymmetryBlockCount - 1; D++ ) { Dist = Convert.ToSingle((NodeTag.Pos - PassageNodes[D, C].Pos).ToDoubles().GetMagnitude()); if ( Dist < BestDist ) { BestDist = Dist; BestNode = PassageNodes[D, C]; Flag = true; } } //End If } if ( Flag ) { NodeLevel[A] = BestNode.Level; } else { NodeLevel[A] = BestConnection.PassageNodeA.Level; } if ( NodeLevel[A] < 0 ) { ReturnResult.ProblemAdd("Error: Node height is not set."); return ReturnResult; } } for ( A = 0; A <= LevelCount - 1; A++ ) { for ( B = 0; B <= JitterLayer.GetNodeCount - 1; B++ ) { if ( NodeLevel[B] >= A ) { SetBaseLevel(JitterLayer.get_GetNode(B), A, BaseNodeLevel); } } } //make ramp slopes int MinRampLength = ((int)(LevelHeight * Map.HeightMultiplier * 2.0D)) + 128; clsSetBaseLevelRampArgs RampArgs = new clsSetBaseLevelRampArgs(); RampArgs.BaseLevel = BaseNodeLevel; RampArgs.RampRadius = 320.0F; for ( B = 0; B <= ConnectionCount - 1; B++ ) { RampArgs.Connection = Connections[B]; RampArgs.RampLength = Math.Max(Convert.ToInt32((Connections[B].PassageNodeA.Pos - Connections[B].PassageNodeB.Pos).ToDoubles().GetMagnitude() * 0.75D), MinRampLength * Math.Abs(Connections[B].PassageNodeA.Level - Connections[B].PassageNodeB.Level)); for ( A = 0; A <= JitterLayer.GetNodeCount - 1; A++ ) { if ( Connections[B].IsRamp ) { NodeTag = (clsNodeTag)(JitterLayer.get_GetNode(A).Tag); XY_int = MathUtil.PointGetClosestPosOnLine(Connections[B].PassageNodeA.Pos, Connections[B].PassageNodeB.Pos, NodeTag.Pos); Dist = Convert.ToSingle((XY_int - NodeTag.Pos).ToDoubles().GetMagnitude()); if ( Dist < RampArgs.RampLength * 2.0F ) { SetBaseLevelRamp(RampArgs, JitterLayer.get_GetNode(A)); } } } } for ( A = 0; A <= BaseLayer.GetNodeCount - 1; A++ ) { NodeTag = (clsNodeTag)(BaseLayer.get_GetNode(A).Tag); Map.Terrain.Vertices[(int)(NodeTag.Pos.X / 128.0F), (int)(NodeTag.Pos.Y / 128.0F)].Height = (byte)(BaseNodeLevel.NodeLevels[A] * LevelHeight); } return ReturnResult; }
public PathfinderLayer(PathfinderNetwork NewParentNetwork) { Network = NewParentNetwork; Network.NodeLayer_Add(this); }
public void ForceDeallocate() { int A = 0; for ( A = 0; A <= NodeCount - 1; A++ ) { Nodes[A].ForceDeallocate(); } Nodes = null; Connections = null; Network = null; ParentLayer = null; }