/// <summary> /// Moves to a point right now. Before using this function, check if you cannot use MoveToQueue(Point p). This function may /// impact the FPS in a bad manner if used outside the queue. /// </summary> /// <param name="p">The point to move to</param> public void MoveToNow(Point p) { long ticks = DateTime.UtcNow.Ticks; if (Game1.GetInstance().collision.IsCollisionBetween(new Point((int)this.x, (int)this.y), p)) { Game1 game = Game1.GetInstance(); // Create temp nodes Node start = new Node(game.collision, (int)this.x, (int)this.y, true); Node end = new Node(game.collision, p.X, p.Y, true); LinkedList<PathfindingNode> nodes = new AStar(start, end).FindPath(); if (nodes != null) { // Remove the first node, because that's the node we're currently on .. nodes.RemoveFirst(); // Clear our current waypoints this.waypoints.Clear(); /*PathfindingNode previousNode = null; foreach (Node node in nodes) { node.selected = true; if (previousNode != null) { PathfindingNodeConnection conn = node.IsConnected(previousNode); if (conn != null && ((Node)conn.node1).selected && ((Node)conn.node2).selected) conn.drawColor = Color.Blue; } previousNode = node; }*/ foreach (Node n in nodes) { this.waypoints.AddLast(n.GetLocation()); } } // Nodes can no longer be used start.Destroy(); end.Destroy(); } else { this.waypoints.Clear(); this.waypoints.AddLast(p); } if (this.waypoints.Count > 0) { Point newTarget = this.waypoints.ElementAt(0); SetMoveToTarget(newTarget.X, newTarget.Y); } // Console.Out.WriteLine("Found path in " + ((DateTime.UtcNow.Ticks - ticks) / 10000) + "ms"); }
/// <summary> /// Calculates a path between the current unit and the point. /// </summary> /// <param name="p">The point to calculate to.</param> /// <returns>The list containing all the points that you should visit.</returns> public LinkedList<Point> CalculatePath(Point p) { LinkedList<Point> result = new LinkedList<Point>(); long ticks = DateTime.UtcNow.Ticks; if (Game1.GetInstance().collision.IsCollisionBetween(new Point((int)this.x, (int)this.y), p)) { Game1 game = Game1.GetInstance(); // Create temp nodes Node start = new Node(game.collision, (int)this.x, (int)this.y, true); Node end = new Node(game.collision, p.X, p.Y, true); LinkedList<PathfindingNode> nodes = new AStar(start, end).FindPath(); if (nodes != null) { // Remove the first node, because that's the node we're currently on .. nodes.RemoveFirst(); // Clear our current waypoints this.waypoints.Clear(); foreach (Node n in nodes) { result.AddLast(n.GetLocation()); } } // Nodes can no longer be used start.Destroy(); end.Destroy(); } else { result.AddLast(p); } return result; }
/// <summary> /// Updates the collisionmap, adding the rectangle to the collisionmap, and performing new connections, as for placing nodes /// </summary> /// <param name="rect"></param> public BuildingMesh PlaceBuilding(Rectangle rect) { CollisionChangedEvent e = new CollisionChangedEvent(); e.collision = this; e.changedRect = rect; e.collisionAdded = true; long ticks = DateTime.UtcNow.Ticks; e.oldData = (Boolean[])data.Clone(); Console.Out.WriteLine("Clone time: " + (DateTime.UtcNow.Ticks - ticks) / 10000 + "ms"); ticks = DateTime.UtcNow.Ticks; Boolean color = true; // Update collisionmap data for (int i = rect.Left; i < rect.Right; i++) { for (int j = rect.Top; j < rect.Bottom; j++) { data[PointToIndex(i, j)] = color; } } // Update collisionmap texture this.texture = BoolToTexture(Game1.GetInstance().graphics.GraphicsDevice, this.data, mapWidth, collisionMapTextureScale); e.newData = data; Console.Out.WriteLine("Data put time: " + (DateTime.UtcNow.Ticks - ticks) / 10000 + "ms"); ticks = DateTime.UtcNow.Ticks; Node[] newNodes = new Node[4]; RTSCollisionMap map = Game1.GetInstance().collision; newNodes[0] = new Node(map, rect.Left - 1, rect.Top - 1, true); newNodes[1] = new Node(map, rect.Right + 1, rect.Top - 1, true); newNodes[2] = new Node(map, rect.Left - 1, rect.Bottom + 1, true); newNodes[3] = new Node(map, rect.Right + 1, rect.Bottom + 1, true); Console.Out.WriteLine("Node create time: " + (DateTime.UtcNow.Ticks - ticks) / 10000 + "ms"); ticks = DateTime.UtcNow.Ticks; BuildingMesh mesh = new BuildingMesh(this); mesh.rect = rect; mesh.createdNodes = newNodes; LinkedList<PathfindingNode> nodes = PathfindingNodeManager.GetInstance().nodeList; foreach (PathfindingNode node in nodes) { if (rect.Contains(node.GetLocation())) mesh.removedNodes.AddLast(node.GetLocation()); } Console.Out.WriteLine("Mesh create time: " + (DateTime.UtcNow.Ticks - ticks) / 10000 + "ms"); ticks = DateTime.UtcNow.Ticks; LinkedList<Node> processedNodes = new LinkedList<Node>(); int nodesAdded = 0; foreach (Node newNode in newNodes) { foreach (Node connectedNode in newNode.GetConnectedNodes()) { // Let's not process things twice, as it's quite a heavy computation if (!processedNodes.Contains(connectedNode)) { // Remove its current nodes connectedNode.RemoveAllConnections(); // Scedule it for reprocessing SmartPathfindingNodeProcessor.GetInstance().Push(connectedNode); processedNodes.AddLast(connectedNode); nodesAdded++; } } } Console.Out.WriteLine("Node connection time: " + (DateTime.UtcNow.Ticks - ticks) / 10000 + "ms, adding " + nodesAdded + " nodes"); ticks = DateTime.UtcNow.Ticks; FireCollisionChangedEvent(e); Console.Out.WriteLine("Event time: " + (DateTime.UtcNow.Ticks - ticks)); return mesh; }
public BuildingMesh(RTSCollisionMap collision) { this.collision = collision; createdNodes = new Node[4]; removedNodes = new CustomArrayList<Point>(); }
/// <summary> /// Loads all the pathfinding nodes in the game. Also creates the connections. /// </summary> /// <param name="filename">The filename of the map to load from</param> public void LoadPathfindingNodes(String filename) { PathfindingNodeManager.GetInstance().ClearNodes(); XmlDocument xmldoc = new XmlDocument(); xmldoc.Load(filename); XmlNode rootNode = xmldoc.ChildNodes[1]; XmlNode nodes = rootNode.ChildNodes.Item(1); if (!nodes.Name.Equals("Nodes")) { throw new Exception("XML document is not formatted correctly"); } for (int i = 0; i < nodes.ChildNodes.Count; i++) { XmlNode node = nodes.ChildNodes[i]; if (!node.Name.Equals("Node")) { throw new Exception("XML document is not formatted correctly"); } Node pfNode = new Node(this.collisionMap, Int32.Parse(node.Attributes.GetNamedItem("x").Value), Int32.Parse(node.Attributes.GetNamedItem("y").Value), true); pfNode.generatedOnLoadTime = true; // One more node ready Game1.GetInstance().currentLoadProgress += 100; } SmartPathfindingNodeProcessor.GetInstance().StartThread(); }
/// <summary> /// Updates the collisionmap, adding the rectangle to the collisionmap, and performing new connections, as for placing nodes /// </summary> /// <param name="rect"></param> public BuildingMesh PlaceBuilding(Rectangle rect) { CollisionChangedEvent e = new CollisionChangedEvent(); e.collisionMap = this; e.changedRect = rect; e.collisionAdded = true; long ticks = DateTime.UtcNow.Ticks; this.UpdateCollisionMap(rect, true); Console.Out.WriteLine("Data put time: " + (DateTime.UtcNow.Ticks - ticks) / 10000 + "ms"); ticks = DateTime.UtcNow.Ticks; Node[] newNodes = new Node[4]; RTSCollisionMap map = Game1.GetInstance().map.collisionMap; newNodes[0] = new Node(map, rect.Left - 1, rect.Top - 1, false); newNodes[1] = new Node(map, rect.Right + 1, rect.Top - 1, false); newNodes[2] = new Node(map, rect.Left - 1, rect.Bottom + 1, false); newNodes[3] = new Node(map, rect.Right + 1, rect.Bottom + 1, false); Console.Out.WriteLine("Node create time: " + (DateTime.UtcNow.Ticks - ticks) / 10000 + "ms"); ticks = DateTime.UtcNow.Ticks; BuildingMesh mesh = new BuildingMesh(this); mesh.rect = rect; mesh.createdNodes = newNodes; PathfindingNodeManager manager = PathfindingNodeManager.GetInstance(); for (int i = 0; i < manager.GetNodeCount(); i++) { Node node = (Node)manager.GetNodeAt(i); if (rect.Contains(node.GetLocation())) mesh.removedNodes.AddLast(node.GetLocation()); } Console.Out.WriteLine("Mesh create time: " + (DateTime.UtcNow.Ticks - ticks) / 10000 + "ms"); /* ticks = DateTime.UtcNow.Ticks; CustomArrayList<Node> processedNodes = new CustomArrayList<Node>(); int nodesAdded = 0; foreach (Node newNode in newNodes) { } Console.Out.WriteLine("Node connection time: " + (DateTime.UtcNow.Ticks - ticks) / 10000 + "ms, adding " + nodesAdded + " nodes"); */ ticks = DateTime.UtcNow.Ticks; FireCollisionChangedEvent(e); Console.Out.WriteLine("Event time: " + (DateTime.UtcNow.Ticks - ticks)); return mesh; }