Пример #1
0
 /// <summary>
 /// Constructor of an edge
 /// </summary>
 /// <param name="node1">node 1 where node 1 != node 2</param>
 /// <param name="node2">node 2 where node 2 != node 1</param>
 /// <param name="edgeWeight">Initial weight of the edge ( a higher number is less attractive to the AI )</param>
 public Edge(Node node1, Node node2, float edgeWeight)
 {
     this.node1 = node1;
     this.node2 = node2;
     distance = (node1.Position - node2.Position).Length();   //precompute heuristic so that the run-time of the game is spead up
     weight = edgeWeight;
 }
Пример #2
0
 /// <summary>
 /// Method to establish connection to another node.
 /// </summary>
 /// <param name="anotherNode">Node not the same instance as the node the method is invoked on</param>
 /// <param name="weightOfConnection">Weight of the established connection (not the distance, but a higher number will result in the edge being less desirable for the AI</param>
 /// <param name="distanceToNode">Sets the distance</param>
 public void connectToNode(Node anotherNode, float weightOfConnection, float distanceToNode)
 {
     connectToNode(anotherNode, weightOfConnection);
     foreach (Edge e in this.connectedEdges)
         if (e.node1 == anotherNode || e.node2 == anotherNode)
             e.distance = distanceToNode;
 }
Пример #3
0
 /// <summary>
 /// Method to establish connection to another node.
 /// </summary>
 /// <param name="anotherNode">Node not the same instance as the node the method is invoked on</param>
 /// <param name="weightOfConnection">Weight of the established connection (not the distance, but a higher number will result in the edge being less desirable for the AI</param>
 public void connectToNode(Node anotherNode, float weightOfConnection)
 {
     if (anotherNode != this)
     {
         foreach (Edge e in this.connectedEdges)
             if (e.node1 == anotherNode || e.node2 == anotherNode)
                 return;         //already connected
         Edge conn = new Edge(this, anotherNode, weightOfConnection);
         //Bidirectional edge:
         connectedEdges.Add(conn);
         anotherNode.connectedEdges.Add(conn);
     }
 }
Пример #4
0
        /// <summary>
        /// Method to load a map
        /// </summary>
        /// <param name="filename">file name of map</param>
        /// <param name="contentMgr">content manager instance</param>
        /// <param name="gfxDevice">graphics device instance</param>
        public static void loadMap(String filename, ContentManager contentMgr, GraphicsDevice gfxDevice)
        {
            XmlReader reader = XmlReader.Create(filename);
            XPathDocument docNav = new XPathDocument(reader);
            XPathNavigator nav = docNav.CreateNavigator();
            XmlNamespaceManager nsmanager = new XmlNamespaceManager(nav.NameTable);
            XPathNodeIterator iter;
            XPathNavigator mapIter = nav.SelectSingleNode("/Map");
            mapRadius = Convert.ToSingle(mapIter.GetAttribute("mapRadius", nsmanager.DefaultNamespace));

            XPathNavigator skyboxIter = nav.SelectSingleNode("/Map/Skybox");
            String texName = skyboxIter.GetAttribute("texture", nsmanager.DefaultNamespace);
            skyBoxRepeat = Convert.ToSingle(skyboxIter.GetAttribute("repeat", nsmanager.DefaultNamespace));
            SetUpSkyBox(gfxDevice, contentMgr, texName, Convert.ToString(skyBoxRepeat));
            //Now read in path nodes:
            iter = nav.Select("/Map/Marker[@className!='SpawnPoint' and @className!='PlayerSpawnPoint']");
            while (iter.MoveNext())
            {
                Node n = new Node();
                readMarkerData(contentMgr, reader, docNav, nav, nsmanager, iter, n);
                content.Add(n.id, n);
            }
            //Read spawnpoints:
            iter = nav.Select("/Map/Marker[@className='SpawnPoint']");
            while (iter.MoveNext())
            {
                SpawnPoint n = new SpawnPoint();
                readMarkerData(contentMgr, reader, docNav, nav, nsmanager, iter, n);
                content.Add(n.id, n);
            }
            //Read player spawnpoints:
            iter = nav.Select("/Map/Marker[@className='PlayerSpawnPoint']");
            while (iter.MoveNext())
            {
                SpawnPoint n = new PlayerSpawnPoint();
                readMarkerData(contentMgr, reader, docNav, nav, nsmanager, iter, n);
                content.Add(n.id, n);
            }
            //Now read other content:
            iter = nav.Select("/Map/ContentItem");
            while (iter.MoveNext())
            {
                Drawer n = new Drawer(false);
                n.contentLoader = contentMgr;
                readObjectData(contentMgr, reader, docNav, nav, nsmanager, iter, n);
            }
            List<Edge> edgeList = new List<Edge>();
            List<float> edgeDistances = new List<float>();
            iter = nav.Select("/Map/PathEdge");
            while (iter.MoveNext())
            {
                float weight = Convert.ToSingle(iter.Current.GetAttribute("weight", nsmanager.DefaultNamespace));
                float distance = Convert.ToSingle(iter.Current.GetAttribute("distance", nsmanager.DefaultNamespace));
                String firstId = iter.Current.SelectSingleNode("firstNodeId").Value;
                String secondId = iter.Current.SelectSingleNode("secondNodeId").Value;
                Node first = null, second = null;
                foreach (Object item in content.Values)
                    if (item is Node)
                    {
                        if ((item as Marker).id == firstId)
                            first = item as Node;
                        else if ((item as Marker).id == secondId)
                            second = item as Node;
                        if (first != null && second != null)
                            break;
                    }
                edgeList.Add(new Edge(first, second, weight));
                edgeDistances.Add(distance);
            }
            //Connect nodes:
            for (int i = 0; i < edgeList.Count; i++)
            {
                Edge item = edgeList.ElementAt(i);
                float distance = edgeDistances.ElementAt(i);
                item.node1.connectToNode(item.node2, item.weight, distance);
            }
            reader.Close();
        }
Пример #5
0
 /// <summary>
 /// Method to disconnect another node
 /// </summary>
 /// <param name="otherNode">node to disconnect</param>
 public void disconnectFromNode(Node otherNode)
 {
     if (otherNode == this) return;
     Edge foundEdge = null;
     foreach (Edge e in this.connectedEdges)
         if (e.node1 == otherNode || e.node2 == otherNode)
         {
             foundEdge = e;
             break;
         }
     if (foundEdge != null)
     {
         foundEdge.node1.connectedEdges.Remove(foundEdge);
         foundEdge.node2.connectedEdges.Remove(foundEdge);
     }
 }
Пример #6
0
        /// <summary>
        /// A* path finding algorithm.
        /// </summary>
        /// <param name="start">Start node</param>
        /// <param name="end">End node</param>
        /// <returns>Path to end node if one is found, otherwise null</returns>
        public List<Node> AStar(Node start, Node end, bool addRandomFactor)
        {
            if (start == end || start == null || end == null) return null;
            List<Node> openList = new List<Node>();
            List<Node> visitedList = new List<Node>();
            openList.Add(start);
            start.heuristic = (end.Position - start.Position).Length(); //calculate heuristic
            while (openList.Count > 0)  //while we have more nodes to explore
            {
                Node bestChoice = openList.ElementAt<Node>(0);
                //get the best node choice:
                foreach (Node node in openList)
                    if (bestChoice.pathCost + bestChoice.heuristic > node.pathCost + node.heuristic)
                    {
                        bestChoice = node;
                        break;
                    }
                //move best choice to visited list
                visitedList.Add(bestChoice);
                bestChoice.hasBeenVisited = true;
                openList.Remove(bestChoice);

                if (bestChoice == end) //REACHED DESTINATION!!!
                {

                    List<Node> result = new List<Node>();

                    result.Add(end);
                    Node it = (end.edgeToPrevNode.node1 == end) ? end.edgeToPrevNode.node2 : end.edgeToPrevNode.node1;

                    while (it != null)
                    {
                        result.Add(it);
                        if (it.edgeToPrevNode != null)
                            it = (it.edgeToPrevNode.node1 == it) ? it.edgeToPrevNode.node2 : it.edgeToPrevNode.node1;
                        else
                            it = null;
                    }
                    //Finally clear node data for the next iteration of the A*:
                    foreach (Node node in visitedList)
                        node.clear();

                    return result;
                }
                //Not yet at destination so we look at the best choice's neighbours:
                foreach (Edge neighbourEdge in bestChoice.connectedEdges)
                {
                    Node neighbour = (neighbourEdge.node1 == bestChoice) ? neighbourEdge.node2 : neighbourEdge.node1;
                    if (neighbour.hasBeenVisited) continue;
                    visitedList.Add(neighbour);
                    Random randomizer = new Random();
                    double distToNeighbour = bestChoice.pathCost + (addRandomFactor ?
                        neighbourEdge.distance + neighbourEdge.weight + randomizer.NextDouble() * ASTAR_RANDOM_FACTOR * neighbourEdge.distance : neighbourEdge.distance + neighbourEdge.weight);
                    double newMoveLength = distToNeighbour + bestChoice.pathCost;
                    neighbour.heuristic = (neighbour.Position - end.Position).Length();
                    Boolean shouldMove = false;

                    if (openList.IndexOf(neighbour) < 0)
                    {
                        openList.Add(neighbour);
                        shouldMove = true;
                    }
                    else if (distToNeighbour < neighbour.pathCost)
                        shouldMove = true;
                    else
                        shouldMove = false;

                    if (shouldMove == true)
                    {
                        neighbour.edgeToPrevNode = neighbourEdge;
                        neighbour.pathCost = distToNeighbour;
                    }
                }
            }
            return null; //Not found
        }
Пример #7
0
 /// <summary>
 /// Sets a new path for an object if it is already registered
 /// </summary>
 /// <param name="AIObject">Any registered dynamic object</param>
 /// <param name="start">Start node (should be close to the object if possible)</param>
 /// <param name="end">End node</param>
 public void setNewPathForRegisteredObject(DynamicObject AIObject, Node start, Node end)
 {
     if (objectPaths.Keys.Contains(AIObject))
     {
         List<Node> path = AStar(start, end, AIObject is Destroyer);
         if (path != null)
             objectPaths[AIObject].remainingPath = path;
         else //we just go the the start node
         {
             path = new List<Node>();
             path.Add(start);
             objectPaths[AIObject].remainingPath = path;
         }
     }
 }
Пример #8
0
 /// <summary>
 /// Method to update remaining path variables when an object reaches its waypoint
 /// </summary>
 internal void reachedWaypoint()
 {
     if (objectRemainingPath != null) //if there is a path
     {
         if (objectRemainingPath.Count > 1) //if we have not reached our destination yet
         {
             previousNode = objectRemainingPath.Last();
             objectRemainingPath.Remove(objectRemainingPath.Last());
             currentWaypoint = objectRemainingPath.Last();
             calculateCurrentEdge();
         }
         else //the destination have been reached
         {
             previousNode = null;
             objectRemainingPath.Clear();
             currentWaypoint = null;
             currentEdge = null;
         }
     }
 }