private void UpdatePathMovement() { if (m_CurrentWaypoint == null) { m_CurrentWaypoint = path.GetNextWaypoint(); if (m_CurrentWaypoint == null) { return; } } Vector3 movement = Vector3.MoveTowards(transform.localPosition, m_CurrentWaypoint.gameObject.transform.position, Time.deltaTime * speed); transform.localPosition = movement; Vector3 objectPositionNoY = new Vector3(transform.position.x, 0f, transform.position.z); Vector3 waypointPositionNoY = new Vector3(m_CurrentWaypoint.transform.position.x, 0f, m_CurrentWaypoint.transform.position.z); float delta = Vector3.Distance(objectPositionNoY, waypointPositionNoY); if (delta < 0.1f) { m_CurrentWaypoint = path.GetNextWaypoint(m_CurrentWaypoint); } }
private void onGrassSearchReached(PathWaypoint lastWaypoint, bool reached) { if (reached) { var grass = this.World.getFirstEntityOnPoint(lastWaypoint.Goal, typeof(EntityGrassTuft), false); if (grass != null) { grass.Dead = true; } } this.eatCooldown = 200 + this.Rand.Next(200); }
public void setPath(PathWaypoint newPath, AIState state, CollidableObj obj = null) { timeSincePathUpdate = 0; path = newPath; targetObj = obj; jumped = false; if (this.state != AIState.Chasing && state == AIState.Chasing) { agroTimer = 0; tiredIntervals = 1; } this.state = state; }
void OnSceneGUI() { PathWaypoint path = target as PathWaypoint; List <Transform> listTransform = path.GetPath(); if (listTransform == null || listTransform.Count == 0) { return; } // we store the start and end points of the line segments in this array Vector3[] lineSegments = new Vector3[listTransform.Count * 2]; int lastObject = listTransform.Count - 1; Vector3 prevPoint; if (listTransform[lastObject]) { prevPoint = listTransform[lastObject].position; } else { prevPoint = Vector3.zero; } int pointIndex = 0; for (int currObjectIndex = 0; currObjectIndex < listTransform.Count; currObjectIndex++) { // find the position of our connected object and store it Vector3 currPoint; if (listTransform[currObjectIndex]) { currPoint = listTransform[currObjectIndex].position; } else { currPoint = Vector3.zero; } // store the starting point of the line segment lineSegments[pointIndex] = prevPoint; pointIndex++; // store the ending point of the line segment lineSegments[pointIndex] = currPoint; pointIndex++; prevPoint = currPoint; } Handles.color = Color.yellow; Handles.DrawLines(lineSegments); }
private void DrawGizmos() { Gizmos.color = gizmosColor; for (int i = 0; i < m_WayPoints.Count; i++) { PathWaypoint first = m_WayPoints[i]; Gizmos.DrawSphere(first.gameObject.transform.position, 1f); if (i < m_WayPoints.Count - 1) { PathWaypoint second = m_WayPoints[i + 1]; Gizmos.DrawSphere(second.gameObject.transform.position, 1f); Gizmos.DrawLine(first.gameObject.transform.position, second.gameObject.transform.position); } } }
public PathWaypoint GetNextWaypoint(PathWaypoint currentWaypoint = null) { if (m_WayPoints == null || m_WayPoints.Count == 0) { return(null); } if (currentWaypoint == null) { return(m_WayPoints[0]); } for (int i = 0; i < m_WayPoints.Count; i++) { if (m_WayPoints[i] == currentWaypoint) { if (i + 1 == m_WayPoints.Count) { return(null); } return(m_WayPoints[i + 1]); } } return(null); }
private PathWaypoint generateIdlePath(SortedVector2List <Platform> platforms, CollidableObj obj, AI ai, int jumpStrength, int xVelocity, float gravity, PathWaypoint curWapoint = null) { ConnectivityNode curNode = null; if (curWapoint != null && !(connectivityGraph.ContainsKey((int)curWapoint.position.X) && connectivityGraph[(int)curWapoint.position.X].ContainsKey((int)curWapoint.position.Y))) { curWapoint = null; } if (curWapoint != null) { curNode = connectivityGraph[(int)curWapoint.position.X][(int)curWapoint.position.Y]; } if (curNode == null) { List <Vector2> res = getClosestNodeKeyForPosition(platforms, obj, obj.Position, obj.Position, gravity, xVelocity, jumpStrength); if (res == null) { return(null); } foreach (Vector2 v in res) { if (ai.inBoundingBox(v)) { return(new PathWaypoint(v, null, PathType.Free)); } } } List <PathWaypoint> waypoints = new List <PathWaypoint> { new PathWaypoint(new Vector2(obj.Position.X, obj.getBot()), null, PathType.Free) }; if (curNode != null) { foreach (ConnectivityPath path in curNode.connections) { if (ai.inBoundingBox(path.endNode.position)) { bool jumpPath = path.jumpPath && path.jumpableStrengths[jumpStrength] && path.minXVel(jumpStrength, 0.15f) <= xVelocity; bool straightPath = path.straightPath && path.minXVel(0, 0.15f) <= xVelocity; if (straightPath) { waypoints.Add(new PathWaypoint(path.endNode.position, null, PathType.Straight)); } if (jumpPath) { waypoints.Add(new PathWaypoint(path.endNode.position, null, PathType.Jump)); } } } } return(waypoints[new Random().Next(waypoints.Count)]); }
private PathWaypoint getPath(SortedVector2List <Platform> platforms, CollidableObj start, CollidableObj end, int jumpStrength, int xVelocity, float gravity, PathWaypoint curWapoint = null) { Dictionary <Vector2, ConnectivityNodeWrapper> exploredSet = new Dictionary <Vector2, ConnectivityNodeWrapper>(); Dictionary <Vector2, ConnectivityNodeWrapper> openSet = new Dictionary <Vector2, ConnectivityNodeWrapper>(); MinHeap <ConnectivityNodeWrapper> queue = new MinHeap <ConnectivityNodeWrapper>(delegate(ConnectivityNodeWrapper n1, ConnectivityNodeWrapper n2) { if (n1.heurisitc < n2.heurisitc) { return(-1); } else if (n1.heurisitc == n2.heurisitc) { return(0); } else { return(1); } }); List <Vector2> res; ConnectivityNodeWrapper curNode; if (curWapoint != null && !(connectivityGraph.ContainsKey((int)curWapoint.position.X) && connectivityGraph[(int)curWapoint.position.X].ContainsKey((int)curWapoint.position.Y))) { curWapoint = null; } if (curWapoint != null) { curNode = new ConnectivityNodeWrapper(connectivityGraph[(int)curWapoint.position.X][(int)curWapoint.position.Y], calculateHeuristic(curWapoint.position, end.Position, xVelocity, jumpStrength)); } else { res = getClosestNodeKeyForPosition(platforms, start, start.Position, end.Position, gravity, xVelocity); if (res == null) { return(null); } foreach (Vector2 vec in res) { ConnectivityNodeWrapper cnw = new ConnectivityNodeWrapper(connectivityGraph[(int)vec.X][(int)vec.Y], calculateHeuristic(vec, end.Position, xVelocity, jumpStrength)); queue.add(cnw); openSet.Add(cnw.node.position, cnw); } curNode = queue.peek(); queue.pop(); openSet.Remove(curNode.node.position); } res = getClosestNodeKeyForPosition(platforms, end, end.Position, end.Position, gravity, xVelocity, jumpStrength); if (res == null) { return(null); } ConnectivityNode endNode = connectivityGraph[(int)res[0].X][(int)res[0].Y]; int it = 0; while (curNode != endNode) { foreach (ConnectivityPath path in curNode.node.connections) { if (!exploredSet.ContainsKey(path.endNode.position)) { bool jumpPath = path.jumpPath && path.jumpableStrengths[jumpStrength] && path.minXVel(jumpStrength, gravity) <= xVelocity; bool straightPath = path.straightPath && (path.minXVel(0, gravity) <= xVelocity || path.walkable); if (straightPath) { float h = calculateHeuristic(path.endNode.position, endNode.position, xVelocity, jumpStrength); if (!openSet.ContainsKey(path.endNode.position)) { ConnectivityNodeWrapper cnw = new ConnectivityNodeWrapper(path.endNode, path.getStraightPathCost(xVelocity, gravity), h, curNode, PathType.Straight); queue.add(cnw); openSet.Add(cnw.node.position, cnw); } else if (openSet[path.endNode.position].heurisitc > h) { ConnectivityNodeWrapper cnw = new ConnectivityNodeWrapper(path.endNode, path.getStraightPathCost(xVelocity, gravity), h, curNode, PathType.Straight); queue.add(cnw); openSet[path.endNode.position] = cnw; } } else if (jumpPath) { queue.add(new ConnectivityNodeWrapper(path.endNode, path.jumpCosts[jumpStrength], calculateHeuristic(path.endNode.position, endNode.position, xVelocity, jumpStrength), curNode, PathType.Jump)); } } } exploredSet.Add(curNode.node.position, curNode); ++it; if (it == 20) { return(null); } do { if (queue.empty()) { return(null); } curNode = queue.peek(); queue.pop(); } while (exploredSet.ContainsKey(curNode.node.position)); } PathWaypoint pathWaypoint = new PathWaypoint(new Vector2(end.Position.X, end.getBot()), null, PathType.Free); while (curNode != (object)null) { pathWaypoint = new PathWaypoint(curNode.node.position, pathWaypoint, curNode.pathType); curNode = curNode.parent; } if (curWapoint != null) { pathWaypoint = pathWaypoint.nextWaypoint; } return(pathWaypoint); }
public void updateAIPaths(SortedVector2List <Platform> platforms, Hero hero, float gravity) { foreach (Enemy enemy in enemies) { // If enemy has no path or has a path that is not mandatory if (enemy.ai.state != AIState.Correctional) { // If hero is within agro range and within bounding box, otherwise idle if (distance(hero.Position, enemy.Position) < enemy.maxAgroRange && enemy.ai.inBoundingBox(hero.Position)) { // If hero is within chase range and not blocked by a platform, otherwise if enemyy needs a new path if (distance(hero.Position, enemy.Position) < 150 && !platformsCollissionRay(platforms, enemy.Position, hero.Position)) { enemy.ai.clearPath(); enemy.ai.setPath(null, AIState.Chasing, hero); } else if (enemy.ai.timeSincePathUpdate > MIN_SEARCH_INTERVAL + distance(hero.Position, enemy.Position) / 20 && enemy.ai.newPathFlag) { bool noPath = false; // If the target location is within an accessible area in the bounding box if (canStayInBounds(platforms, enemy, gravity, new Vector2(hero.Position.X, hero.Position.Y + (enemy.Position.Y - enemy.getBot())), new Vector2(hero.Position.X, hero.Position.Y + (enemy.Position.Y - enemy.getBot())))) { PathWaypoint path = getPath(platforms, enemy, hero, (int)enemy.calculateStat(StatTypes.Jump), (int)enemy.calculateStat(StatTypes.Movement), gravity, enemy.ai.currentWaypoint); if (path != null) { enemy.ai.setPath(path, AIState.Chasing, hero); } else { noPath = true; } } else { noPath = true; } if (noPath && (enemy.ai.newPathFlag && enemy.ai.timeSincePathUpdate > idleTime || enemy.ai.state != AIState.Idling)) { enemy.ai.setPath(generateIdlePath(platforms, enemy, enemy.ai, (int)enemy.calculateStat(StatTypes.Jump), (int)enemy.calculateStat(StatTypes.Movement), gravity, enemy.ai.currentWaypoint), AIState.Idling, null); } } } else if ((enemy.ai.newPathFlag && enemy.ai.timeSincePathUpdate > idleTime) || enemy.ai.state != AIState.Idling) { enemy.ai.setPath( generateIdlePath(platforms, enemy, enemy.ai, (int)enemy.calculateStat(StatTypes.Jump), (int)enemy.calculateStat(StatTypes.Movement), gravity, enemy.ai.currentWaypoint), (enemy.ai.state == AIState.Tired) ? AIState.Tired : AIState.Idling); } } enemy.ai.moveBody(); // If the enemy's next movement will still allow it to stay in the bounding box if (enemy.ai.targetObj != null && enemy.ai.path == null) { if (!canStayInBounds(platforms, enemy, gravity, new Vector2(enemy.Position.X, enemy.getBot()), new Vector2(enemy.Position.X, enemy.getBot()) + enemy.Velocity)) { enemy.ai.setPath(new PathWaypoint(getClosestNodeKeyForPosition(platforms, enemy, enemy.Position, new Vector2(enemy.Position.X, enemy.getBot()), gravity, (int)enemy.calculateStat(StatTypes.Movement))[0], null, PathType.Free), AIState.Correctional); enemy.ai.moveBody(); } } } }
public PathWaypoint(Vector2 position, PathWaypoint nextWaypoint, PathType pathType) { this.position = position; this.nextWaypoint = nextWaypoint; this.pathType = pathType; }