예제 #1
0
        private bool SearchForPath(cAI 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
            currentNode.State = NodeState.Closed;
            List <Node> passableNeighbours = GetPassableNeighbours(ai, currentNode);

            passableNeighbours.Sort((node1, node2) => node1.F.CompareTo(node2.F));

            //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);
        }
예제 #2
0
        private void SetNextNode(cAI ai)
        {
            //Updates current node location then finds next node in the path and sets it as the next node
            ai.CurrentNodeLocation = ai.NextNodeLocation;

            //Ensures path has at least more than one value in it or finds another target and path
            if (ai.Path.Count() > 1)
            {
                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;
            }
            else
            {
                SetTargetNode(ai);
                SetRandomPath(ai);
            }
        }
예제 #3
0
        private List <Node> GetPassableNeighbours(cAI 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);
        }
예제 #4
0
        private void SetRandomPath(cAI 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();
                ai.PathSet = true;
            }

            //Prints out path in console for debugging purposes
            foreach (Vector2 node in ai.Path)
            {
                //Console.WriteLine(node.X + ", " + node.Y);
            }
        }
예제 #5
0
        private void SetTargetNode(cAI 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;
                }
            }
        }
예제 #6
0
        private List <Node> GetNeighbours(cAI ai, Node currentNode)
        {
            List <Node> neighbours = new List <Node>();

            //Gets neighbour above current node
            if (currentNode.Directions.Contains(NodeDirection.Up))
            {
                neighbours.Add(map[(int)currentNode.mapX, (int)currentNode.mapY + 1]);
            }
            //Gets neighbour below current node
            if (currentNode.Directions.Contains(NodeDirection.Down))
            {
                neighbours.Add(map[(int)currentNode.mapX, (int)currentNode.mapY - 1]);
            }
            //Gets neighbour right of current node
            if (currentNode.Directions.Contains(NodeDirection.Right))
            {
                neighbours.Add(map[(int)currentNode.mapX + 1, (int)currentNode.mapY]);
            }
            //Gets neighbour left of current node
            if (currentNode.Directions.Contains(NodeDirection.Left))
            {
                neighbours.Add(map[(int)currentNode.mapX - 1, (int)currentNode.mapY]);
            }

            //Diagonal movement
            //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);
        }
예제 #7
0
        public void OnAction()
        {
            foreach (oEntity entity in entityList)
            {
                //Retrieves list of components from current entity
                List <IComponent> components = entity.Components;

                //Retrieves transform component from current entity
                IComponent transformComponent = components.Find(delegate(IComponent component)
                {
                    return(component.ComponentMask == ComponentMasks.COMPONENT_TRANSFORM);
                });

                //Sets transform if not already set
                if (((cTransform)transformComponent).SetTransform == false)
                {
                    UpdateTransform((cTransform)transformComponent);
                    ((cTransform)transformComponent).SetTransform = true;
                }

                //Retrieves speed component from current entity
                IComponent speedComponent = components.Find(delegate(IComponent component)
                {
                    return(component.ComponentMask == ComponentMasks.COMPONENT_SPEED);
                });

                //Retrieves AI component from current entity
                IComponent aiComponent = components.Find(delegate(IComponent component)
                {
                    return(component.ComponentMask == ComponentMasks.COMPONENT_AI);
                });


                #region AI movement
                //Checks if the entity has an AI component, then applies movement based on AI path
                if (aiComponent != null && ((cAI)aiComponent).DestinationReached != true)
                {
                    cAI        ai        = ((cAI)aiComponent);
                    float      velocity  = ((cSpeed)speedComponent).Speed;
                    cTransform transform = ((cTransform)transformComponent);
                    Vector3    direction;
                    float      angle;

                    //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.Right.X, transform.Right.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 towards the target location if not facing it
                    transform.Rotation += new Vector3(0, angle, 0);

                    //Moves agent towards target location
                    transform.Translation += transform.Right * velocity * sceneManager.dt;

                    //Checks if entity is moving left
                    if (direction.X < -0.3f)
                    {
                        //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 ((transform.Translation.X) < (ai.NextNodeLocation.X + 0.1f))
                        {
                            ai.CurrentNode = ai.NextNode;
                        }
                    }
                    //Checks if entity is moving down
                    else if (direction.Z < -0.3f)
                    {
                        //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 ((transform.Translation.Z) < (ai.NextNodeLocation.Z + 0.1f))
                        {
                            ai.CurrentNode = ai.NextNode;
                        }
                    }
                    else
                    {
                        //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.1f) == ai.NextNodeLocation.X && (int)(transform.Translation.Z + 0.1f) == ai.NextNodeLocation.Z)
                        {
                            ai.CurrentNode = ai.NextNode;
                        }
                    }
                }
                #endregion

                //Updates transform of entity every frame
                UpdateTransform((cTransform)transformComponent);
            }
        }