public PathRequest(Vector3 pathStart, Vector3 pathEnd, BBCoordinate bound, Action<Vector3[], bool> callback) { this.pathStart = pathStart; this.pathEnd = pathEnd; this.bound = bound; this.callback = callback; }
public static BBCoordinate CompoundCoordinate(BBCoordinate[] coordinates) { int x = 0, y = 0; for (int i = 0; i < coordinates.Length; i++) { x += coordinates[i].x; y += coordinates[i].y; } return new BBCoordinate(x, y); }
private IEnumerator FindPath(Vector3 startPos, Vector3 targetPos, BBCoordinate bound) { Vector3[] waypoints = new Vector3[0]; bool isPathSuccess = false; BBNode startNode = this.grid.NodeFromWorldPoint(startPos); BBNode targetNode = this.grid.NodeFromWorldPoint(targetPos); if (startNode.IsWalkable && targetNode.IsWalkable) { BBHeap<BBNode> openSet = new BBHeap<BBNode>(this.grid.MaxSize); HashSet<BBNode> closedSet = new HashSet<BBNode>(); openSet.Add(startNode); while (openSet.Count > 0) { BBNode currentNode = openSet.RemoveFirst(); closedSet.Add(currentNode); if (currentNode == targetNode) { isPathSuccess = true; break; } foreach (BBNode neighbour in grid.GetNeighbours(currentNode)) { if (!neighbour.IsWalkable || closedSet.Contains(neighbour)) { continue; } if (grid.IsDiagonalMove(currentNode, neighbour)) { if (!grid.IsDiagonalMoveValid(currentNode, neighbour, bound)) { continue; } } // Cost is the cost to the current position + cost to next node + penalty int costToNeighbour = currentNode.GCost + this.GetDistance(currentNode, neighbour) + neighbour.TerrainPenalty; if (costToNeighbour < neighbour.GCost || !openSet.Contains(neighbour)) { neighbour.GCost = costToNeighbour; neighbour.HCost = this.GetDistance(neighbour, targetNode); neighbour.Parent = currentNode; if (!openSet.Contains(neighbour)) { openSet.Add (neighbour); } else { openSet.UpdateItem(neighbour); } } } } yield return null; if (isPathSuccess) { waypoints = this.RetracePath(startNode, targetNode); } this.requestManager.FinishedProcessingPath(waypoints, isPathSuccess); } }
public List<BBNode> GetNeighbours(BBNode node) { List<BBNode> neighbhours = new List<BBNode>(); // Checks adjacent nodes and adds them to list if within grid for (int x = -1; x <= 1; x++) { for (int y = -1; y <= 1; y++) { if (x == 0 && y == 0) { continue; } BBCoordinate checkCoordinate = new BBCoordinate(node.Coordinate.x + x, node.Coordinate.y + y); if (this.IsCoordinateInBounds(checkCoordinate)) { neighbhours.Add(grid[checkCoordinate.x, checkCoordinate.y]); } } } return neighbhours; }
public void Init(GameObject originObject) { base.Init(originObject); this.gridController = GameObject.FindGameObjectWithTag(BBSceneConstants.layoutControllerTag).GetComponent<BBGridController>(); this.originCoordinate = this.gridController.CoordinateFromWorldPoint(originObject.transform.position); this.path = new BBCoordinate[] { BBCoordinate.CompoundCoordinate(new BBCoordinate[] { this.originCoordinate, new BBCoordinate(1, 1) }), BBCoordinate.CompoundCoordinate(new BBCoordinate[] { this.originCoordinate, new BBCoordinate(0, 2) }), BBCoordinate.CompoundCoordinate(new BBCoordinate[] { this.originCoordinate, new BBCoordinate(-1, 1) }), BBCoordinate.CompoundCoordinate(new BBCoordinate[] { this.originCoordinate, new BBCoordinate(-2, 0) }), BBCoordinate.CompoundCoordinate(new BBCoordinate[] { this.originCoordinate, new BBCoordinate(-1, -1) }), BBCoordinate.CompoundCoordinate(new BBCoordinate[] { this.originCoordinate, new BBCoordinate(0, -2) }), BBCoordinate.CompoundCoordinate(new BBCoordinate[] { this.originCoordinate, new BBCoordinate(1, -1) }) }; transform.GetComponent<BBPathFollow>().Path = this.path; }
// Used in conjunction with NearestOpenNode to reduce boilerplate private void OpenNodeHelper(BBCoordinate coordinate, HashSet<BBCoordinate> searchedCoordinates, Queue<BBCoordinate> coordinatesToSearch) { if (!searchedCoordinates.Contains(coordinate) && !coordinatesToSearch.Contains(coordinate)) { if (this.IsCoordinateInBounds(coordinate)) { coordinatesToSearch.Enqueue(coordinate); } } }
// Determine valid nodes private bool IsCoordinateInGridBounds(BBCoordinate coordinate) { return !(coordinate.x >= this.gridWorldSize.x|| coordinate.y >= this.gridWorldSize.y); }
void Awake() { this.nodeDiameter = this.nodeRadius * 2; this.gridSize = new BBCoordinate(Mathf.RoundToInt(this.gridWorldSize.x / this.nodeDiameter), Mathf.RoundToInt(this.gridWorldSize.y / this.nodeDiameter)); this.CreateGrid(); }
public Vector3 WorldPointFromCoordinate(BBCoordinate coordinate) { Vector3 center = transform.position; return new Vector3(center.x + (coordinate.x - (this.gridWorldSize.x / 2)) + this.nodeRadius, center.y + (coordinate.y - (this.gridWorldSize.y / 2)) + this.nodeRadius, BBSceneConstants.collidedGround); }
// If number is not needed, just feed it a negative number. This will be the convention we use instead of assigning it random values public SpawnUnit(BBSpriteFactory.Sprite sprite, float spawnDelaySeconds, float spawnOffsetSeconds, BBCoordinate coordinate, bool atOpenCoordinate, BBEntityStats stats, int number) { this.sprite = sprite; this.spawnSeconds = spawnDelaySeconds + spawnOffsetSeconds; this.coordinate = coordinate; this.atOpenCoordinate = atOpenCoordinate; this.stats = stats; this.number = number; }
public static void RequestPath(Vector3 pathStart, Vector3 pathEnd, BBCoordinate bound, Action<Vector3[], bool> callback) { PathRequest newRequest = new PathRequest(pathStart, pathEnd, bound, callback); BBPathRequestController.instance.pathRequestQueue.Enqueue(newRequest); BBPathRequestController.instance.TryProcessNext(); }
public BBNode NearestOpenNode(BBCoordinate coordinate) { if (this.IsOpenNodeAtCoordinate(coordinate)) { return this.NodeFromCoordinate(coordinate); } Queue<BBCoordinate> coordinatesToSearch = new Queue<BBCoordinate>(); coordinatesToSearch.Enqueue(coordinate); // BFS for open node HashSet<BBCoordinate> searchedCoordinates = new HashSet<BBCoordinate>(); while (coordinatesToSearch.Count > 0) { BBCoordinate coor = coordinatesToSearch.Dequeue(); if (this.IsOpenNodeAtCoordinate(coor)) { return this.NodeFromCoordinate(coor); } BBCoordinate left = new BBCoordinate(coor.x - 1, coor.y); this.OpenNodeHelper(left, searchedCoordinates, coordinatesToSearch); BBCoordinate top = new BBCoordinate(coor.x, coor.y + 1); this.OpenNodeHelper(top, searchedCoordinates, coordinatesToSearch); BBCoordinate right = new BBCoordinate(coor.x + 1, coor.y); this.OpenNodeHelper(right, searchedCoordinates, coordinatesToSearch); BBCoordinate bottom = new BBCoordinate(coor.x, coor.y - 1); this.OpenNodeHelper(bottom, searchedCoordinates, coordinatesToSearch); searchedCoordinates.Add(coor); } return null; }
public BBCoordinate NearestOpenCoordinate(BBCoordinate coordinate) { BBNode nearestOpenNode = this.NearestOpenNode(coordinate); if (nearestOpenNode != null) { return nearestOpenNode.Coordinate; } else { return null; } }
public bool IsOpenNodeAtCoordinate(BBCoordinate coordinate) { if (!this.IsCoordinateInBounds(coordinate)) { return false; } BBNode node = this.NodeFromCoordinate(coordinate); return (node.IsWalkable && node.InhabitedCount == 0); }
public bool IsNodeAtCoordinate(BBCoordinate coordinate) { if (!this.IsCoordinateInBounds(coordinate)) { return false; } BBNode node = this.NodeFromCoordinate(coordinate); return node.IsWalkable; }
public void StartFindPath(Vector3 startPos, Vector3 targetPos, BBCoordinate bound) { StartCoroutine(this.FindPath (startPos, targetPos, bound)); }
public bool IsCoordinateInBounds(BBCoordinate coordinate) { return (coordinate.x >= 0 && coordinate.x < this.gridSize.x) && (coordinate.y >= 0 && coordinate.y < this.gridSize.y); }
// Checks if adjacent horizontal and vertical nodes would be cut off during a diagonal move public bool IsDiagonalMoveValid(BBNode startNode, BBNode targetNode, BBCoordinate bound) { //Set Indices accordingly and check if valid int horizontalX = (targetNode.Coordinate.x < startNode.Coordinate.x) ? startNode.Coordinate.x - bound.x : startNode.Coordinate.x + bound.x; if ((horizontalX < 0) || (horizontalX >= this.gridSize.x)) { return false; } int verticalY = (targetNode.Coordinate.y < startNode.Coordinate.y) ? startNode.Coordinate.y - bound.y : startNode.Coordinate.y + bound.y; if ((verticalY < 0) || (verticalY >= this.gridSize.y)) { return false; } BBCoordinate horizontalIndex = new BBCoordinate(horizontalX, startNode.Coordinate.y); BBCoordinate verticalIndex = new BBCoordinate(startNode.Coordinate.x, verticalY); return (grid[horizontalIndex.x, horizontalIndex.y].IsWalkable && grid[verticalIndex.x, verticalIndex.y].IsWalkable); }
// Place wherever you want public SpawnUnit CreateSpawnUnit(BBSpriteFactory.Sprite sprite, float spawnDelaySeconds, BBCoordinate coordinate, bool atValidCoordinate, BBEntityStats stats, int number) { BBNode referencedNode = this.gridController.grid[coordinate.x, coordinate.y]; return new SpawnUnit(sprite, spawnDelaySeconds, this.timer.Seconds, coordinate, atValidCoordinate, stats, number); }
public BBNode NodeFromCoordinate(BBCoordinate coordinate) { return this.grid[coordinate.x, coordinate.y]; }
public SpawnUnit CreateSpawnUnit(BBSpriteFactory.Sprite sprite, float spawnDelaySeconds, BBCoordinate coordinate, bool atValidCoordinate, BBEntityStats stats) { return this.CreateSpawnUnit(sprite, spawnDelaySeconds, coordinate, atValidCoordinate, stats, (int)BBSceneConstants.NumberConventions.DEFAULTNUMBER); }
public void RequestPath(Vector3 startPos, Vector3 targetPos, BBCoordinate bound, float speed) { this.targetIndex = 0; this.speed = speed; BBPathRequestController.RequestPath(startPos, targetPos, bound, OnPathFound); }
public BBGroundTile TileAtCoordinate(BBCoordinate coordinate) { if (!this.IsNodeAtCoordinate(coordinate)) { return null; } // WorldPointFromCoordinate returns the collided ground. We want where the ground actually is for these calculations Collider[] colliders = Physics.OverlapSphere(this.WorldPointFromCoordinate(coordinate) - BBSceneConstants.collidedGroundVect, this.nodeRadius - .01f); foreach (Collider collider in colliders) { BBGroundTile tile = collider.gameObject.GetComponent<BBGroundTile>(); if (tile != null) { return tile; } } return null; }