Example #1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="NPCUnit"/> class. 
 /// </summary>
 /// <param name="id"> The id of the unit.  </param>
 /// <param name="name"> The name.  </param>
 /// <param name="position"> The position of the unit.  </param>
 /// <param name="sprite"> The sprite. </param>
 /// <param name="unitClass"> The class of the unit. </param>
 public NPCUnit(int id, string name, Vector position, AnimatedSprite sprite, UnitClass unitClass)
     : base(id, name, position, sprite, unitClass)
 {
 }
Example #2
0
        /// <summary>
        /// Finds the shortest path between the start vector and the goal vector,
        /// taking into account whether the unit can actually get there or not.
        /// A* pathfinding.
        /// </summary>
        /// <param name="start"> The vector to start the search from. </param>
        /// <param name="goal"> The vector to end the search at. </param>
        /// <param name="unit"> The unit that is trying to find the route. </param>
        /// <param name="dataMap"> The data map. </param>
        /// <returns>
        /// A list representing the shortest path.
        /// </returns>
        public static List<Vector> FindShortestPathWithinReach(Vector start, Vector goal, Unit unit, MapData dataMap)
        {
            // Set stuff up
            var closedList = new List<Vector>();
            var openList = new List<Vector>();
            var openListQueue = new PriorityQueue<Vector, int>();

            var newStart = start;
            newStart.CameFrom = null;
            newStart.GScore = 0;
            newStart.FScore = newStart.GScore + CostEstimate(newStart, goal);

            openList.Add(newStart);
            openListQueue.Enqueue(newStart);

            if (newStart.Equals(goal))
            {
                return openList;
            }

            // While the queue isn't empty ...
            while (!openListQueue.Empty)
            {
                // ... get highest prioritied point
                var current = openListQueue.Dequeue();
                openList.Remove(current);

                if (current.Equals(goal))
                {
                    return RetracePath(current);
                }

                closedList.Add(current);

                // Iterates over nearby points
                foreach (var neighbor in NeighborNodes(current))
                {
                    // If the point has been visited, ignore it
                    if (closedList.Contains(neighbor))
                    {
                        continue;
                    }

                    // If it hasn't been visited and the unit can reach it, add it
                    // to the list.
                    if (!openList.Contains(neighbor)
                        && dataMap.WithinMapAndCanTraverse(neighbor.X, neighbor.Y, unit)
                        && CostEstimate(unit.Location, neighbor) <= unit.MoveRange)
                    {
                            neighbor.CameFrom = current;
                            neighbor.GScore = current.GScore + 1;
                            neighbor.FScore = newStart.GScore + CostEstimate(neighbor, goal);

                            openList.Add(neighbor);
                            openListQueue.Enqueue(neighbor);
                    }
                }
            }

            return openList;
        }
Example #3
0
 /// <summary>
 /// Finds the shortest path for the unit from the unit's position
 /// to the target vector.
 /// </summary>
 /// <param name="unit"> The unit. </param>
 /// <param name="target"> The target position. </param>
 /// <returns>
 /// A list containing the Vectors that make up the shortest path from
 /// the unit's position to the vector.
 /// </returns>
 public List<Vector> FindShortestPathWithinReach(Unit unit, Vector target)
 {
     var start = new Vector(unit.Location.X, unit.Location.Y);
     return PathFinding.FindShortestPathWithinReach(start, target, unit, this.dataMap);
 }
Example #4
0
        /// <summary>
        /// Calculates the steps it takes to move from start to target.
        /// </summary>
        /// <param name="start"> The start location. </param>
        /// <param name="target"> The target location. </param>
        /// <returns>
        /// The amount of steps it takes.
        /// </returns>
        private static int CostEstimate(Vector start, Vector target)
        {
            var temp = new Vector(start.X, start.Y);
            var cost = 0;

            while (!temp.Equals(target))
            {
                if (temp.X > target.X)
                {
                    temp = new Vector(temp.X - 1, temp.Y);
                    cost++;
                }
                else if (temp.X < target.X)
                {
                    temp = new Vector(temp.X + 1, temp.Y);
                    cost++;
                }

                if (temp.Y > target.Y)
                {
                    temp = new Vector(temp.X, temp.Y - 1);
                    cost++;
                }
                else if (temp.Y < target.Y)
                {
                    temp = new Vector(temp.X, temp.Y + 1);
                    cost++;
                }
            }

            return cost;
        }
Example #5
0
        /// <summary>
        /// Traces the path back to construct the shortest route.
        /// </summary>
        /// <param name="retraceFrom"> The vector to retrace from. </param>
        /// <returns>
        /// A list that represents the shortest path found.
        /// </returns>
        private static List<Vector> RetracePath(Vector retraceFrom)
        {
            var tempList = new List<Vector>();
            var tempNode = retraceFrom.CameFrom;
            var maxRuns = 0;

            while (maxRuns < 500)
            {
                tempList.Add(tempNode);

                if (tempNode.CameFrom == null)
                {
                    break;
                }

                tempNode = tempNode.CameFrom;
                maxRuns++;
            }

            return tempList;
        }
Example #6
0
        /// <summary>
        /// Finds the nodes that are just around the input node.
        /// </summary>
        /// <param name="node"> The node to find the neighbors for. </param>
        /// <returns>
        /// A list of the neighbor nodes.
        /// </returns>
        public static List<Vector> NeighborNodes(Vector node)
        {
            var neighbors = new List<Vector>
                {
                    new Vector(node.X - 1, node.Y),
                    new Vector(node.X, node.Y - 1),
                    new Vector(node.X + 1, node.Y),
                    new Vector(node.X, node.Y + 1)
                };

            return neighbors;
        }
Example #7
0
        /// <summary>
        /// Finds the areas the unit can move to.
        /// </summary>
        /// <param name="unit"> The unit.  </param>
        /// <param name="dataMapData"> The datamap.  </param>
        /// <returns>
        /// The list of vectors.
        /// </returns>
        public static List<Vector> MarkValidMoves(Unit unit, MapData dataMapData)
        {
            var startVector = new Vector(unit.Location.X, unit.Location.Y);

            var validMovesList = new List<Vector>();
            var validMoves = new LinkedList<Vector>();

            validMovesList.Add(startVector);
            validMoves.AddFirst(startVector);

            // While there are places left to check ...
            while (validMoves.Count > 0)
            {
                // ... get the first move
                var moveNode = validMoves.First.Value;
                validMoves.RemoveFirst();

                // Find further possible moves
                foreach (var neighborNode in NeighborNodes(moveNode))
                {
                    var tempVector = new Vector(neighborNode.X, neighborNode.Y);

                    // If the point has been visited, ignore it
                    if (validMovesList.Contains(tempVector) ||
                        !unit.PointWithinMoveRange(tempVector))
                    {
                        continue;
                    }

                    // If the unit can move there ...
                    if (dataMapData.WithinMapMoveRangeAndCanTraverse(tempVector.X, tempVector.Y, unit))
                    {
                        // ... add it to the list.
                        validMoves.AddLast(tempVector);
                        validMovesList.Add(tempVector);
                    }
                }
            }

            return validMovesList;
        }
Example #8
0
        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        /// A new object that is a copy of this instance.
        /// </returns>
        public object Clone()
        {
            var tempVector = new Vector(this.X, this.Y)
                {
                    GScore = this.GScore,
                    FScore = this.FScore,
                    CameFrom = this.CameFrom
                };

            return tempVector;
        }
Example #9
0
        /// <summary>
        /// Moves the selected unit to the clicked location, assuming the location
        /// is within range of the unit.
        /// </summary>
        /// <param name="level"> The level. </param>
        private void MoveUnit(Level level)
        {
            if (InputHandler.LeftMouseClicked()
                && this.unitSelected
                && !this.justClicked)
            {
                // Note! MouseState.X is the horizontal position and MouseState.Y is the vertical position.
                // I want Y to be the horizontal coordinate (the width) and X to be the vertical coordinate
                // (the height), so tileY is using the X values and tileX is using the Y values.
                var tileY = (int)(InputHandler.MouseState.X + level.Camera.Position.X) / Engine.TileHeight;
                var tileX = (int)(InputHandler.MouseState.Y + level.Camera.Position.Y) / Engine.TileWidth;

                var tempVector = new Vector(tileX, tileY);

                // Checks if the chosen tile is occupied or not.
                if (!level.LevelMap.IsOccupied(tileX, tileY)
                    && this.selectedUnit.CanTraverse(level.LevelMap.GetCollisionType(tileX, tileY))
                    && this.selectedUnit.PointWithinMoveRange(tempVector))
                {
                    var pathToTarget = level.LevelMap.FindShortestPathWithinReach(this.selectedUnit, tempVector).Count;
                    if (pathToTarget != 0 && pathToTarget <= this.selectedUnit.MoveRange)
                    {
                        // Removes the unit from the list, as we need to change the
                        // position of the unit.
                        this.PlayerUnits.Remove(this.selectedUnit);

                        // Notifies the map that the unit is disappearing from its current
                        // location.
                        level.LevelMap.MoveUnitAway(this.selectedUnit, level);

                        // Changes the unit's location.
                        this.selectedUnit.Location = (Vector)tempVector.Clone();
                        this.selectedUnit.MoveUnit();

                        // Notifies the map that the unit has arrived at its target
                        // location and adds the unit to the unit list again.
                        level.LevelMap.MoveUnitToNewPosition(this.selectedUnit);
                        this.PlayerUnits.Add(this.selectedUnit);

                        this.unitSelected = false;
                        this.selectedUnit = null;
                    }
                }

                // Ensures that other parts in the update method won't be triggered.
                this.justClicked = true;
            }
        }
Example #10
0
        /// <summary>
        /// Checks if a location is within the map, if the location is within the
        /// move range of the unit and if the unit can traverse the position.
        /// </summary>
        /// <param name="x"> The x coordinate to check. </param>
        /// <param name="y"> The y coordinate to check. </param>
        /// <param name="unit"> The unit. </param>
        /// <returns>
        /// True if the above conditions are fulfilled.
        /// </returns>
        public bool WithinMapMoveRangeAndCanTraverse(int x, int y, Unit unit)
        {
            var tempVector = new Vector(x, y);

            if (this.WithinMap(x, y) &&
                unit.PointWithinMoveRange(tempVector))
            {
                var test2 = PathFinding.FindShortestPathWithinReach(unit.Location, tempVector, unit, this);

                if (unit.CanTraverse(this.GetCollisionType(x, y)) &&
                    test2.Count <= unit.MoveRange)
                {
                    return true;
                }
            }

            return false;
        }