Guest User

Separating Axis Theorem Issue

a guest
Apr 23rd, 2014
51
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //The code in the Update method of the level checking for collisions between enemies:
  2.  
  3.           foreach (Enemy e in Enemies)
  4.             {
  5.                 foreach (Enemy e2 in Enemies)
  6.                 {
  7.                     if (e != e2)
  8.                         //The enemy's Test is its collider object containing the Shape used for SAT.
  9.                         if (e.Test.isColliding(e2.Test, ref MTV))
  10.                             e.Position += MTV;
  11.                 }
  12.             }
  13.  
  14. //The isColliding method inside the Collider class (this is a big one):
  15.  
  16.             public bool isColliding(Collider<T> target, ref Vector2 minTransVect)
  17.         {
  18.             //Get the normalized axes of each shape for projection.
  19.             Vector2[] axes1 = BoundingShape.getAxes();
  20.             Vector2[] axes2 = target.BoundingShape.getAxes();
  21.             Vector2 smallAxis = Vector2.Zero;
  22.             double overlap = 0;
  23.  
  24.             //Loop through this collider's shape's axes and check for overlap.
  25.             for (int a = 0; a < axes1.Length; a++)
  26.             {
  27.                 if (!Collision.overlap(BoundingShape.project(axes1[a]),
  28.                     target.BoundingShape.project(axes1[a])))
  29.                 {
  30.                     return false;
  31.                 }
  32.                 else
  33.                 {
  34.                     double o = Collision.getOverlap(BoundingShape.project(axes1[a]), target.BoundingShape.project(axes1[a]));
  35.                     if (overlap < o)
  36.                     {
  37.                         overlap = o;
  38.                         smallAxis = axes1[a];
  39.                     }
  40.                 }
  41.  
  42.             }
  43.  
  44.             //Loop through the target collider's shape's axes and check for overlap.
  45.             for (int a = 0; a < axes2.Length; a++)
  46.             {
  47.                 if (!Collision.overlap(BoundingShape.project(axes2[a]),
  48.                     target.BoundingShape.project(axes2[a])))
  49.                 {
  50.                     return false;
  51.                 }
  52.                 else
  53.                 {
  54.                     double o = Collision.getOverlap(BoundingShape.project(axes2[a]), target.BoundingShape.project(axes2[a]));
  55.                     if (overlap < o)
  56.                     {
  57.                         overlap = o;
  58.                         smallAxis = axes2[a];
  59.                     }
  60.                 }
  61.             }
  62.  
  63.             Vector2 mtv = new Vector2(smallAxis.X, smallAxis.Y);
  64.             mtv = Vector2.Multiply(mtv, (float)overlap);
  65.             Vector2 dir = Vector2.Subtract(Position, target.Position);
  66.             float test = Vector2.Dot(mtv, dir);
  67.  
  68.             if (test > 0)
  69.                 minTransVect = Vector2.Multiply(mtv, -1);
  70.             else
  71.                 minTransVect = mtv;
  72.  
  73.             return true;
  74.         }
  75.  
  76. //The Collision class is a static class that handles the overlap and getOverlap methods:
  77.  
  78.         //For projections in Vector2 form, x is the min and y is the max.
  79.         public static bool overlap(Vector2 proj1, Vector2 proj2)
  80.         {
  81.             float test1 = proj1.X - proj2.Y;
  82.             float test2 = proj2.X - proj1.Y;
  83.  
  84.             if (test1 > 0 || test2 > 0)
  85.                 return false;
  86.  
  87.             return true;
  88.         }
  89.  
  90.         //For projections in Vector2 form, x is the min and y is the max.
  91.         public static double getOverlap(Vector2 proj1, Vector2 proj2)
  92.         {
  93.             float start = proj1.X > proj2.X ? proj1.X : proj2.X;
  94.             float end = proj1.Y < proj2.Y ? proj1.Y : proj2.Y;
  95.             return (end - start);
  96.         }
  97.  
  98. //Finally, here are relevant methods in the Shape class (which is typically parented by a Collider)
  99.  
  100.         //Gets the position in world space of a transformed vertex at index in the shape's list of vertices.
  101.         public Vector2 getVertPos(int index)
  102.         {
  103.             if (TransformedVertices[index] != null)
  104.                 return Vector2.Add(TransformedVertices[index], Center);
  105.  
  106.             return Vector2.Zero;
  107.         }
  108.  
  109.         //Return an array of the shape's normalized perpendicular axis.
  110.         public Vector2[] getAxes()
  111.         {
  112.             Vector2[] axes = new Vector2[TransformedVertices.Count];
  113.  
  114.             for (int a = 0; a < axes.Length; a++)
  115.             {
  116.                 Vector2 v1 = getVertPos(a);
  117.                 Vector2 v2 = getVertPos(a + 1 == axes.Length ? 0 : a + 1);
  118.                 Vector2 edge = Vector2.Subtract(v1, v2);
  119.                 Vector2 normal = new Vector2(-edge.Y, edge.X);
  120.                 normal.Normalize();
  121.                 axes[a] = normal;
  122.             }
  123.  
  124.             return axes;
  125.         }
  126.  
  127.         //Project the shape into 1-dimensional space along a specified axis.
  128.         public Vector2 project(Vector2 axis)
  129.         {
  130.             float min = Vector2.Dot(getVertPos(0), axis);
  131.             float max = min;
  132.  
  133.             for (int i = 0; i < TransformedVertices.Count; i++)
  134.             {
  135.                 float c = Vector2.Dot(getVertPos(i), axis);
  136.  
  137.                 if (c < min)
  138.                     min = c;
  139.                 else if (c > max)
  140.                     max = c;
  141.             }
  142.  
  143.             return new Vector2(min, max);
  144.         }
  145.  
  146.         public void Update()
  147.         {
  148.             if (!Circle && Rotation != lastRotation)
  149.             {
  150.                 lastRotation = Rotation;
  151.  
  152.                 Matrix rotate = Matrix.CreateRotationZ(Rotation);
  153.  
  154.                 for (int v = 0; v < Vertices.Count; v++)
  155.                 {
  156.                     TransformedVertices[v] = Vector2.Transform(Vertices[v], rotate);
  157.                 }
  158.             }
  159.         }
Advertisement
Add Comment
Please, Sign In to add comment