public static int ClosestExceptCurrentNode(List <PathNode> inNodes, PathNode currentNode) { Vector3 toPoint = currentNode.transform.position; int closestIndex = 0; float minDist = float.MaxValue; for (int i = 0; i < inNodes.Count; i++) { if (AStarScript.Invalid(inNodes[i]) || currentNode == inNodes[i] || inNodes[i].Connections.Count == 0) { continue; } float thisDist = Vector3.Distance(toPoint, inNodes[i].Position); if (thisDist > minDist) { continue; } minDist = thisDist; closestIndex = i; } return(closestIndex); }
public void DisableNode(Vector3 position) { int nodeToDisableIndex = Closest(hexaNodeList, position); PathNode nodeToDisable = hexaNodeList[nodeToDisableIndex]; List <PathNode> oldPathNode = new List <PathNode>(); for (int i = 0; i < nodeToDisable.Connections.Count; i++) { oldPathNode.Add(nodeToDisable.Connections[i]); } //Disconnect all link from neighbour nodes to current node for (int i = 0; i < nodeToDisable.Connections.Count; i++) { PathNode neighbourNode = nodeToDisable.Connections[i]; for (int j = 0; j < neighbourNode.Connections.Count; j++) { if (neighbourNode.Connections[j] == nodeToDisable) { neighbourNode.Connections.Remove(nodeToDisable); j--; } } } //Disconnect all link from current node to neighhour nodes nodeToDisable.Connections.Clear(); GameObject[] enemyList = GameObject.FindGameObjectsWithTag("Enemy"); for (int i = 0; i < enemyList.Length; ++i) { Enemy enemyScript = enemyList[i].GetComponent <Enemy>(); // If there where any nodes to be disabled // Enemies are force to go to the next node if (enemyScript.solvedPath[enemyScript.mPathIndex] == nodeToDisable) { enemyScript.mForceGoToNext = true; enemyScript.solvedPath = AStarScript.Calculate(ShortestNextPathNodeFromNeighbour(oldPathNode), hexaNodeList[Closest(hexaNodeList, spawnManager.targetPosition)]); } else { enemyScript.solvedPath = AStarScript.Calculate(enemyScript.solvedPath[enemyScript.mPathIndex], hexaNodeList[Closest(hexaNodeList, spawnManager.targetPosition)]); } enemyScript.mPathIndex = 0; } Array.Clear(enemyList, 0, enemyList.Length); }
void OnMouseDown() { Debug.Log("Clicked on " + position.x + ", " + position.y); if (WallToggle.isOn) { setWall(); } else if (StartToggle.isOn) { setStart(); } else if (EndToggle.isOn) { setEnd(); } if (start != null && end != null) { mapScript.resetGrid(); StartCoroutine(AStarScript.findPath()); } }
public PathNode ShortestNextPathNodeFromNeighbour(List <PathNode> currentNode) { int chosenNeighbourIndex = 0; int shortestPathValue = 100000; List <PathNode> shortestPath; for (int i = 0; i < currentNode.Count; i++) { shortestPath = AStarScript.Calculate(currentNode[i], hexaNodeList[Closest(hexaNodeList, spawnManager.targetPosition)]); int tempPathValue = 1000000; if (shortestPath != null) { tempPathValue = shortestPath.Count; } if (tempPathValue < shortestPathValue) { shortestPathValue = tempPathValue; chosenNeighbourIndex = i; } } return(currentNode[chosenNeighbourIndex]); }
public static int Closest(List <PathNode> inNodes, Vector3 toPoint) { int closestIndex = 0; float minDist = float.MaxValue; for (int i = 0; i < inNodes.Count; i++) { if (AStarScript.Invalid(inNodes[i])) { continue; } float thisDist = Vector3.Distance(toPoint, inNodes[i].Position); if (thisDist > minDist) { continue; } minDist = thisDist; closestIndex = i; } return(closestIndex); }
public bool CheckPathExist(Vector3 position) { int nodeToDisableIndex = Closest(hexaNodeList, position); PathNode nodeToDisable = hexaNodeList[nodeToDisableIndex]; List <PathNode> oldPathNode = new List <PathNode>(); if (position == spawnManager.targetPosition || position == spawnManager.spawnPosition) { return(false); } //Backup neighbour list for (int i = 0; i < nodeToDisable.Connections.Count; i++) { oldPathNode.Add(nodeToDisable.Connections[i]); } //Disconnect all link from current node to neighhour nodes nodeToDisable.Connections.Clear(); //Check if path is valid // Allow tower to be built if valid // Don't allow tower to be built if invalid List <PathNode> testPath = (List <PathNode>)AStarScript.Calculate(hexaNodeList[Closest(hexaNodeList, GameObject.Find("SpawnManager").GetComponent <SpawnManager>().spawnPosition)], hexaNodeList[Closest(hexaNodeList, GameObject.Find("SpawnManager").GetComponent <SpawnManager>().targetPosition)]); for (int i = 0; i < oldPathNode.Count; ++i) { PathNode tempOldPathNode = oldPathNode[i]; nodeToDisable.Connections.Add(tempOldPathNode); } if (testPath != null) { return(true); } return(false); }
// Update is called once per frame void Update() { if (ingameUI.endPreparation) { preparationTime = false; } // Starts the game when preparation time runs out if (!preparationTime && !disableSpawning) { Level[currentLevel].Wave[currentWave].waveStart = ingameUI.startWave; // Starts the wave if wave is activated if (Level[currentLevel].Wave[currentWave].waveStart) { // If group spawn interval is not zero if (Level[currentLevel].Wave[currentWave].Group[currentGroup].groupSpawnInterval > 0.0f) { // Countdown group spawn interval timer Level[currentLevel].Wave[currentWave].Group[currentGroup].groupSpawnInterval -= Time.deltaTime; } // Starts the group spawning if the group spawning interval is less than zero if (Level[currentLevel].Wave[currentWave].Group[currentGroup].groupSpawnInterval <= 0.0f) { if (dropCoinIndex == -1) { dropCoinIndex = Random.Range(0, Level[currentLevel].Wave[currentWave].Group[currentGroup].spawnAmount); } // Interval between each enemy spawn // Countdown enemy spawn interval timer enemySpawnIntervalTimer -= Time.deltaTime; if (enemySpawnIntervalTimer <= 0.0f && Level[currentLevel].Wave[currentWave].Group[currentGroup].spawnAmount > 0) { // Spawn GameObject tempEnemy = ObjectPool.Instance.instantiate(Level[currentLevel].Wave[currentWave].Group[currentGroup].enemyType, spawnPosition, Quaternion.Euler(new Vector3(0.0f, 0.0f, 0.0f))); Level[currentLevel].Wave[currentWave].Group[currentGroup].spawnAmount -= 1; currentSpawn += 1; tempEnemy.GetComponent <Enemy>().solvedPath = AStarScript.Calculate(gridManager.hexaNodeList[GridManager.Closest(gridManager.hexaNodeList, tempEnemy.transform.position)], gridManager.hexaNodeList[GridManager.Closest(gridManager.hexaNodeList, GameObject.Find("SpawnManager").GetComponent <SpawnManager>().targetPosition)]); // Reset enemy spawn interval timer enemySpawnIntervalTimer = Level[currentLevel].Wave[currentWave].Group[currentGroup].enemySpawnInterval; tempEnemy.GetComponent <Enemy>().tempTokenIndicator = null; if (dropCoinIndex == currentSpawn) { tempEnemy.GetComponent <Enemy>().AddToken(); } } if (Level[currentLevel].Wave[currentWave].Group[currentGroup].spawnAmount <= 0) { currentSpawn = -1; currentGroup++; if (currentGroup == Level[currentLevel].Wave[currentWave].Group.Count) { currentGroup = 0; currentWave++; ingameUI.startWave = false; } if (currentWave >= Level[currentLevel].Wave.Count) { currentGroup = 0; currentWave = 0; disableSpawning = true; } if (!disableSpawning) { dropCoinIndex = Random.Range(0, Level[currentLevel].Wave[currentWave].Group[currentGroup].spawnAmount); } } } } } }
void Awake() { int column = 0; int lastRowInColumn = 0; foreach(Transform rowTransform in transform) { foreach(Transform tileTransform in rowTransform) { TileScript tile = tileTransform.gameObject.GetComponent<TileScript>(); tiles.Add(tile.tileCoordinate,tile); column = (int)tile.tileCoordinate.y; if(lastRowInColumn < (int)tile.tileCoordinate.x) { lastRowInColumn = (int)tile.tileCoordinate.x; } } lastRowInColumn += 1; rowCounts.Insert(column,lastRowInColumn); lastRowInColumn = 0; } aStar = new AStarScript(this); gm = GameObject.Find(ConstantsScript.gameManagerObjectName).GetComponent<GameManagerScript>(); }
// Calculate the A* path public static List <PathNode> Calculate(PathNode start, PathNode goal) { List <PathNode> closedset = new List <PathNode>(); // The set of nodes already evaluated. List <PathNode> openset = new List <PathNode>(); // The set of tentative nodes to be evaluated. openset.Add(start); Dictionary <PathNode, PathNode> came_from = new Dictionary <PathNode, PathNode>(); // The map of navigated nodes. Dictionary <PathNode, float> g_score = new Dictionary <PathNode, float>(); g_score[start] = 0.0f; // Cost from start along best known path. Dictionary <PathNode, float> h_score = new Dictionary <PathNode, float>(); h_score[start] = HeuristicCostEstimate(start, goal); Dictionary <PathNode, float> f_score = new Dictionary <PathNode, float>(); f_score[start] = h_score[start]; // Estimated total cost from start to goal through y. while (openset.Count != 0) { PathNode x = LowestScore(openset, f_score); if (x.Equals(goal)) { List <PathNode> result = new List <PathNode>(); ReconstructPath(came_from, x, ref result); return(result); } openset.Remove(x); closedset.Add(x); foreach (PathNode y in x.Connections) { if (AStarScript.Invalid(y) || closedset.Contains(y)) { continue; } float tentative_g_score = g_score[x] + Distance(x, y); bool tentative_is_better = false; if (!openset.Contains(y)) { openset.Add(y); tentative_is_better = true; } else if (tentative_g_score < g_score[y]) { tentative_is_better = true; } if (tentative_is_better) { came_from[y] = x; g_score[y] = tentative_g_score; h_score[y] = HeuristicCostEstimate(y, goal); f_score[y] = g_score[y] + h_score[y]; } } } return(null); }
//Finally the method which initialises and positions all the tiles void CreateGrid() { //Game object which is the parent of all the hex tiles GameObject hexGridGO = new GameObject("HexGrid"); GameObject hexGridNode = new GameObject("HexGridNode"); float width = 0.0f; float height = 0.0f; for (int y = 0; y < gridHeightInHexes; y++) { for (int x = 0; x < gridWidthInHexes; x++) { //GameObject assigned to Hex public variable is cloned GameObject Hex = null; int tempGridValue = Grid[y, x]; if (Grid[y, x] >= 0) { Grid[y, x] %= 10; } if (Grid[y, x] == 1) { Hex = ObjectPool.Instance.instantiate(GrassTilePrefab); if (width == 0.0f && height == 0.0f) { width = Hex.GetComponent <Renderer>().bounds.size.x; height = Hex.GetComponent <Renderer>().bounds.size.z; setSizes(width, height); } } if (Grid[y, x] == 2) { Hex = ObjectPool.Instance.instantiate(LavaTilePrefab); if (width == 0.0f && height == 0.0f) { width = Hex.GetComponent <Renderer>().bounds.size.x; height = Hex.GetComponent <Renderer>().bounds.size.z; setSizes(width, height); } } if (Grid[y, x] == 3) { Hex = ObjectPool.Instance.instantiate(SnowTilePrefab); if (width == 0.0f && height == 0.0f) { width = Hex.GetComponent <Renderer>().bounds.size.x; height = Hex.GetComponent <Renderer>().bounds.size.z; setSizes(width, height); } } if (Grid[y, x] == 4) { Hex = ObjectPool.Instance.instantiate(ScifiTilePrefab); if (width == 0.0f && height == 0.0f) { width = Hex.GetComponent <Renderer>().bounds.size.x; height = Hex.GetComponent <Renderer>().bounds.size.z; setSizes(width, height); } } if (Grid[y, x] == 0) { Hex = ObjectPool.Instance.instantiate(EmptyTilePrefab); if (width == 0.0f && height == 0.0f) { width = Hex.GetComponent <Renderer>().bounds.size.x; height = Hex.GetComponent <Renderer>().bounds.size.z; setSizes(width, height); } } //Current position in grid if (Hex) { Vector2 gridPos = new Vector2(x, y); Hex.transform.position = calcWorldCoord(gridPos); Hex.transform.parent = hexGridGO.transform; PathNode tempNode = PathNode.Spawn(Hex.transform.position); tempNode.transform.parent = hexGridNode.transform; hexaNodeList.Add(tempNode); } if (tempGridValue >= 10) { if (tempGridValue < 20) { GameObject.Find("SpawnManager").GetComponent <SpawnManager>().spawnPosition = calcWorldCoord(new Vector2(x, y)); ObjectPool.Instance.instantiate(SpawnerPrefab, calcWorldCoord(new Vector2(x, y)), Quaternion.identity); } else if (tempGridValue < 30) { GameObject.Find("SpawnManager").GetComponent <SpawnManager>().targetPosition = calcWorldCoord(new Vector2(x, y)); ObjectPool.Instance.instantiate(NexusPrefab, calcWorldCoord(new Vector2(x, y)), Quaternion.identity); } } } } for (int y = 0; y < gridHeightInHexes; y++) { for (int x = 0; x < gridWidthInHexes; x++) { int currentIndex = (y * gridWidthInHexes) + x; List <int> neighbourList = new List <int>(); PathNode currentNode = hexaNodeList[currentIndex]; if (AStarScript.Invalid(currentNode)) { continue; } //Check left neighbour if (x > 0) { neighbourList.Add((y * gridWidthInHexes) + x - 1); } //Check right neighbour if (x != gridWidthInHexes - 1) { neighbourList.Add((y * gridWidthInHexes) + x + 1); } // Check odd row if (y % 2 == 0) { //Check top left neighbour if (x != 0 && y != 0) { neighbourList.Add(((y - 1) * gridWidthInHexes) + x - 1); } //Check top right neighbour if (y != 0) { neighbourList.Add(((y - 1) * gridWidthInHexes) + x); } //Check bottom left neighbour if (x != 0 && y != gridHeightInHexes - 1) { neighbourList.Add(((y + 1) * gridWidthInHexes) + x - 1); } //Check bottom right neighbour if (y != gridHeightInHexes - 1) { neighbourList.Add(((y + 1) * gridWidthInHexes) + x); } } //Check even row else { //Check top left neighbour if (y != 0) { neighbourList.Add(((y - 1) * gridWidthInHexes) + x); } //Check top right neighbour if (y != 0 && x != gridWidthInHexes - 1) { neighbourList.Add(((y - 1) * gridWidthInHexes) + x + 1); } //Check bottom left neighbour if (y != gridHeightInHexes - 1) { neighbourList.Add(((y + 1) * gridWidthInHexes) + x); } //Check bottom right neighbour if (y != gridHeightInHexes - 1 && x != gridWidthInHexes - 1) { neighbourList.Add(((y + 1) * gridWidthInHexes) + x + 1); } } for (int i = 0; i < neighbourList.Count; i++) { PathNode connectedNode = hexaNodeList[neighbourList[i]]; if (AStarScript.Invalid(connectedNode)) { continue; } currentNode.Connections.Add(connectedNode); currentNode.OriginalConnections.Add(connectedNode); } } } for (int y = 0; y < gridHeightInHexes; y++) { for (int x = 0; x < gridWidthInHexes; x++) { if (Grid[y, x] == 0) { int currentIndex = (y * gridWidthInHexes) + x; PathNode nodeToDisable = hexaNodeList[currentIndex]; DisableNode(nodeToDisable.Position); for (int i = 0; i < nodeToDisable.Connections.Count; i++) { PathNode neighbourNode = nodeToDisable.Connections[i]; for (int j = 0; j < neighbourNode.Connections.Count; j++) { if (neighbourNode.Connections[j] == nodeToDisable) { neighbourNode.Connections.Remove(nodeToDisable); j--; } } } nodeToDisable.Connections.Clear(); } } } }