/// <summary>
 /// Organizes Units by X Y Z coordinates
 /// More efficient to recreate a tree rather than update it
 /// </summary>
 /// <param name="ParentSplitDimensionIndex">Outside of this constructor, inputs should be -1</param>
 /// <param name="UnitList">Should be converted from a List</param>
 public Unit_KDTree(int ParentSplitDimensionIndex, Unit[] UnitList)
 {
     SplitDimensionIndex = (ParentSplitDimensionIndex + 1) % 3;
     if (UnitList.Length > 2)
     {
         int MedianIndex = UnitList.Length / 2;
         PartialSortListAt(MedianIndex, SplitDimensionIndex, ref UnitList);
         SplitPosition = UnitList[MedianIndex].IndexablePosition[SplitDimensionIndex];
         Unit[] LowerList = new Unit[MedianIndex + 1];
         Unit[] UpperList = new Unit[UnitList.Length - MedianIndex - 1];
         Array.Copy(UnitList, 0, LowerList, 0, LowerList.Length);
         Array.Copy(UnitList, MedianIndex + 1, UpperList, 0, UpperList.Length);
         LessEqualNode = new Unit_KDTree(SplitDimensionIndex, LowerList);
         GreaterNode = new Unit_KDTree(SplitDimensionIndex, UpperList);
     }
     else
     {
         Constituents = UnitList;
         isLeafNode = true;
     }
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="Searcher"></param>
 /// <param name="Closest">Can be a null input</param>
 /// <param name="Distance">Can be up to float.PositiveInfinity</param>
 public void FindNearestUnit(Unit Searcher, ref Unit Closest, ref float Distance)
 {
     if (isLeafNode)
     {
         for (int i = 0; i < Constituents.Length; i++)
         {
             if (Constituents[i].HitPoints > 0.0)
             {
                 float tempDistance = (Constituents[i].Position - Searcher.Position).Length();
                 if (tempDistance < Distance)
                 {
                     Closest = Constituents[i];
                     Distance = tempDistance;
                 }
             }
         }
     }
     else
     {
         if (Searcher.IndexablePosition[SplitDimensionIndex] > SplitPosition)
         {
             GreaterNode.FindNearestUnit(Searcher, ref Closest, ref Distance);
             if (Searcher.IndexablePosition[SplitDimensionIndex] - Distance < SplitPosition)
             {
                 LessEqualNode.FindNearestUnit(Searcher, ref Closest, ref Distance);
             }
         }
         else
         {
             LessEqualNode.FindNearestUnit(Searcher, ref Closest, ref Distance);
             if (Searcher.IndexablePosition[SplitDimensionIndex] + Distance > SplitPosition)
             {
                 GreaterNode.FindNearestUnit(Searcher, ref Closest, ref Distance);
             }
         }
     }
 }
 /// <summary>
 /// (Obsolete) Performs a Merge Sort on the Unsorted list based on the DimensionIndex 
 /// </summary>
 private static void SortByDimension(ref Unit[] Unsorted, int DimensionIndex)
 {
     if (Unsorted.Length > 0)
     {
         List<List<Unit>> Sorter = new List<List<Unit>>();
         for (int i = 0; i < Unsorted.Length; i++)
         {
             Sorter.Add(new List<Unit>());
             Sorter[i].Add(Unsorted[i]);
         }
         while (Sorter.Count > 1)
         {
             for (int i = 0; i < Sorter.Count - 1; i++)
             {
                 for (int a = 0; a < Sorter[i].Count; a++)
                 {
                     for (int b = 0; b < Sorter[i + 1].Count; b++)
                     {
                         if (Sorter[i + 1][b].IndexablePosition[DimensionIndex] < Sorter[i][a].IndexablePosition[DimensionIndex])
                         {
                             Sorter[i].Insert(a++, Sorter[i + 1][b]);
                             Sorter[i + 1].RemoveAt(b--);
                         }
                     }
                 }
                 Sorter[i].AddRange(Sorter[i + 1]);
                 Sorter.RemoveAt(i + 1);
             }
         }
         Unsorted = Sorter[0].ToArray();
     }
 }
 /// <summary>
 /// Performs a modified reflexive Quick Sort on the Unsorted list while looking for the specified Index
 /// A majority of the data should not be sorted in the process
 /// </summary>
 private static void PartialSortListAt(int Index, int DimensionIndex, ref Unit[] Unsorted)
 {
     if (Unsorted.Length > 3)
     {
         Unit[] PartialSorted = new Unit[Unsorted.Length];
         //Find an approximate median of the Unsorted data using the median of three method
         //Keep track of the Pivot's index since it must be ignored while sorting
         int[] MedianOfThreeIndices = new int[] {
             MyGame.random.Next(Unsorted.Length)
             , MyGame.random.Next(Unsorted.Length)
             , MyGame.random.Next(Unsorted.Length) };
         PartialSorted[0] = Unsorted[MedianOfThreeIndices[0]];
         PartialSorted[1] = Unsorted[MedianOfThreeIndices[1]];
         PartialSorted[2] = Unsorted[MedianOfThreeIndices[2]];
         Unit Pivot = Unsorted[MyGame.random.Next(Unsorted.Length)];
         int PivotIndex;
         if (PartialSorted[0].IndexablePosition[DimensionIndex] <= PartialSorted[1].IndexablePosition[DimensionIndex]
             && PartialSorted[0].IndexablePosition[DimensionIndex] > PartialSorted[2].IndexablePosition[DimensionIndex])
         {
             Pivot = PartialSorted[0];
             PivotIndex = MedianOfThreeIndices[0];
         }
         else if (PartialSorted[1].IndexablePosition[DimensionIndex] <= PartialSorted[0].IndexablePosition[DimensionIndex]
             && PartialSorted[1].IndexablePosition[DimensionIndex] > PartialSorted[2].IndexablePosition[DimensionIndex])
         {
             Pivot = PartialSorted[1];
             PivotIndex = MedianOfThreeIndices[1];
         }
         else
         {
             Pivot = PartialSorted[2];
             PivotIndex = MedianOfThreeIndices[2];
         }
         //Sort the Pivot into its correct location, ignoring the Pivot itself
         int StartCounter = 0;
         int EndCounter = Unsorted.Length - 1;
         for (int i = 0; i < PivotIndex; i++)
         {
             if (Unsorted[i].IndexablePosition[DimensionIndex] > Pivot.IndexablePosition[DimensionIndex])
             {
                 PartialSorted[EndCounter--] = Unsorted[i];
             }
             else
             {
                 PartialSorted[StartCounter++] = Unsorted[i];
             }
         }
         for (int i = PivotIndex + 1; i < Unsorted.Length; i++)
         {
             if (Unsorted[i].IndexablePosition[DimensionIndex] > Pivot.IndexablePosition[DimensionIndex])
             {
                 PartialSorted[EndCounter--] = Unsorted[i];
             }
             else
             {
                 PartialSorted[StartCounter++] = Unsorted[i];
             }
         }
         //Check to see if the code is working properly
         if (StartCounter != EndCounter)
         {
             throw new Exception("Index preceding the pivot is not equal to the index after the pivot");
         }
         else
         {
             PartialSorted[StartCounter] = Pivot;
         }
         Unsorted = PartialSorted;
         //Grab the a section of the array for further sorting to find the specified Index
         if (StartCounter == Index)
         {
             return;
         }
         else if (Index > StartCounter)
         {
             PartialSorted = new Unit[Unsorted.Length - StartCounter - 1];
             Array.Copy(Unsorted, StartCounter + 1, PartialSorted, 0, PartialSorted.Length);
             PartialSortListAt(Index - StartCounter - 1, DimensionIndex, ref PartialSorted);
             Array.Copy(PartialSorted, 0, Unsorted, StartCounter + 1, PartialSorted.Length);
         }
         else
         {
             PartialSorted = new Unit[StartCounter];
             Array.Copy(Unsorted, 0, PartialSorted, 0, PartialSorted.Length);
             PartialSortListAt(Index, DimensionIndex, ref PartialSorted);
             Array.Copy(PartialSorted, 0, Unsorted, 0, PartialSorted.Length);
         }
     }
     else
     {
         //Merge sort the ones that are too small
         SortByDimension(ref Unsorted, DimensionIndex);
     }
 }
 public void InsertUnit(Unit Newbie)
 {
     if (isLeafNode)
     {
         Array.Resize<Unit>(ref Constituents, Constituents.Length + 1);
         Constituents[Constituents.Length - 1] = Newbie;
     }
     else
     {
         if (Newbie.IndexablePosition[SplitDimensionIndex] > SplitPosition)
         {
             GreaterNode.InsertUnit(Newbie);
         }
         else
         {
             LessEqualNode.InsertUnit(Newbie);
         }
     }
 }
Esempio n. 6
0
 /// <summary>
 /// With BuddyUp, the Unit moves (with a bias) towards the first ally Unit it encounters
 /// The unit still targets the closest enemy Unit
 /// </summary>
 private void Behavior_BuddyUp(GameTime gameTime, List<Unit_KDTree> EnemyTrees, Unit_KDTree AllyTree)
 {
     DirectionTimer -= gameTime.ElapsedGameTime.TotalSeconds;
     if (DirectionTimer <= 0.0)
     {
         DirectionTimer = 3.0;
         TargetPosition = Manager.terrain.GetRandomPosition();
     }
     if (OtherTarget == null || OtherTarget.HitPoints <= 0.0)
     {
         OtherTarget = null;
         Distance = float.PositiveInfinity;
         AllyTree.FindNearestUnit(this, ref OtherTarget, ref Distance);
     }
     else
     {
         TargetPosition = Vector3.Lerp(TargetPosition, OtherTarget.Position, (float)gameTime.ElapsedGameTime.TotalSeconds);
     }
     Move(gameTime);
     Attack(gameTime, EnemyTrees);
 }
Esempio n. 7
0
 private void Attack(GameTime gameTime, List<Unit_KDTree> EnemyTrees)
 {
     AttackTimer -= gameTime.ElapsedGameTime.TotalSeconds;
     if (AttackTimer <= 0.0)
     {
         AttackTimer = 0.1;
         if (Target == null || Target.HitPoints <= 0.0 || (Target.Position - Position).Length() > Range)
         {
             Target = null;
             Distance = Range;
             for (int i = 0; i < EnemyTrees.Count; i++)
             {
                 EnemyTrees[i].FindNearestUnit(this, ref Target, ref Distance);
             }
             if (Target != null)
             {
                 Target.HitPoints -= Damage;
             }
         }
         else
         {
             Target.HitPoints -= Damage;
         }
     }
 }