//TODO Change time to a constant speed based on rough estimations of distance. //TODO Add an interrupt variable so that the AI can leave the path or change paths. Maybe check to see if destination changes. IEnumerator PathTravel(pathNode location, pathNode destination, float speed) { List <pathNode> path = Dijkstra.ShortestPath(NodePath, location.ID, destination.ID); if (path.Count > 1) { //Add initial location twice to initialize spline cap path.Insert(0, path[0]); //Add destination twice for the end cap on spline path.Add(path[path.Count - 1]); float timer = 0; for (int i = 0; i < path.Count - 3; i++) { timer = 0; pathNode nextNode = path[i + 2]; float dist = Spline_Catmull_Rom.LengthofCurve(path[i].position, path[i + 1].position, path[i + 2].position, path[i + 3].position, 5); float time = dist / speed; while (Vector3.Distance(transform.position, nextNode.position) > Time.deltaTime) { timer += Time.deltaTime; if (timer > time) { break; } transform.position = Spline_Catmull_Rom.PointOnCurve(path[i].position, path[i + 1].position, path[i + 2].position, path[i + 3].position, timer / time); transform.LookAt(Spline_Catmull_Rom.PointOnCurve(path[i].position, path[i + 1].position, path[i + 2].position, path[i + 3].position, (timer + Time.deltaTime) / time)); yield return(null); } } currentNode = destination.ID; traveling = false; } }
//get nearest node ladder, ground. Useful for finding start and end points of the path private pathNode getNearestNode(Vector3 obj) { float dist = float.MaxValue; pathNode node = null; for (int i = 0; i < groundNodes.Count; i++) { if (groundNodes[i].neighbours.Count > 0 && obj.y > groundNodes[i].pos.y && Mathf.Abs(obj.x - groundNodes[i].pos.x) < blockSize && /*only find ground nodes that are within 4f*/ obj.y - groundNodes[i].pos.y < 4f) { float temp = Vector3.Distance(obj, (Vector3)groundNodes[i].pos); if (dist > temp) { dist = temp; node = groundNodes[i]; } } } for (int i = 0; i < ladderNodes.Count; i++) { if (ladderNodes[i].neighbours.Count > 0 && obj.y > ladderNodes[i].pos.y && Mathf.Abs(obj.x - ladderNodes[i].pos.x) < blockSize) { float temp = Vector3.Distance(obj, (Vector3)ladderNodes[i].pos); if (dist > temp) { dist = temp; node = ladderNodes[i]; } } } return(node); }
private void GroundNeighbors(List <pathNode> fromNodes, List <pathNode> toNodes) { //Distance max distance allowed between two nodes float distanceBetween = blockSize + groundMaxWidth; for (int i = 0; i < fromNodes.Count; i++) { pathNode a = fromNodes[i]; for (int t = 0; t < toNodes.Count; t++) { pathNode b = toNodes[t]; //PREFORM A - > B TESTING HERE //testing distance between nodes if (Mathf.Abs(a.pos.y - b.pos.y) < blockSize * 0.7 && Vector3.Distance(a.pos, b.pos) < distanceBetween) { //testing collision between nodes if (!Physics2D.Linecast(a.pos, b.pos, groundLayer)) { a.neighbours.Add(b); } } //END TESTING } } }
public static void bakePathNode(pathNode node) { List <pathNode> bakes = new List <pathNode>(); foreach (pathNode newNode in _nodes) { if (newNode == node) { continue; //No unneccesary trace } if (newNode.location.DistanceTo(node.location) > 2000) { continue; //Don't trace for too far away points } bool trace = GSCFunctions.SightTracePassed(node.location + new Vector3(0, 0, 5), newNode.location + new Vector3(0, 0, 5), false); if (trace) { bakes.Add(newNode); } } if (bakes.Count > 0) { node.visibleNodes = bakes; } else { Utilities.PrintToConsole("A pathNode had no visible links! (" + node.location.ToString() + ")"); } }
//Used to remove a node from the graph. Takes care of all references to the node public void DeleteNode(int A) { for (int i = 0; i < graph.Count; i++) { for (int j = 0; j < graph[i].neighbors.Count; j++) { pathNode GraphLoc = graph[i].neighbors[j]; //Remove all instances of the pathNode from all connections in the graph if (GraphLoc.ID == A) { graph[i].neighbors.RemoveAt(j); graph[i].weight.RemoveAt(j); } } } for (int i = 0; i < graph.Count; i++) { //Decrement the ID on each node that occurs AFTER the deleted node. if (graph[i].ID > A) { graph[i].ID -= 1; } } //Finally, remove the Node from the graph. graph.RemoveAt(A); NodeCount--; }
private void LadderNeighbors(List <pathNode> fromNodes, List <pathNode> toNodes, bool includesGround) { float distanceBetween = blockSize + groundMaxWidth; float distanceForGround = blockSize * 0.5f + 0.2f; float maxXDistance = blockSize * 0.501f; for (int i = 0; i < fromNodes.Count; i++) { pathNode a = fromNodes[i]; for (int t = 0; t < toNodes.Count; t++) { pathNode b = toNodes[t]; if (Mathf.Abs(a.pos.x - b.pos.x) < maxXDistance && ((!includesGround && Vector3.Distance(a.pos, b.pos) < distanceBetween) || (includesGround && Vector3.Distance(a.pos, b.pos) < distanceForGround))) { a.neighbours.Add(b); if (debugTools) { Debug.DrawLine(a.pos, b.pos, Color.red); } } } } }
public void freeNode() { if (m_node != null) { m_node.m_refEnemy = null; m_node = null; } }
private void FindJumpNodes(List <pathNode> searchList) { if (jumpHeight > 0) { for (int i = 0; i < searchList.Count; i++) { float curHeight = jumpHeight; while (curHeight >= minimumJump) { Vector3 air = searchList[i].pos; air.y += curHeight; if (!Physics2D.Linecast(searchList[i].pos, air, groundLayer)) { pathNode newJumpNode = new pathNode("jump", air); newJumpNode.spawnedFrom = searchList[i]; //this node has been spawned from a groundNode //jumpNodes.Add(newJumpNode); newJumpNode.c = nodeWeights.GetNodeWeightByString(newJumpNode.type); newJumpNode.height = curHeight; newJumpNode.realHeight = curHeight; nodes.Add(newJumpNode); newJumpNode.spawnedFrom.createdJumpNodes.Add(newJumpNode); } else { float h = curHeight; float minHeight = blockSize * 1f; //2f while (h > minHeight) { Vector3 newHeight = new Vector3(air.x, air.y - (curHeight - h), air.z); if (!Physics2D.Linecast(searchList[i].pos, newHeight, groundLayer)) { pathNode newJumpNode = new pathNode("jump", newHeight); newJumpNode.spawnedFrom = searchList[i]; //this node has been spawned from a groundNode //jumpNodes.Add(newJumpNode); newJumpNode.c = nodeWeights.GetNodeWeightByString(newJumpNode.type); newJumpNode.realHeight = curHeight; newJumpNode.height = h; nodes.Add(newJumpNode); newJumpNode.spawnedFrom.createdJumpNodes.Add(newJumpNode); break; } else { //0.5f h -= blockSize * 0.1f; } } } curHeight -= jumpHeightIncrement; } } } }
private void FindFallNodes(List <pathNode> searchList) { float spacing = blockSize * 0.5f + blockSize * fall_X_Spacing; for (int i = 0; i < searchList.Count; i++) { Vector3 leftNode = searchList[i].pos; leftNode.x -= spacing; Vector3 rightNode = searchList[i].pos; rightNode.x += spacing; //raycheck left if (!Physics2D.Linecast(searchList[i].pos, leftNode, groundLayer)) { Vector3 colliderCheck = leftNode; colliderCheck.y -= fall_Y_GrndDist; //raycheck down if (!Physics2D.Linecast(leftNode, colliderCheck, groundLayer)) { pathNode newFallNode = new pathNode("fall", leftNode); newFallNode.spawnedFrom = searchList[i]; //this node has been spawned from a groundNode //fallNodes.Add(newFallNode); newFallNode.c = nodeWeights.GetNodeWeightByString(newFallNode.type); nodes.Add(newFallNode); newFallNode.spawnedFrom.createdFallNodes.Add(newFallNode); //Debug.DrawLine(nodes[i].pos, temp.pos, Color.red); //climbNodes("right", nodes[i]); } } //raycheck right if (!Physics2D.Linecast(searchList[i].pos, rightNode, groundLayer)) { Vector3 colliderCheck = rightNode; colliderCheck.y -= fall_Y_GrndDist; //raycheck down if (!Physics2D.Linecast(rightNode, colliderCheck, groundLayer)) { pathNode newFallNode = new pathNode("fall", rightNode); newFallNode.spawnedFrom = searchList[i]; //this node has been spawned from a groundNode //fallNodes.Add(newFallNode); newFallNode.c = nodeWeights.GetNodeWeightByString(newFallNode.type); nodes.Add(newFallNode); newFallNode.spawnedFrom.createdFallNodes.Add(newFallNode); //Debug.DrawLine(nodes[i].pos, temp.pos, Color.red); //climbNodes("right", nodes[i]); } } } }
public pathNode(Transform node, pathNode nextNode, bool fastMove, int col, int row) { m_fastMove = fastMove; m_nextNode = nextNode; m_nodeTransform = node; //m_inUse = false; m_col = col; m_row = row; m_refEnemy = null; }
private void FallNeighbors(List <pathNode> fromNodes, List <pathNode> toNodes) { for (int i = 0; i < fromNodes.Count; i++) { pathNode a = fromNodes[i]; for (int t = 0; t < toNodes.Count; t++) { pathNode b = toNodes[t]; //PREFORM A - > B TESTING HERE float xDistance = Mathf.Abs(a.pos.x - b.pos.x); a.spawnedFrom.neighbours.Add(a); if ((xDistance < blockSize * 1f + groundMaxWidth && a.pos.y > b.pos.y) || (a.pos.y - b.pos.y > Mathf.Abs(a.pos.x - b.pos.x) * 2.2f + blockSize * 1f && //2.2 + blocksize * 1f xDistance < blockSize * 4f)) { if (!Physics2D.Linecast(a.pos, b.pos, groundLayer)) { bool hitTest = true; float middle = -(a.pos.x - b.pos.x) * 0.5f; float quarter = middle / 2f; float reduceY = Mathf.Abs(a.pos.y - b.pos.y) > blockSize * 4f ? blockSize * 1.3f : 0f; Vector3 middlePointDrop = new Vector3(a.pos.x + middle, a.pos.y - reduceY, a.pos.z); Vector3 quarterPointTop = new Vector3(a.pos.x + quarter, a.pos.y, a.pos.z); Vector3 quarterPointBot = new Vector3(b.pos.x - quarter, b.pos.y, b.pos.z); Vector3 corner = new Vector3(b.pos.x, (a.pos.y - blockSize * xDistance - blockSize * 0.5f) - groundNodeHeight, a.pos.z); //Debug.DrawLine(middlePointDrop, b.pos, Color.yellow); //Debug.DrawLine (quarterPointTop, b.pos, Color.yellow); //Debug.DrawLine (quarterPointBot, a.pos, Color.yellow); //Debug.DrawLine (corner, b.pos, Color.yellow); if (Physics2D.Linecast(quarterPointTop, b.pos, groundLayer) || Physics2D.Linecast(middlePointDrop, b.pos, groundLayer) || a.pos.y > b.pos.y + blockSize + groundNodeHeight && Physics2D.Linecast(corner, b.pos, groundLayer) || Physics2D.Linecast(quarterPointBot, a.pos, groundLayer)) { hitTest = false; } if (hitTest) { a.neighbours.Add(b); } } } //END TESTING } } }
//Not meant for real-time use public void ConstructGraph() { if (meshGraph == null) { Debug.Log("No mesh to operate on! Please set meshGraph before calling this function"); return; } //Create a sampler Gameobject to perform raycasts to neighboring nodes Sampler = new GameObject("Sampler"); List <int> neighbors; List <int> DeadVertices = new List <int>(); List <pathNode> DeadNodes = new List <pathNode>(); simpleGraph = new GraphSimple(); simpleGraph.AddNodes(meshGraph.vertexCount); float dist = 0; for (int i = 0; i < meshGraph.vertexCount; i++) { //if(DeadVertices.Contains(i)) //continue; neighbors = GetNeighbors(i); pathNode currentNode = simpleGraph.graph[i]; currentNode.position = transform.TransformPoint(meshGraph.vertices[i]); for (int j = 0; j < neighbors.Count; j++) { dist = Vector3.Distance(transform.TransformPoint(meshGraph.vertices[i]), transform.TransformPoint(meshGraph.vertices[neighbors[j]])); currentNode.neighbors.Add(simpleGraph.graph[neighbors[j]]); currentNode.weight.Add(dist); Sampler.transform.position = transform.TransformPoint(meshGraph.vertices[i]); if (Physics.Raycast(Sampler.transform.position, Vector3.Normalize(meshGraph.vertices[neighbors[j]] - meshGraph.vertices[i]), dist)) { if (!DeadVertices.Contains(neighbors[j])) { DeadVertices.Add(neighbors[j]); DeadNodes.Add(simpleGraph.graph[neighbors[j]]); break; } } } //Debug.Log(i); } foreach (pathNode node in DeadNodes) { simpleGraph.DeleteNode(node.ID); } //Rebuild mesh NavMeshGenerator.RemoveTriangles(meshGraph, DeadVertices); }
private void FindLadderNodes(List <GameObject> objects) { for (int i = 0; i < objects.Count; i++) { Vector3 ladder = objects[i].transform.position; pathNode newLadderNode = new pathNode(EPathNodeType.climb, ladder); ladderNodes.Add(newLadderNode); newLadderNode.c = nodeWeights.GetNodeWeightByString(newLadderNode.type); nodes.Add(newLadderNode); } }
private static List <pathNode> getPath(pathNode Destination) { pathNode CurrentNode = Destination; List <pathNode> Path = new List <pathNode>(); Path.Add(CurrentNode); do { CurrentNode = CurrentNode.previous; Path.Insert(0, CurrentNode); }while(CurrentNode.previous != null); return(Path); }
public void LinkGraph(GraphSimple linkedGraph, int NodePos, pathNode Link) { foreach (GraphSimple link in NeighborGraphs) { if (link == linkedGraph) { return; } } NeighborGraphs.Add(linkedGraph); TransitionNodes.Add(NodePos); Links.Add(Link); }
public pathNode getClosestNode(Vector3 pos) { float dis = 999999999; pathNode closest = null; foreach (pathNode p in _nodes) { if (p.location.DistanceTo2D(pos) < dis) { closest = p; } } return(closest); }
private void FindOnewayNodes(List <GameObject> objects) { for (int i = 0; i < objects.Count; i++) { Vector3 ground = objects[i].transform.position; ground.y += blockSize * 0.5f + blockSize * groundNodeHeight; pathNode newGroundNode = new pathNode("walkable", ground); groundNodes.Add(newGroundNode); newGroundNode.c = nodeWeights.GetNodeWeightByString(newGroundNode.type); nodes.Add(newGroundNode); newGroundNode.gameObject = objects[i]; } }
private void FindPortalNodes(List <GameObject> objects) { for (int i = 0; i < objects.Count; i++) { Vector3 portal = objects[i].transform.position; //ground.y += blockSize * 0.5f + blockSize * groundNodeHeight; pathNode newPortalNode = new pathNode(EPathNodeType.portal, portal); newPortalNode.gameObject = objects[i]; portalNodes.Add(newPortalNode); newPortalNode.c = nodeWeights.GetNodeWeightByString(newPortalNode.type); nodes.Add(newPortalNode); } }
//Create pathNode for sparse graph public void ConnectGraphs(int GraphIDA, int GraphNodeA, int GraphIDB, int GraphNodeB) { sparseGraph.AddNodes(1); pathNode linker = sparseGraph.GetNodeList()[sparseGraph.NodeCount - 1]; //Place linker node over doorway linker.position = Graphs[GraphIDA].GetNodeList()[GraphNodeA].position; //Link A to B Graphs[GraphIDA].LinkGraph(Graphs[GraphIDB], GraphNodeA, linker); //Link B to A Graphs[GraphIDB].LinkGraph(Graphs[GraphIDA], GraphNodeB, linker); }
public pathNode getClosestPathNodeToEndNode(pathNode node) { float dis = 999999999; pathNode closest = this; foreach (pathNode p in node.visibleNodes) { if (p.location.DistanceTo2D(location) < dis) { closest = p; } } return(closest); }
void SpawnNodes() { for (int i = 0; i < 4; i++) { newNode = Instantiate (nodePrefab, GetSpawnPos (), Quaternion.identity) as pathNode; //newNode.angleDegrees = angleDegrees; newNode.transform.LookAt (transform.position); Vector3 heading = newNode.transform.position - transform.position; distance = heading.magnitude; SpawnPath(); /*Vector3 direction = heading / distance; Debug.Log (distance); Debug.Log (direction); Debug.Log (heading);*/ } }
public List <pathNode> getPathToNode(pathNode node) { List <pathNode> path = new List <pathNode>(); //End = node float currentDistance = 999999; pathNode currentNode = node; while (currentDistance > 256)//Risky business... { currentNode = currentNode.getClosestPathNodeToEndNode(this); currentDistance = location.DistanceTo2D(currentNode.location); path.Add(currentNode); } return(path); }
// Update is called once per frame void Update() { if (!pathReady && !pathBlocked && buildPath) { // Set first node to be our starting node if (currentPath.Count == 0) { var newNode = new pathNode(); newNode.position = startingTile; currentPath.Add(newNode); } searchForNextTile(); } }
bool tryTilePosition2() { var newNode = new pathNode(); newNode.position = currentPath[currentPath.Count - 1].position; newNode.position.x += 1; if (towerLevelMap.GetTile(newNode.position) != null) { // Tower exists on this tile // Set prev node side blocked currentPath[currentPath.Count - 1].sidesBlocked |= side2Blocked; #if DEBUG_PATH_GEN Debug.Log("Tower exists on this tile. sidesBlocked=" + currentPath[currentPath.Count - 1].sidesBlocked); #endif } else if (pathLevelMap.GetTile(newNode.position) != null) { // Path already exists on this tile // Set prev node side blocked currentPath[currentPath.Count - 1].sidesBlocked |= side2Blocked; } else { if (checkForTargetTile(newNode.position)) { return(false); } // Block new node form backtracking newNode.sidesBlocked |= side5Blocked; // New Node position is available, place tile pathLevelMap.SetTile(newNode.position, pathTile); newNode.pathTilePlaced = true; // Add new node to list currentPath.Add(newNode); return(true); } return(false); }
public pathNode GetClosestNode(Vector3 position) { float distance = Mathf.Infinity; pathNode ClosestNode = new pathNode(); foreach (pathNode Node in graph) { float currDist = Vector3.Distance(Node.position, position); if (distance > currDist) { distance = currDist; ClosestNode = Node; } } return(ClosestNode); }
private void PortalNeighbors(List <pathNode> fromNodes, List <pathNode> toNodes, bool onlyPortals) { float distanceForGround = blockSize * 1.5f + 0.1f; float maxXDistance = blockSize * 1f; for (int i = 0; i < fromNodes.Count; i++) { pathNode a = fromNodes[i]; if (a.gameObject) { //GameObject aCheck = a.gameObject.transform.GetComponent<Portal>().connectedTo; //if (aCheck != null) //{ // for (int t = 0; t < toNodes.Count; t++) // { // pathNode b = toNodes[t]; // if (onlyPortals) // { // if (aCheck == b.gameObject) // { // a.neighbours.Add(b); // if (debugTools) // { // Debug.DrawLine(a.pos, b.pos, Color.cyan); // } // } // } // else // { // if (Mathf.Abs(a.pos.x - b.pos.x) < maxXDistance && // Vector3.Distance(a.pos, b.pos) < distanceForGround) // { // a.neighbours.Add(b); // b.neighbours.Add(a); // if (debugTools) // { // Debug.DrawLine(a.pos, b.pos, Color.cyan); // } // } // } // } //} } } }
private pathNode getNearestLadderNode(Vector3 obj) { float dist = float.MaxValue; pathNode node = null; for (int i = 0; i < ladderNodes.Count; i++) { if (ladderNodes[i].neighbours.Count > 0) { float temp = Vector3.Distance(obj, (Vector3)ladderNodes[i].pos); if (dist > temp && Mathf.Abs(obj.x - ladderNodes[i].pos.x) < blockSize) { dist = temp; node = ladderNodes[i]; } } } return(node); }
// Update is called once per frame void Update() { if (currentNode != null && followTrigger == true) { setRotation(Quaternion.RotateTowards( this.getRotation(), currentNode.getRotation(), stepSpeed(currentNode.getRotationSpeed()) )); setPosition(Vector3.MoveTowards( this.getPosition(), currentNode.getPosition(), stepSpeed(currentNode.getSpeed()) )); if (Vector3.Distance(this.getPosition(), currentNode.getPosition()) < threshold) { currentNode = currentNode.getNextNode(); } } }
//Used for runtime adding terrain block to pathfinding nodes public void CreateBlockCalled(Vector3 position) { GameObject newGameObject = (GameObject)Instantiate(Resources.Load("Tiles/GroundTile"), new Vector3(position.x, position.y, 0.0f), Quaternion.identity) as GameObject; newGameObject.GetComponent <SpriteRenderer>().sprite = Resources.Load("Sprites/ground2", typeof(Sprite)) as Sprite; //add the ground node, Vector3 ground = newGameObject.transform.position; ground.y += blockSize * 0.5f + blockSize * groundNodeHeight; pathNode newGroundNode = new pathNode("walkable", ground); groundNodes.Add(newGroundNode); newGroundNode.c = nodeWeights.GetNodeWeightByString(newGroundNode.type); nodes.Add(newGroundNode); newGroundNode.gameObject = newGameObject; //run it through the list RefreshAreaAroundBlock(newGameObject, false); }
void Start() { int index = transform.GetSiblingIndex(); if (index == 0) { previousNode = null; } else { previousNode = transform.parent.GetChild(index - 1).GetComponent <pathNode>(); } if (index >= (transform.parent.childCount - 1)) { nextNode = null; } else { nextNode = transform.parent.GetChild(index + 1).GetComponent <pathNode>(); } }
//get nearest node ground. Useful for finding start and end points of the path private pathNode getNearestNode(Vector3 obj) { float dist = float.MaxValue; pathNode node = null; for (int i = 0; i < _groundNodes.Count; i++) { if (_groundNodes[i].neighbours.Count > 0 && obj.y > _groundNodes[i].pos.y && Mathf.Abs(obj.x - _groundNodes[i].pos.x) < blockSize && /*only find ground nodes that are within 4f*/ obj.y - _groundNodes[i].pos.y < 10000f) { Debug.Log("testino"); float temp = Vector3.Distance(obj, (Vector3)_groundNodes[i].pos); if (dist > temp) { Debug.Log("nodeset"); dist = temp; node = _groundNodes[i]; } } } return(node); }
//This function removes the outermost nodes from any future path-generation functions //This is useful if we have the outer nodes look for nodes to connect to //However, since the startCastleNodes are the only ones looking for connections, it's useless now void CleanUpNodes() { pathNode rightMostNode = new pathNode(); pathNode leftMostNode = new pathNode(); pathNode topMostNode = new pathNode (); pathNode bottomMostNode = new pathNode (); rightMostNode.transform.position = new Vector3 (-100, 0, 0); leftMostNode.transform.position = new Vector3 (100, 0, 0); topMostNode.transform.position = new Vector3 (0, 0, -100); bottomMostNode.transform.position = new Vector3 (0, 0, 100); foreach (pathNode castlePathNode in castlePathNodes) { if(castlePathNode.transform.position.x > rightMostNode.transform.position.x){ rightMostNode = castlePathNode; } if(castlePathNode.transform.position.x < leftMostNode.transform.position.x){ leftMostNode = castlePathNode; } if(castlePathNode.transform.position.z > topMostNode.transform.position.z){ topMostNode = castlePathNode; } if(castlePathNode.transform.position.z < bottomMostNode.transform.position.z){ bottomMostNode = castlePathNode; } } Destroy (rightMostNode.castlePath); castlePathNodes.Remove (rightMostNode); Destroy (rightMostNode); Destroy (leftMostNode.castlePath); castlePathNodes.Remove (leftMostNode); Destroy (leftMostNode); Destroy (topMostNode.castlePath); castlePathNodes.Remove (topMostNode); Destroy (topMostNode); Destroy (bottomMostNode.castlePath); castlePathNodes.Remove (bottomMostNode); Destroy (bottomMostNode); }
public void calcMoves() //Djikstra's Algorithm based calculation of available moves { List <pathNode> nNodes = new List <pathNode>(); //new nodes to be checked. Not guaranteed to have best route, yet. List <pathNode> fNodes = new List <pathNode>(); //Nodes added once they are they shortest new route and have had children checked. nNodes.Add(new pathNode()); //Start by adding current node to seed (but not as valid. Nodes valid = false by default) nNodes [0].x = gridX; nNodes [0].y = gridY; nNodes [0].rMoves = 0; //Vars for wgile loop. int cNode; int cMoves; int tx; int ty; bool found = false; pathNode nNode; while (nNodes.Count != 0) //I.e. while there are still new nodes to check { cNode = 0; //Prime each loop to prevent unnecessary carryover cMoves = 99999999; for (int i = 0; i < nNodes.Count; i++) //Find the lowest number with fewest moves in new nodes { if (nNodes [i].rMoves < cMoves) { cNode = i; cMoves = nNodes [i].rMoves; } } //This could possibly be broken down into a function repeated four times with the invdividual adjacent tiles. C/P'ed for now due to laziness and scope. //Technically runs inconsequentially and imperceptibly faster than a function call. Behaviour undefined if pawn is not in valid grid. //Test Top tx = nNodes[cNode].x; ty = nNodes[cNode].y + 1; if (ty < grid.Height() && // Not Outside Grid (((grid [tx, ty].restricted & moveType) ^ moveType) != 0) && //Has an active movetype that can occupy tile (cMoves < moveSpeed) && //movespeed won't be exceeded ((grid [tx, ty].occupied | team) == team) && //Tile is not occupied by a different team (((grid [tx, ty].slow & moveType) == 0) || //Movetype won't cause slowness, or (cMoves + 1 < moveSpeed))) //Have enough remaining move to enter slow tile { nNode = new pathNode(); nNode.x = tx; nNode.y = ty; nNode.rMoves = cMoves + 1; nNode.prev = nNodes [cNode]; if (grid [tx, ty].occupied == 0) //if completely empty, can move to here. Otherwise, just through here. { nNode.valid = true; } if ((grid [tx, ty].slow & moveType) != 0) //account for slow movement { ++nNode.rMoves; } //Check if node already exists found = false; for (int i = 0; i < fNodes.Count && !found; i++) { if (fNodes [i].x == tx && fNodes[i].y == ty) //Don't add if already in { found = true; //If found in this list, required moves must be <= current moves, so no need to try harder. } } for (int i = 0; i < nNodes.Count && !found; i++) { if (nNodes [i].x == tx && nNodes[i].y == ty) //Don't add if already in { found = true; if (nNodes [i].rMoves > nNode.rMoves) //Make sure shortest path is used { nNodes [i].rMoves = nNode.rMoves; nNodes [i].prev = nNode.prev; } } } if (!found) { nNodes.Add(nNode); } } //Test Bottom tx = nNodes[cNode].x; ty = nNodes[cNode].y - 1; if (ty > 0 && // Not Outside Grid (((grid [tx, ty].restricted & moveType) ^ moveType) != 0) && //Has an active movetype that can occupy tile (cMoves < moveSpeed) && //movespeed won't be exceeded ((grid [tx, ty].occupied | team) == team) && //Tile is not occupied by a different team (((grid [tx, ty].slow & moveType) == 0) || //Movetype won't cause slowness, or (cMoves + 1 < moveSpeed))) //Have enough remaining move to enter slow tile { nNode = new pathNode(); nNode.x = tx; nNode.y = ty; nNode.rMoves = cMoves + 1; nNode.prev = nNodes [cNode]; if (grid [tx, ty].occupied == 0) //if completely empty, can move to here. Otherwise, just through here. { nNode.valid = true; } if ((grid [tx, ty].slow & moveType) != 0) //account for slow movement { ++nNode.rMoves; } //Check if node already exists found = false; for (int i = 0; i < fNodes.Count && !found; i++) { if (fNodes [i].x == tx && fNodes[i].y == ty) //Don't add if already in { found = true; //If found in this list, required moves must be <= current moves, so no need to try harder. } } for (int i = 0; i < nNodes.Count && !found; i++) { if (nNodes [i].x == tx && nNodes[i].y == ty) //Don't add if already in { found = true; if (nNodes [i].rMoves > nNode.rMoves) //Make sure shortest path is used { nNodes [i].rMoves = nNode.rMoves; nNodes [i].prev = nNode.prev; } } } if (!found) { nNodes.Add(nNode); } } //Test Left tx = nNodes[cNode].x - 1; ty = nNodes[cNode].y; if (tx > 0 && // Not Outside Grid (((grid [tx, ty].restricted & moveType) ^ moveType) != 0) && //Has an active movetype that can occupy tile (cMoves < moveSpeed) && //movespeed won't be exceeded ((grid [tx, ty].occupied | team) == team) && //Tile is not occupied by a different team (((grid [tx, ty].slow & moveType) == 0) || //Movetype won't cause slowness, or (cMoves + 1 < moveSpeed))) //Have enough remaining move to enter slow tile { nNode = new pathNode(); nNode.x = tx; nNode.y = ty; nNode.rMoves = cMoves + 1; nNode.prev = nNodes [cNode]; if (grid [tx, ty].occupied == 0) //if completely empty, can move to here. Otherwise, just through here. { nNode.valid = true; } if ((grid [tx, ty].slow & moveType) != 0) //account for slow movement { ++nNode.rMoves; } //Check if node already exists found = false; for (int i = 0; i < fNodes.Count && !found; i++) { if (fNodes [i].x == tx && fNodes[i].y == ty) //Don't add if already in { found = true; //If found in this list, required moves must be <= current moves, so no need to try harder. } } for (int i = 0; i < nNodes.Count && !found; i++) { if (nNodes [i].x == tx && nNodes[i].y == ty) //Don't add if already in { found = true; if (nNodes [i].rMoves > nNode.rMoves) //Make sure shortest path is used { nNodes [i].rMoves = nNode.rMoves; nNodes [i].prev = nNode.prev; } } } if (!found) { nNodes.Add(nNode); } } //Test Right tx = nNodes[cNode].x + 1; ty = nNodes[cNode].y; if (tx < grid.Width() && // Not Outside Grid (((grid [tx, ty].restricted & moveType) ^ moveType) != 0) && //Has an active movetype that can occupy tile (cMoves < moveSpeed) && //movespeed won't be exceeded ((grid [tx, ty].occupied | team) == team) && //Tile is not occupied by a different team (((grid [tx, ty].slow & moveType) == 0) || //Movetype won't cause slowness, or (cMoves + 1 < moveSpeed))) //Have enough remaining move to enter slow tile { nNode = new pathNode(); nNode.x = tx; nNode.y = ty; nNode.rMoves = cMoves + 1; nNode.prev = nNodes [cNode]; if (grid [tx, ty].occupied == 0) //if completely empty, can move to here. Otherwise, just through here. { nNode.valid = true; } if ((grid [tx, ty].slow & moveType) != 0) //account for slow movement { ++nNode.rMoves; } //Check if node already exists found = false; for (int i = 0; i < fNodes.Count && !found; i++) { if (fNodes [i].x == tx && fNodes[i].y == ty) //Don't add if already in { found = true; //If found in this list, required moves must be <= current moves, so no need to try harder. } } for (int i = 0; i < nNodes.Count && !found; i++) { if (nNodes [i].x == tx && nNodes[i].y == ty) //Don't add if already in { found = true; if (nNodes [i].rMoves > nNode.rMoves) //Make sure shortest path is used { nNodes [i].rMoves = nNode.rMoves; nNodes [i].prev = nNode.prev; } } } if (!found) { nNodes.Add(nNode); } } //This Tile is finished. fNodes.Add(nNodes[cNode]); nNodes.RemoveAt(cNode); } if (ValidMoves != null) //Delete old stuff if it exists, for memory purposes. { ValidMoves.Clear(); } ValidMoves = fNodes; foreach (pathNode i in ValidMoves) //Debug string to list all valid moves and some info on completion. { Debug.Log(i.x + "," + i.y + " can move: " + i.valid + ". Requires " + i.rMoves + " Moves."); } }
//Faster Method public void BuildPlaneGraph(float width, float height, int segments) { this.width = width; this.height = height; simpleGraph = new GraphSimple(); List <int> Neighbors = new List <int>(); List <float> Weights = new List <float>(); float deltaHeight = height / segments; float deltaWidth = width / segments; //transform.TransformPoint(new Vector3(j*(width/segments)-width/2, 0, i*(height/segments)-height/2)); simpleGraph.AddNodes((segments + 1) * (segments + 1)); List <pathNode> DeadNodes = new List <pathNode>(); List <int> DeadVerts = new List <int>(); pathNode currentNode; for (int i = 0; i <= segments; i++) { for (int j = 0; j <= segments; j++) { currentNode = simpleGraph.GetNodeList()[i * (segments + 1) + j]; currentNode.position = transform.TransformPoint(new Vector3(j * (deltaWidth) - width / 2, 0, i * (deltaHeight) - height / 2)); //RaycastHit hit; //if (Physics.Raycast(currentNode.position, -Vector3.up, out hit)) //{ // currentNode.position=transform.TransformPoint(new Vector3(j*(deltaWidth)-width/2, hit.point.y, i*(deltaHeight)-height/2)); //} Neighbors.Clear(); Weights.Clear(); //Debug.Log ("Node #"+(i*(segments+1)+j)); //Up and Down if (i > 0) { Neighbors.Add(((i - 1) * (segments + 1) + (j))); Weights.Add(deltaHeight); //Debug.Log ("Down"); } if (i < segments) { Neighbors.Add(((i + 1) * (segments + 1) + (j))); Weights.Add(deltaHeight); //Debug.Log ("Up"); } //Left and Right if (j > 0) { Neighbors.Add(((i) * (segments + 1) + (j - 1))); Weights.Add(deltaWidth); //Debug.Log ("Left"); } if (j < segments) { Neighbors.Add(((i) * (segments + 1) + (j + 1))); Weights.Add(deltaWidth); //Debug.Log ("Right"); } //Top-left to Bottom-right Diagonal if (i > 0 && j > 0) { Neighbors.Add((i - 1) * (segments + 1) + (j - 1)); Weights.Add(Mathf.Sqrt(deltaWidth * deltaWidth + deltaHeight * deltaHeight)); //Debug.Log ("Bottom Left"); } if (i < segments && j < segments) { Neighbors.Add((i + 1) * (segments + 1) + (j + 1)); Weights.Add(Mathf.Sqrt(deltaWidth * deltaWidth + deltaHeight * deltaHeight)); //Debug.Log ("Top right"); } //Top-right to Bottom-left Diagonal if ((i < segments) && j > 0) { Neighbors.Add(((i + 1) * (segments + 1) + (j - 1))); Weights.Add(Mathf.Sqrt(deltaWidth * deltaWidth + deltaHeight * deltaHeight)); //Debug.Log ("Top left"); } if (i > 0 && j < segments) { Neighbors.Add((i - 1) * (segments + 1) + (j + 1)); Weights.Add(Mathf.Sqrt(deltaWidth * deltaWidth + deltaHeight * deltaHeight)); //Debug.Log ("Bottom Right"); } int index = 0; foreach (int Neighbor in Neighbors) { //Debug.Log (Neighbor); pathNode neighbor = simpleGraph.GetNodeList()[Neighbor]; currentNode.neighbors.Add(neighbor); currentNode.weight.Add(Weights[index]); index++; } //Debug.Log(i); } } foreach (pathNode node in simpleGraph.GetNodeList()) { node.dist = 0; } //Scan physics graph foreach (pathNode node in simpleGraph.GetNodeList()) { //Debug.Log (node.neighbors.Count); for (int i = 0; i < node.neighbors.Count; i++) { pathNode Neighbor = node.neighbors[i]; //Debug.Log ("Ray cast from "+node.position+" to "+Neighbor.position+" with a distance of "+Vector3.Distance(Neighbor.position,node.position)); //Debug.Log ("Node #"+node.ID+" Hit toward: "+Neighbor.ID); if (Physics.Raycast(node.position, Vector3.Normalize(Neighbor.position - node.position), Vector3.Distance(Neighbor.position, node.position))) { //Debug.DrawLine(Neighbor.position,node.position); if (!Physics.Raycast(node.position, Vector3.Normalize(node.position - Neighbor.position), Vector3.Distance(Neighbor.position, node.position))) { if (DeadVerts.Contains(Neighbor.ID)) { DeadNodes.Add(Neighbor); DeadVerts.Add(Neighbor.ID); } } //removeCount++; node.neighbors.RemoveAt(i); node.weight.RemoveAt(i); i--; Neighbor.dist += 1; } } } //Dead Node Removal for (int i = 0; i < DeadNodes.Count; i++) { //Debug.Log (DeadNodes[i]); simpleGraph.DeleteNode(DeadNodes[i].ID); } //Filter nodes Remove count for (int i = 0; i < simpleGraph.NodeCount; i++) { pathNode node = simpleGraph.GetNodeList()[i]; //Debug.Log("Hit count: "+node.dist); if (node.dist >= 3) { simpleGraph.DeleteNode(node.ID); i--; } } for (int i = 0; i < simpleGraph.NodeCount; i++) { pathNode node = simpleGraph.GetNodeList()[i]; if (node.neighbors.Count < 3) { simpleGraph.DeleteNode(node.ID); } } }
//End Spawning node stuff //Start Spawning each castle's paths stuff void SpawnCastlePath(pathNode castlePathNode) { float pathLength = 10f; Vector3 spawnPos = castlePathNode.transform.position + castlePathNode.transform.forward * pathLength / 2; GameObject newCastlePath = Instantiate (castlePathPrefab, spawnPos, Quaternion.identity) as GameObject; newCastlePath.transform.localScale = new Vector3 (newCastlePath.transform.localScale.x, newCastlePath.transform.localScale.y, pathLength); newCastlePath.transform.rotation = castlePathNode.transform.rotation; castlePathNode.castlePath = newCastlePath; //newCastlePath.transform.parent = castlePathNode.transform; }
public void moveToNextNode() { m_node.m_refEnemy = null; m_node = m_node.m_nextNode; m_node.m_refEnemy = this; }
private void buildPathPanel() { m_columns = new pathColumn[NUM_COLS]; for (int colIndex = 0; colIndex < NUM_COLS; colIndex++) { pathNode[] nodes = new pathNode[NUM_ROWS]; for (int rowIndex = 0; rowIndex < NUM_ROWS; rowIndex++) { Transform nodeTrans = GetComponent<Transform>().Find("pathCol" + colIndex + "Row" + rowIndex); pathNode nextNode = (rowIndex !=0)?nodes[rowIndex-1]: null; nodes[rowIndex] = new pathNode(nodeTrans, nextNode, rowIndex >= FAST_MOVE_ROW, colIndex, rowIndex); } m_columns[colIndex] = new pathColumn(nodes); } }
public void reset() { m_node = null; m_enemyView = null; m_updateTime = float.MaxValue; m_hitEffect = BeltItem.EffectTypeEnum.ETE_NORMAL; }
public pathColumn(pathNode[] nodes) { m_nodes = nodes; }
public void setNodeAndView(pathNode node, EnemyView enemyView) { m_node = node; node.m_refEnemy = this; m_enemyView = enemyView; m_enemyView.showEffectBG(true); }