private void Start() { //create map map = new NodeMap(); map.defaultNodeGraphic = defaultSprite; map.defaultUnpathableGraphic = unpathableSprite; map.Initialize(WIDTH, HEIGHT, SIZE); //set unpathable nodes map.SetPathingAt(2, 1, false); map.SetPathingAt(2, 2, false); map.SetPathingAt(2, 3, false); map.SetPathingAt(3, 3, false); map.SetPathingAt(4, 3, false); map.SetPathingAt(5, 3, false); map.SetPathingAt(6, 3, false); map.SetPathingAt(7, 3, false); map.SetPathingAt(7, 2, false); map.SetPathingAt(7, 1, false); map.SetPathingAt(7, 0, false); //create and place character if (characterSprite) { character = new NodeOccupant(); character.graphic = (GameObject)Instantiate(characterSprite, new Vector3(0, 0, 0), Quaternion.identity); map.SetNodeOccupantAt(1, 1, character); } map.Build(); map.OnNodeClicked += OnNodeClicked; }
//This probably shouldn't do any rendering changes, perhaps NodeRenderer? private void UpdateOccupant(Node node, NodeOccupant occupant) { //Calculate path to target Node targetNode = occupant.target; if (targetNode != null && occupant.isPathingDirty) { occupant.path = NodePathing.GetPath(nodes, node, targetNode, occupant); occupant.isPathingDirty = false;//perhaps the setter for 'path' should do this automatically? } //Move towards next node Node nextNode = occupant.GetNextNode(); if (nextNode != null) { Vector3 currentPosition = occupant.graphic.transform.position; Vector3 targetPosition = GetWorldPositionOfNode(nextNode); occupant.graphic.transform.position = Vector3.Lerp(currentPosition, targetPosition, 5f * Time.deltaTime); //if close enough to target node, update path if (Vector3.Distance(currentPosition, targetPosition) < 0.1f) { occupant.path.RemoveAt(0); node.occupant = null; SetNodeOccupant(nextNode, occupant); } } else { occupant.graphic.transform.position = GetWorldPositionOfNode(node); } }
//shortcut helper method, so consumers don't need to know about Nodes or inner workings public void SetNodeOccupantAt(int x, int y, NodeOccupant occupant) { Node node = GetNodeAt(x, y); if (node != null && node.isPathable) { SetNodeOccupant(node, occupant); } }
public void Update() { foreach (Node node in nodes) { NodeOccupant occupant = node.GetFirstOccupant(); if (occupant != null) { UpdateOccupant(node, occupant); } } }
private void ValidateNode(Node node) { NodeOccupant occupant = node.GetFirstOccupant(); if (!node.isPathable && occupant != null) { Node validNode = NodePathing.FindClosestPathableNode(this, node); if (validNode != null) { node.occupant = null; SetNodeOccupant(validNode, occupant); } } }
private Node GetNodeFromOccupant(NodeOccupant occupant) { for (int x = 0; x < this.width; x++) { for (int y = 0; y < this.height; y++) { Node node = GetNodeAt(x, y); if (node == null) { continue; } if (node.GetFirstOccupant() == occupant) { return(node); } } } return(null); }
//this doesn't clear occupants, so they could end up in an unpathable node public void ClearMap() { foreach (Node node in nodes) { node.isPathable = true; NodeOccupant occupant = node.GetFirstOccupant(); if (occupant != null) { occupant.path = null; } } foreach (GameObject gameObject in gameObjectsToNodes.Keys) { GameObject.Destroy(gameObject); } gameObjectsToNodes = new Dictionary <GameObject, Node>(); }
private static float GetPathingCost(Node from, Node to, NodeOccupant occupant = null) { float cost = 1;//eventually node types will have a different pathing cost by default bool doesOccupantBlockPathing = occupant != null && occupant.doesBlockPathing; if (!to.isPathable && doesOccupantBlockPathing) { return(Mathf.Infinity); } if (from.x != to.x && from.y != to.y) { // nudge diagonal movement to break ties cost += 0.001f; } return(cost); }
private void SetNodeOccupant(Node node, NodeOccupant occupant) { node.occupant = occupant; occupant.owner = node; }
//Dijkstra public static List <Node> GetPath(Node[,] map, Node from, Node to, NodeOccupant occupant = null) { Dictionary <Node, float> distance = new Dictionary <Node, float>(); Dictionary <Node, Node> previousNode = new Dictionary <Node, Node>(); List <Node> uncheckedNodes = new List <Node>();//Q //initialize default values distance[from] = 0; previousNode[from] = null; foreach (Node node in map) { if (node != from) { distance[node] = Mathf.Infinity; previousNode[node] = null; } uncheckedNodes.Add(node); } //loop until all nodes are checked while (uncheckedNodes.Count > 0) { Node closestNode = null; foreach (Node potentialClosestNode in uncheckedNodes) { if (closestNode == null || distance[potentialClosestNode] < distance[closestNode]) { closestNode = potentialClosestNode; } } if (closestNode == to) { break; } uncheckedNodes.Remove(closestNode); foreach (Node node in closestNode.neighbors) { float alt = distance[closestNode] + GetPathingCost(closestNode, node, occupant); if (alt < distance[node]) { distance[node] = alt; previousNode[node] = closestNode; } } } if (previousNode[to] == null) { return(null);//no route found } List <Node> path = new List <Node>(); while (to != null) { path.Add(to); to = previousNode[to]; } path.Reverse(); return(path); }