private void FindNearestNode(ComponentAI ai) { Vector3 distance; Vector3 shortestDistance = new Vector3(0, 0, 0); Node closestNode = null; bool distanceSet = false; foreach (Node node in map) { distance = ai.CurrentPosition - node.Location; if (distanceSet) { if (distance.Length < shortestDistance.Length) { shortestDistance = distance; closestNode = node; } } else { distanceSet = true; shortestDistance = distance; closestNode = node; } } ai.CurrentNode = new Vector2(closestNode.mapX, closestNode.mapY); ai.CurrentNodeLocation = closestNode.Location; }
/// <summary> /// Checks if the player is in the FOV of the drone /// </summary> /// <param name="ai"> the ai component of this entity </param> /// <param name="transform"> the transform component of this entity </param> /// <returns> true if the player is in the drones FOV </returns> private bool PlayerInFOV(ComponentAI ai, ComponentTransform transform) { //Finds the direction from the drone to the player Vector3 direction = (player.GetTransform().Translation - transform.Translation).Normalized(); //Finds the angle between the target direction and the agent forward vector float angle = (float)(Math.Atan2(direction.X, direction.Z) - Math.Atan2(transform.Forward.X, transform.Forward.Z)); //if the angle is over 180 in either direction then invert it to be a smaller angle in the opposite direction if (angle > Math.PI) { angle -= (float)(2 * Math.PI); } if (angle < -Math.PI) { angle += (float)(2 * Math.PI); } angle = MathHelper.RadiansToDegrees(angle); //if the player is in sight return true if (angle < ai.FOV && angle > -angle) { //Console.WriteLine("player spotted"); return(true); } return(false); }
private bool SearchForPath(ComponentAI ai, Node currentNode) { //Gets list of passable neighbours and then sorts them by the estimated distance traveled if taking this node on the path (F) and sets current node to closed List <Node> passableNeighbours = GetPassableNeighbours(ai, currentNode); passableNeighbours.Sort((node1, node2) => node1.F.CompareTo(node2.F)); currentNode.State = NodeState.Closed; //Recursively searches through each neighbour until the shortest path is found if a valid path is available foreach (Node passableNeighbour in passableNeighbours) { if (passableNeighbour.Location == ai.TargetNodeLocation) { return(true); } else { if (SearchForPath(ai, passableNeighbour)) { return(true); } } } return(false); }
private void SetNextNode(ComponentAI ai) { //Updates current node location then finds next node in the path and sets it as the next node ai.CurrentNodeLocation = ai.NextNodeLocation; if (ai.Path.Count() != 0) { ai.NextNode = ai.Path[ai.PathNodesTraversed]; ai.NextNodeLocation = map[(int)ai.Path[ai.PathNodesTraversed].X, (int)ai.Path[ai.PathNodesTraversed].Y].Location; } ai.NextSet = true; }
public void Motion(ComponentPosition pPos, ComponentVelocity pVel, ComponentAI pAI, string name) { // Updates the target with the most recent player position if (targetIsPlayer) { pAI.Target = mCamera.Position; } // Checks if the AI has found its target and skips search code for efficency if (RoundVectorPosition(pPos.Position).Xz == pAI.Target.Xz) { return; } // Checks if the AI's target is within map boundaries if (!(pAI.Target.X < (mWidth / 2) && !(pAI.Target.X > (mWidth / 2)) && pAI.Target.Z < (mHeight / 2) && !(pAI.Target.Z > (mHeight / 2)))) { return; } // Makes sure target is in a traversable area if (!Traversable[(int)pAI.Target.Z + (mHeight / 2), (int)pAI.Target.X + (mWidth / 2)]) { return; } if (pAI.Path.Length > 0 && pAI.ogTarget == pAI.Target) { // Path following Vector3 direction = pAI.Path[0] - pPos.Position; pPos.Position += direction * pVel.Veclotiy * deltaTime; } else { // Updates path finding pAI.ogTarget = pAI.Target; pAI.Path = ASPath(RoundVectorPosition(pPos.Position), RoundVectorPosition(pAI.Target)); // Path following if (pAI.Path.Length <= 0) { // Path finding failed return; } Vector3 direction = pAI.Path[0] - pPos.Position; pPos.Position += direction * pVel.Veclotiy * deltaTime; } // Check to see if AI has hit closest point in path and removes it if true so it can follow the next point if (RoundVectorPosition(pPos.Position) == pAI.Path[0]) { pAI.Path = pAI.Path.Skip(1).ToArray(); } }
public ComponentAI GetComponentAI() { //Checks if entity has an AI component if ((mask & ComponentTypes.COMPONENT_AI) == ComponentTypes.COMPONENT_AI) { //Gets AiComponent from entity ComponentAI aiComponent = (ComponentAI)componentList.Find(delegate(IComponent e) { return(e.ComponentType == ComponentTypes.COMPONENT_AI); }); return(aiComponent); } return(null); }
public void OnAction(Entity entity) { if (entity.Name == "Player") { //Delete(entity); } if ((entity.Mask & MASK) == MASK) { List <IComponent> components = entity.Components; IComponent healthComponent = components.Find(delegate(IComponent component) { return(component.ComponentType == ComponentTypes.COMPONENT_HEALTH); }); IComponent ammoComponent = components.Find(delegate(IComponent component) { return(component.ComponentType == ComponentTypes.COMPONENT_AMMO); }); ComponentAI aiComponent = (ComponentAI)components.Find(delegate(IComponent component) { return(component.ComponentType == ComponentTypes.COMPONENT_AI); }); AIStates state = aiComponent.CurrentState; IComponent pickupComponent = components.Find(delegate(IComponent component) { return(component.ComponentType == ComponentTypes.COMPONENT_PICK_UP); }); IComponent aliveComponent = components.Find(delegate(IComponent component) { return(component.ComponentType == ComponentTypes.COMPONENT_ALIVE); }); PowerUp((ComponentHealth)healthComponent, (ComponentAmmo)ammoComponent, (ComponentPickUp)pickupComponent, (ComponentAlive)(aliveComponent)); if (pickupComponent == null && aliveComponent == null) { Delete(entity); } } }
private List <Node> GetPassableNeighbours(ComponentAI ai, Node currentNode) { List <Node> passableNeighbours = new List <Node>(); //Gets all neighbouring nodes of current node List <Node> neighbours = GetNeighbours(ai, currentNode); //Gets all walkable nodes in the neighbouring nodes that are more efficient nodes to use in the path than the currently chosen node foreach (Node neighbour in neighbours) { //Ignores closed nodes if (neighbour.State == NodeState.Closed) { continue; } //Ignores unpassable nodes if (!neighbour.Passable) { continue; } //If node has already been tested, tests to see if traversing the neighbouring node will be more efficient from this node than its parents node, then adds it to passable neighbours if it is if (neighbour.State == NodeState.Open) { float gDistance = new Vector3(neighbour.Location - neighbour.ParentNode.Location).Length; float tempGDistance = currentNode.G + gDistance; if (tempGDistance < neighbour.G) { neighbour.ParentNode = currentNode; passableNeighbours.Add(neighbour); } } //If node is currently untested, adds it to the passable neighbours list and sets it to Open State else { neighbour.ParentNode = currentNode; neighbour.State = NodeState.Open; passableNeighbours.Add(neighbour); } } return(passableNeighbours); }
/// <summary> /// Method to organise the ghost AI target points /// </summary> private void ManageGhostTargets() { // For every ghost in the system AI update its target for (int i = 0; i < NumberOfGhost; i++) { // Gets access to the AI componet and position component to update their values for each AI ComponentAI Ai = (ComponentAI)entityManager.FindEntityWithMask(ComponentTypes.COMPONENT_AI)[i].FindComponent(ComponentTypes.COMPONENT_AI); ComponentPosition Pos = (ComponentPosition)entityManager.FindEntityWithMask(ComponentTypes.COMPONENT_POSITION)[i].FindComponent(ComponentTypes.COMPONENT_POSITION); // If the player is powered up the the target should be the ghost start (makes them run away from the player) if (isPowerUp) { Ai.Target = StartPosition_Ghost; } // If the player is not powered up then the target is the player (the ghosts be hungery) else { Ai.Target = RoundVector(sceneManager.camera.Position); } } }
private void SetRandomPath(ComponentAI ai) { Node currentNode = map[(int)ai.CurrentNode.X, (int)ai.CurrentNode.Y]; ai.Path.Clear(); //Calculates total direct distance between nodes and target node for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { if (i != ai.CurrentNode.X && j != ai.CurrentNode.Y) { map[i, j].H = new Vector3(map[i, j].Location - ai.TargetNodeLocation).Length; } map[i, j].ParentNode = null; map[i, j].State = NodeState.Untested; } } //Returns true if a valid path to the target node can be found bool pathFound = SearchForPath(ai, currentNode); //If path is found, back tracks through the nodes in the path using the parent nodes to retrieve the complete path and then stores in a list from starting node to target node if (pathFound) { Node node = map[(int)ai.TargetNode.X, (int)ai.TargetNode.Y]; while (node.ParentNode != null) { ai.Path.Add(new Vector2(node.mapX, node.mapY)); node = node.ParentNode; } ai.Path.Reverse(); } //Prints out path in console for debugging purposes foreach (Vector2 node in ai.Path) { //Console.WriteLine(node.X + ", " + node.Y); } }
public void MoveToNextNode(ComponentAI ai) { List <Node> PossiblePaths = new List <Node>(); foreach (var node in ai.TargetNode.Neighbours) { if (node == null) { continue; } if (node.Walkable && node != ai.CurrentNode) { PossiblePaths.Add(node); } } var newNode = PossiblePaths[AIManager.Instance.AIRandom.Next(0, PossiblePaths.Count)]; ai.ToNextNode(newNode); }
public void OnAction(Entity entity) { if ((entity.Mask & MASK) == MASK) { List <IComponent> components = entity.Components; IComponent positionComponent = components.Find(delegate(IComponent component) { return(component.ComponentType == ComponentTypes.COMPONENT_POSITION); }); ComponentAI aiComponent = (ComponentAI)components.Find(delegate(IComponent component) { return(component.ComponentType == ComponentTypes.COMPONENT_AI); }); AIStates state = aiComponent.CurrentState; IComponent velocityComponent = components.Find(delegate(IComponent component) { return(component.ComponentType == ComponentTypes.COMPONENT_VELOCITY); }); ComponentRotation rotationComponent = (ComponentRotation)components.Find(delegate(IComponent component) { return(component.ComponentType == ComponentTypes.COMPONENT_ROTATION); }); Vector2 currentRotation = rotationComponent.Rotation.Xz; if (MyGame.NewCameraPosition != new Vector2(0, 0)) { PathFinding((ComponentPosition)positionComponent); } if (path.Count > 0) { FollowPath((ComponentVelocity)velocityComponent, (ComponentPosition)positionComponent); } PlayerDetection((ComponentPosition)positionComponent, (ComponentVelocity)velocityComponent, state); } }
private List <Node> GetNeighbours(ComponentAI ai, Node currentNode) { List <Node> neighbours = new List <Node>(); //Top neighbours.Add(map[(int)currentNode.mapX, (int)currentNode.mapY + 1]); //Bottom neighbours.Add(map[(int)currentNode.mapX, (int)currentNode.mapY - 1]); //Right neighbours.Add(map[(int)currentNode.mapX + 1, (int)currentNode.mapY]); //Left neighbours.Add(map[(int)currentNode.mapX - 1, (int)currentNode.mapY]); //Top Right //neighbours.Add(map[(int)currentNode.mapX + 1, (int)currentNode.mapY + 1]); //Bottom Right //neighbours.Add(map[(int)currentNode.mapX + 1, (int)currentNode.mapY - 1]); //Top Left //neighbours.Add(map[(int)currentNode.mapX - 1, (int)currentNode.mapY + 1]); //Bottom Left //neighbours.Add(map[(int)currentNode.mapX - 1, (int)currentNode.mapY - 1]); return(neighbours); }
private void SetTargetNode(ComponentAI ai) { bool targetSet = false; int randomX = 0; int randomY = 0; //Randomly chooses a target node that is passable on the map grid while (!targetSet) { randomX = rnd.Next(1, rows); randomY = rnd.Next(1, columns); //Ensures that the chosen target node is passable, then sets new target node if (map[randomX, randomY].Passable == true) { ai.TargetNode = new Vector2(randomX, randomY); ai.TargetNodeLocation = map[randomX, randomY].Location; targetSet = true; ai.TargetSet = true; ai.PathNodesTraversed = 0; } } }
public void OnAction() { foreach (Entity entity in entityList) { List <IComponent> components = entity.Components; IComponent transformComponent = components.Find(delegate(IComponent component) { return(component.ComponentType == ComponentTypes.COMPONENT_TRANSFORM); }); IComponent velocityComponent = components.Find(delegate(IComponent component) { return(component.ComponentType == ComponentTypes.COMPONENT_VELOCITY); }); IComponent aiComponent = components.Find(delegate(IComponent component) { return(component.ComponentType == ComponentTypes.COMPONENT_AI); }); if (((ComponentTransform)transformComponent).SetTransform == false) { UpdateTransform((ComponentTransform)transformComponent); ((ComponentTransform)transformComponent).SetTransform = true; } #region AI movement //Checks if the entity has an AI component, then applies movement based on AI path if (aiComponent != null) { ComponentAI ai = ((ComponentAI)aiComponent); float velocity = ((ComponentVelocity)velocityComponent).Velocity; ComponentTransform transform = ((ComponentTransform)transformComponent); ai.CurrentPosition = transform.Translation; Vector3 direction; float angle; if (ai.Disabled != true) { if (ai.CanSeePlayer) { //Finds direction towards target direction = new Vector3(ai.PlayerPosition - transform.Translation).Normalized(); ai.TargetSet = false; ai.NextSet = false; } else { //Finds the direction towards the target node direction = new Vector3(ai.NextNodeLocation - transform.Translation).Normalized(); } //Finds the angle between the target direction and the agent forward vector angle = (float)(Math.Atan2(direction.X, direction.Z) - Math.Atan2(transform.Forward.X, transform.Forward.Z)); //if the angle is over 180 in either direction then invert it to be a smaller angle in the opposite direction if (angle > Math.PI) { angle -= (float)(2 * Math.PI); } if (angle < -Math.PI) { angle += (float)(2 * Math.PI); } //Rotates the agent a fraction of the angle found each frame and moves the agent forward transform.Rotation += new Vector3(0, angle / 5, 0); transform.Translation += transform.Forward * velocity * sceneManager.dt; if (!ai.CanSeePlayer) { //Checks if entity has reached the next node then sets current node to the next node causing the AI system to update to a new next node if ((int)(transform.Translation.X + 0.4f) == ai.NextNodeLocation.X && transform.Translation.Y == ai.NextNodeLocation.Y && (int)(transform.Translation.Z + 0.4f) == ai.NextNodeLocation.Z) { ai.CurrentNode = ai.NextNode; } //Checks if entity has reached the target node then sets current node to the target node causing the AI system to update to a new target node if ((int)(transform.Translation.X + 0.4f) == ai.TargetNodeLocation.X && (int)(transform.Translation.Y) == ai.TargetNodeLocation.Y && (int)(transform.Translation.Z + 0.4f) == ai.TargetNodeLocation.Z) { ai.CurrentNode = ai.TargetNode; } } } } #endregion UpdateTransform((ComponentTransform)transformComponent); } }