private int GetIndex(Seeker seeker) { int index = -1; float verticalMidpoint = Bounds.xMin + (Bounds.width / 2f); float horizontalMidpoint = Bounds.yMin + (Bounds.height / 2f); var position = seeker.transform.position; // Seeker is inside the top half bool topQuadrant = _pathfinder.worldStart.z - position.z < horizontalMidpoint; // Seeker is inside the bottom half bool bottomQuadrant = _pathfinder.worldStart.z - position.z >= horizontalMidpoint; // Seeker is inside the left half if (seeker.transform.position.x - _pathfinder.worldStart.x < verticalMidpoint) { if (topQuadrant) { index = 1; } else if (bottomQuadrant) { index = 2; } } // Seeker is inside the right half else if (seeker.transform.position.x - _pathfinder.worldStart.x >= verticalMidpoint) { if (topQuadrant) { index = 0; } else if (bottomQuadrant) { index = 3; } } return(index); }
public void insert(Seeker seeker) { if (nodesInUse) { int index = getIndex(seeker); if (index != -1) { nodes[index].insert(seeker); return; } } objects.Add(seeker); if (objects.Count > maxObjectsPerQuad && level < maxDepthLevel) { nodesInUse = true; int i = 0; while (i < objects.Count) { Seeker obj = objects[i]; int index = getIndex(obj); if (index != -1) { nodes[index].insert(obj); objects.Remove(obj); } else { i++; } } } }
public void Insert(Seeker seeker) { if (NodesInUse) { int index = GetIndex(seeker); if (index != -1) { Nodes[index].Insert(seeker); return; } } Objects.Add(seeker); if (Objects.Count > MaxObjectsPerQuad && _level < MaxDepthLevel) { NodesInUse = true; int i = 0; while (i < Objects.Count) { Seeker obj = Objects[i]; int index = GetIndex(obj); if (index != -1) { Nodes[index].Insert(obj); Objects.Remove(obj); } else { i++; } } } }
// Add seeker to already calculated flowPath, for example, there is 1 flowfield path for all characters in a tower defence game // and you want to add characters over time. public void AddSeekerToExistingFlowField(int flowFieldPathKey, Seeker seeker) { charactersInFlowPath[flowFieldPathKey].Add(seeker); seeker.SetFlowField(worldData.flowFieldManager.flowFieldPaths[flowFieldPathKey], false); }
private int getIndex(Seeker seeker) { int index = -1; // Seeker is inside the top half // 2dview bool topQuadrant = seeker.transform.position.z > bounds[1]; // Seeker is inside the bottom half // 2dview bool bottomQuadrant = seeker.transform.position.z <= bounds[1]; // Seeker is inside the top height half bool topWorldY_Quadrant = seeker.transform.position.y >= bounds[2]; // Seeker is inside the left half if (seeker.transform.position.x < bounds[0]) { if (topWorldY_Quadrant) { if (topQuadrant) { index = 5; } else if (bottomQuadrant) { index = 6; } } else { if (topQuadrant) { index = 1; } else if (bottomQuadrant) { index = 2; } } } // Seeker is inside the right half else if (seeker.transform.position.x >= bounds[0]) { if (topWorldY_Quadrant) { if (topQuadrant) { index = 4; } else if (bottomQuadrant) { index = 7; } } else { if (topQuadrant) { index = 0; } else if (bottomQuadrant) { index = 3; } } } return(index); }
public void CheckIfMovementLegit(Seeker seeker) { if (seeker.currentTile != null && seeker.currentWorldArea != null) { int xDir = 0; int yDir = 0; bool capXMovement = false; bool capZMovement = false; int areaXMovement = -1; int areaZMovement = -1; if (seeker.movement.x != 0) { if (seeker.movement.x > 0) { xDir = 1; } else { xDir = -1; } } if (seeker.movement.z != 0) { if (seeker.movement.z > 0) { yDir = -1; } else { yDir = 1; } } if (yDir == 0 && xDir == 0) { // nothing changed } else { Tile destination; if (seeker.currentTile.GridPos.X + xDir > -1 && seeker.currentTile.GridPos.X + xDir < seeker.currentWorldArea.GridWidth) { // inside world area destination = seeker.currentWorldArea.TileGrid[seeker.currentTile.GridPos.X + xDir][ seeker.currentTile.GridPos.Y]; if (destination == null) // null, can we travel to another world area, or is there nothing? { areaXMovement = CheckIfMovingToOtherArea(seeker, xDir, 0); capXMovement = true; } else if (destination.Blocked) { capXMovement = true; } } else { areaXMovement = CheckIfMovingToOtherArea(seeker, xDir, 0); capXMovement = true; } if (seeker.currentTile.GridPos.Y + yDir > -1 && seeker.currentTile.GridPos.Y + yDir < seeker.currentWorldArea.GridLength) { // inside world area destination = seeker.currentWorldArea.TileGrid[seeker.currentTile.GridPos.X][ seeker.currentTile.GridPos.Y + yDir]; if (destination == null) // null, can we travel to another world area, or is there nothing? { areaZMovement = CheckIfMovingToOtherArea(seeker, 0, yDir); capZMovement = true; } else if (destination.Blocked) { capZMovement = true; } } else { // outside areaZMovement = CheckIfMovingToOtherArea(seeker, 0, yDir); capZMovement = true; } if (!capXMovement && !capZMovement) // diagonal check { destination = seeker.currentWorldArea.TileGrid[seeker.currentTile.GridPos.X + xDir][ seeker.currentTile.GridPos.Y + yDir]; if (destination == null || destination.Blocked) { if (seeker.desiredFlowValue == Vector2.zero) { seeker.movement = Vector3.zero; } else { if (seeker.desiredFlowValue.x == 0 || (seeker.desiredFlowValue.x > 0 && seeker.movement.x < 0) || (seeker.desiredFlowValue.x < 0 && seeker.movement.x > 0)) { float futureXPos = seeker.transform.position.x + seeker.movement.x; float border = _worldData.TileManager .GetTileWorldPosition(seeker.currentTile, seeker.currentWorldArea).x + (_worldData.Pathfinder.tileSize * 0.49f * xDir); if (xDir == 1 && futureXPos > border) { seeker.movement.x -= (futureXPos - border); } else if (xDir == -1 && futureXPos < border) { seeker.movement.x -= (futureXPos - border); } } if (seeker.desiredFlowValue.y == 0 || (seeker.movement.z > 0 && seeker.desiredFlowValue.y < 0) || (seeker.movement.z < 0 && seeker.desiredFlowValue.y > 0)) { float futureZPos = seeker.transform.position.z + seeker.movement.z; float border = _worldData.TileManager .GetTileWorldPosition(seeker.currentTile, seeker.currentWorldArea).z + (_worldData.Pathfinder.tileSize * 0.49f * -yDir); if (yDir == -1 && futureZPos > border) { seeker.movement.z -= (futureZPos - border); } else if (yDir == 1 && futureZPos < border) { seeker.movement.z -= (futureZPos - border); } } } } } else { if (areaXMovement != -1 && areaZMovement != -1) { if (seeker.desiredFlowValue.x == 0 || (seeker.desiredFlowValue.x > 0 && seeker.movement.x < 0) || (seeker.desiredFlowValue.x < 0 && seeker.movement.x > 0)) { areaXMovement = -1; } else { areaZMovement = -1; } } } if (capXMovement) { if (areaXMovement == -1) { float futureXPos = seeker.transform.position.x + seeker.movement.x; float border = _worldData.TileManager.GetTileWorldPosition(seeker.currentTile, seeker.currentWorldArea) .x + (_worldData.Pathfinder.tileSize * 0.49f * xDir); if (xDir == 1 && futureXPos > border) { seeker.movement.x -= (futureXPos - border); } else if (xDir == -1 && futureXPos < border) { seeker.movement.x -= (futureXPos - border); } } else { if (yDir != 0) { bool capZ = false; int destinationAreaGridX = (seeker.currentTile.GridPos.X + xDir + seeker.currentWorldArea.LeftOffset) - _worldData.WorldAreas[areaXMovement].LeftOffset; int destinationAreaGridY = (seeker.currentTile.GridPos.Y + yDir + seeker.currentWorldArea.TopOffset) - _worldData.WorldAreas[areaXMovement].TopOffset; if (destinationAreaGridY < _worldData.WorldAreas[areaXMovement].GridLength && destinationAreaGridY > -1) { destination = _worldData.WorldAreas[areaXMovement].TileGrid[destinationAreaGridX][ destinationAreaGridY]; if (destination == null || destination.Blocked) { capZ = true; } } else { capZ = true; } if (capZ) { float futureZPos = seeker.transform.position.z + seeker.movement.z; float border = _worldData.TileManager .GetTileWorldPosition(seeker.currentTile, seeker.currentWorldArea).z + (_worldData.Pathfinder.tileSize * 0.49f * -yDir); if (yDir == -1 && futureZPos > border) { seeker.movement.z -= (futureZPos - border); } else if (yDir == 1 && futureZPos < border) { seeker.movement.z -= (futureZPos - border); } } } } } if (capZMovement) { if (areaZMovement == -1) { float futureZPos = seeker.transform.position.z + seeker.movement.z; float border = _worldData.TileManager.GetTileWorldPosition(seeker.currentTile, seeker.currentWorldArea) .z + (_worldData.Pathfinder.tileSize * 0.49f * -yDir); if (yDir == -1 && futureZPos > border) { seeker.movement.z -= (futureZPos - border); } else if (yDir == 1 && futureZPos < border) { seeker.movement.z -= (futureZPos - border); } } else { if (yDir != 0) { bool capX = false; int destinationAreaGridX = (seeker.currentTile.GridPos.X + xDir + seeker.currentWorldArea.LeftOffset) - _worldData.WorldAreas[areaZMovement].LeftOffset; int destinationAreaGridY = (seeker.currentTile.GridPos.Y + yDir + seeker.currentWorldArea.TopOffset) - _worldData.WorldAreas[areaZMovement].TopOffset; if (destinationAreaGridX < _worldData.WorldAreas[areaZMovement].GridWidth && destinationAreaGridX > -1) { destination = _worldData.WorldAreas[areaZMovement].TileGrid[destinationAreaGridX][ destinationAreaGridY]; if (destination == null || destination.Blocked) { capX = true; } } else { capX = true; } if (capX) { float futureXPos = seeker.transform.position.x + seeker.movement.x; float border = _worldData.TileManager .GetTileWorldPosition(seeker.currentTile, seeker.currentWorldArea).x + (_worldData.Pathfinder.tileSize * 0.49f * xDir); if (xDir == 1 && futureXPos > border) { seeker.movement.x -= (futureXPos - border); } else if (xDir == -1 && futureXPos < border) { seeker.movement.x -= (futureXPos - border); } } } } } } } }
// remove a seeker when you do not want him to move / or is dead/removed public void RemoveSeeker(Seeker seeker) { _allSeekers.Remove(seeker); }
public Vector2 FindFlowValueFromPosition(Vector3 worldPosition, FlowField flowField, Seeker seeker) { seeker.currentWorldArea = null; seeker.currentTile = null; Vector2 vec = Vector2.zero; WorldArea area = _worldData.TileManager.GetWorldAreaAtPosition(worldPosition); if (area != null) { int worldX = _worldData.TileManager.LocationToWorldGridX(worldPosition); int worldY = _worldData.TileManager.LocationToWorldGridY(worldPosition); //Debug.Log("Area Index: " + area.Index); //Debug.Log("WorldX: " + (worldX - area.LeftOffset)); Tile tile = area.TileGrid[worldX - area.LeftOffset][worldY - area.TopOffset]; if (tile != null) { seeker.currentWorldArea = area; seeker.currentTile = tile; _key.X = area.Index; _key.Y = tile.SectorIndex; if (flowField.Field.ContainsKey(_key)) { vec = _worldData.FlowFieldManager.DirToVector(flowField.Field[_key][tile.IndexWithinSector]); } } } return(vec); }
// add seeker to manager, now the seeker's tick() will be called, thus making him move public void AddSeeker(Seeker seeker) { _allSeekers.Add(seeker); }
public void SetNeighboursQuad(Seeker seeker, float neighbourRadiusSquared) { SetSearchBoxQuad(seeker); RetrieveSeekerNeighboursQuad(seeker, neighbourRadiusSquared); }
private int CheckIfMovingToOtherArea(Seeker seeker, int xDir, int yDir) { //if (_worldData.Pathfinder.worldIsMultiLayered) //{ IntVector2 key = seeker.currentTile.GridPos; if (seeker.currentWorldArea.WorldAreaTileConnections.ContainsKey(key) ) // if our current tile connects to tile in another world area, outside of our own tile grid { List <IntVector3> values = seeker.currentWorldArea.WorldAreaTileConnections[key]; for (int i = 0; i < values.Count; i++) { if (!_worldData.WorldAreas[values[i].Z].TileGrid[values[i].X][values[i].Y].Blocked) { if (xDir != 0) { if (_worldData.WorldAreas[values[i].Z].TopOffset + values[i].Y == seeker.currentWorldArea.TopOffset + key.Y ) // align on Z. its straight ahead or behind { if (xDir == 1 && (_worldData.WorldAreas[values[i].Z].LeftOffset + values[i].X > seeker.currentWorldArea.LeftOffset + key.X)) // right { return(values[i].Z); } if (xDir == -1 && (_worldData.WorldAreas[values[i].Z].LeftOffset + values[i].X < seeker.currentWorldArea.LeftOffset + key.X)) // left { return(values[i].Z); } } } else { if (_worldData.WorldAreas[values[i].Z].LeftOffset + values[i].X == seeker.currentWorldArea.LeftOffset + key.X && !_worldData.WorldAreas[values[i].Z].TileGrid[values[i].X][values[i].Y].Blocked ) // align on X. its straight ahead or behind { if (yDir == -1 && (_worldData.WorldAreas[values[i].Z].TopOffset + values[i].Y < seeker.currentWorldArea.TopOffset + key.Y)) // forward { return(values[i].Z); } if (yDir == 1 && (_worldData.WorldAreas[values[i].Z].TopOffset + values[i].Y > seeker.currentWorldArea.TopOffset + key.Y)) // back { return(values[i].Z); } } } } } } //} return(-1); }
private void SetSearchBoxQuad(Seeker seeker) { searchQuad.xMin = seeker.transform.position.x - pathfinder.worldStart.x - seeker.neighbourRadius; searchQuad.yMin = pathfinder.worldStart.z - seeker.transform.position.z - seeker.neighbourRadius; searchQuad.width = searchQuad.height = seeker.neighbourRadius * 2f; }
public Vector2 FindflowValueFromPosition(Vector3 worldPosition, FlowField flowField, Seeker seeker) { seeker.currentWorldArea = null; seeker.currentTile = null; Vector2 vec = Vector2.zero; WorldArea area = worldData.tileManager.GetWorldAreaAtPosition(worldPosition); if (area != null) { int worldX = worldData.tileManager.locationToWorldGridX(worldPosition); int worldY = worldData.tileManager.locationToWorldGridY(worldPosition); Tile tile = area.tileGrid[worldX - area.leftOffset][worldY - area.topOffset]; if (tile != null) { seeker.currentWorldArea = area; seeker.currentTile = tile; key.x = area.index; key.y = tile.sectorIndex; if (flowField.field.ContainsKey(key)) { vec = worldData.flowFieldManager.DirToVector(flowField.field[key][tile.indexWithinSector]); } } } return(vec); }