Advertisement
Guest User

Untitled

a guest
Jun 26th, 2016
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.24 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Diagnostics;
  7. using Duality;
  8. using Duality.Resources;
  9. using Duality.Components;
  10. using Duality.Input;
  11.  
  12. using static Tutorial.Game;
  13. //using static Duality.MathF;
  14.  
  15. namespace Tutorial
  16. {
  17.     public class UnitHandlerCollisionHash : Component, ICmpUpdatable, ICmpInitializable
  18.     {
  19.         public Grid<List<Unit>> Hash { get; set; } = new Grid<List<Unit>>(20, 20);
  20.  
  21.         public int HashWidth { get; set; } = 20;
  22.         public int HashHeight { get; set; } = 20;
  23.  
  24.         public int HashGridSize { get; set; } = G * 3;
  25.         public Rect hashBoundaries;
  26.         float interval = 30;
  27.         float timer = 0;
  28.  
  29.         int collisionChecks = 0;
  30.         int collisions = 0;
  31.  
  32.         void ICmpInitializable.OnInit(InitContext context)
  33.         {
  34.             if (context != InitContext.Activate) return;
  35.  
  36.             for (var i = 0; i < HashWidth; i++)
  37.                 for (var j = 0; j < HashHeight; j++)
  38.                     Hash[i, j] = new List<Unit>();
  39.  
  40.             hashBoundaries = new Rect(0, 0, HashWidth, HashHeight);
  41.         }
  42.  
  43.         void ICmpInitializable.OnShutdown(ShutdownContext context)
  44.         {
  45.  
  46.         }
  47.  
  48.         void ICmpUpdatable.OnUpdate()
  49.         {
  50.             if (timer >= interval)
  51.             {
  52.                 var watch = Stopwatch.StartNew();
  53.                 CheckCollisionBetweenUnits();
  54.  
  55.                 watch.Stop();
  56.  
  57.                 if (Game.Keyboard.KeyPressed(Key.V))
  58.                 {
  59.                     var log = Scene.Current.FindComponent<HelperConsole>();
  60.                     var count = Scene.Current.FindComponents<Unit>().Count();
  61.  
  62.                     log.SetText("Checks / Collisions: " + collisionChecks + "/" + collisions + " (Units: " + count + " / Time taken: " + watch.Elapsed + ")");
  63.  
  64.                 }
  65.  
  66.                 timer = 0;
  67.             }
  68.  
  69.             timer += Time.TimeMult;
  70.         }
  71.  
  72.         void CheckCollisionBetweenUnits()
  73.         {
  74.            
  75.             //Let's get units' list and count
  76.             var units = Scene.Current.FindComponents<Unit>();
  77.             var count = units.Count();
  78.            
  79.             //Let them all coliide
  80.             for (var i = 0; i < count; i++)
  81.             {
  82.                 var thisUnit = units.ElementAt(i);
  83.                 var thisUnitTransf = thisUnit.GameObj.Transform;
  84.  
  85.                 thisUnit.checks = 0;
  86.  
  87.                 //Update collision rectangle and enable collision
  88.                 thisUnit.CheckCollisionUnits = true;
  89.                 thisUnit.CollisionRect = new Rect(thisUnitTransf.Pos.X - 3, thisUnitTransf.Pos.Y - 3, 6, 6);
  90.  
  91.                 //Add to a hash and delete from previous, if needed
  92.                 if (thisUnit.Hash.X == -1000)
  93.                 {
  94.                     var gridPos = new Point2((int)MathF.Floor(thisUnitTransf.Pos.X / HashGridSize), (int)MathF.Floor(thisUnitTransf.Pos.Y / HashGridSize));
  95.  
  96.                     Log.Game.Write("Added to Hash[" + gridPos.X + ", " + gridPos.Y + "].");
  97.  
  98.                     thisUnit.Hash = gridPos;
  99.  
  100.                     Hash[gridPos.X, gridPos.Y].Add(thisUnit);
  101.                 }
  102.                 else//If I'm already in a hash
  103.                 {
  104.                     var gridPos = new Point2((int)MathF.Floor(thisUnitTransf.Pos.X / HashGridSize), (int)MathF.Floor(thisUnitTransf.Pos.Y / HashGridSize));
  105.  
  106.                     //If I'm not in the same hash any more
  107.                     if (thisUnit.Hash != gridPos)
  108.                     {
  109.                         //Remove from previous
  110.                         Hash[thisUnit.Hash.X, thisUnit.Hash.Y].Remove(thisUnit);
  111.  
  112.                         //Add to the new one
  113.                         if (hashBoundaries.Contains(gridPos))
  114.                         {
  115.                             thisUnit.Hash = gridPos;
  116.                             Hash[gridPos.X, gridPos.Y].Add(thisUnit);
  117.                         }
  118.                         else
  119.                         {
  120.                             thisUnit.Hash = new Point2(-1000, -1000);
  121.                         }
  122.                     }
  123.                 }
  124.             }
  125.  
  126.             //Debugging purposes
  127.             collisionChecks = 0;
  128.             collisions = 0;
  129.  
  130.             //TimeSpan time = new TimeSpan();
  131.             for (var i = 0; i < HashWidth; i++)
  132.             {
  133.                 for (var j = 0; j < HashHeight; j++)
  134.                 {
  135.                     CheckCollisionsOfUnitsInHash(i, j);
  136.                 }
  137.             }
  138.         }
  139.  
  140.  
  141.         void CheckCollisionsOfUnitsInHash(int x, int y)
  142.         {
  143.            
  144.             //This will loop through all of the units in this hash
  145.             for (var i = 0; i < Hash[x, y].Count; i++)
  146.             {
  147.                 var unitA = Hash[x, y].ElementAt(i);
  148.  
  149.                 if (!unitA.CheckCollisionUnits) continue;
  150.  
  151.                 unitA.CheckCollisionUnits = false;
  152.  
  153.                 var topLeftX = (int) Math.Max(0, unitA.CollisionRect.TopLeft.X / HashGridSize);
  154.                 var topLeftY = (int) Math.Max(0, unitA.CollisionRect.TopLeft.Y / HashGridSize);
  155.  
  156.                 var bottomRightX = (int) Math.Min(HashWidth, unitA.CollisionRect.BottomRight.X / HashGridSize);
  157.                 var bottomRightY = (int) Math.Min(HashHeight, unitA.CollisionRect.BottomRight.Y / HashGridSize);
  158.  
  159.                 //Now let's loop through its hash (and neighbours, if needed)
  160.                 for (var a = topLeftX; a <= bottomRightX; a++)
  161.                 {
  162.                     for (var b = topLeftY; b <= bottomRightY; b++)
  163.                     {
  164.                         for (var c = 0; c < Hash[a, b].Count; c++)
  165.                         {
  166.                            
  167.                             var unitB = Hash[a, b].ElementAt(c);
  168.                             unitA.checks++;
  169.                             unitB.checks++;
  170.  
  171.                             if (!unitB.CheckCollisionUnits) continue;
  172.  
  173.                             collisionChecks++;
  174.  
  175.                             //If colliding!
  176.                             if (unitA.CollisionRect.Intersects(unitB.CollisionRect))
  177.                             {
  178.                                 //Let's make one of them stop based on movement priority
  179.                                 unitA.CollisionEnd(unitB);
  180.  
  181.                                 //Disable the other as well and +1 to collisions
  182.                                 //unitB.CheckCollisionUnits = false;
  183.                                 collisions++;
  184.                                
  185.                                 break;
  186.                             }
  187.                         }
  188.                     }
  189.                 }
  190.             }
  191.  
  192.             /*
  193.  
  194.             //Loop through all of the units
  195.             for (var i = 0; i < count; i++)
  196.             {
  197.                 //Get current unit and if it's collided with someone this frame, skip
  198.                 var unitA = units.ElementAt(i);
  199.                 if (!unitA.CheckCollisionUnits) continue;
  200.  
  201.                 //Deactivate collision and get GameObject
  202.                 unitA.CheckCollisionUnits = false;
  203.                 var colliderA = unitA.GameObj;
  204.  
  205.                 //Loop through all of the OTHER units
  206.                 for (var j = 0; j < count; j++)
  207.                 {
  208.                     //Get the others and skip if necessary
  209.                     var unitB = units.ElementAt(j);
  210.                     if (!unitB.CheckCollisionUnits) continue;
  211.  
  212.                     collisionChecks++;
  213.  
  214.                     //Get the other and collision vector
  215.                     var colliderB = unitB.GameObj;
  216.                     //var collision = (colliderA.Transform.Pos - colliderB.Transform.Pos);
  217.  
  218.                     //If colliding!
  219.                     if (unitA.CollisionRect.Intersects(unitB.CollisionRect))
  220.                     {
  221.                         //Let's make one of them stop based on movement priority
  222.                         unitA.CollisionEnd(unitB);
  223.  
  224.                         //Disable the other as well and +1 to collisions
  225.                         unitB.CheckCollisionUnits = false;
  226.                         collisions++;
  227.  
  228.                         break;
  229.                     }
  230.                 }
  231.             }
  232.         }*/
  233.  
  234.  
  235.         }
  236.     }
  237. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement