Advertisement
snake5

collision grid

Nov 17th, 2014
536
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.     Collision grid, 16x16 tiles
  3.    
  4.     - create
  5.     + set( x16, y16 )
  6.     + unset( x16, y16 )
  7.     + test( x, y )
  8.     + raycast( x1, y1, x2, y2, notestfirst ) => null / dt, isp_x, isp_y
  9.     + aabbtest( x1, y1, x2, y2 ) => null / true, xnrm, ynrm, push
  10. */
  11.  
  12. global ColGrid = {};
  13.  
  14. function ColGrid.create()
  15. {
  16.     data =
  17.     {
  18.         tiles = map(),
  19.     };
  20.     return class( data, ColGrid );
  21. }
  22.  
  23. function ColGrid._getkey( x16, y16 )
  24. {
  25.     return ((x16&0xffff)<<16) | (y16&0xffff);
  26. }
  27.  
  28. function ColGrid.set( x16, y16 )
  29. {
  30.     this.tiles[ this._getkey( x16, y16 ) ] = true;
  31. }
  32.  
  33. function ColGrid.unset( x16, y16 )
  34. {
  35.     unset( this.tiles, this._getkey( x16, y16 ) );
  36. }
  37.  
  38. function ColGrid.test( x, y )
  39. {
  40.     x16 = toint( floor( x / 16 ) );
  41.     y16 = toint( floor( y / 16 ) );
  42.     return isset( this.tiles, this._getkey( x16, y16 ) );
  43. }
  44.  
  45. function ColGrid.raycast( x1, y1, x2, y2, notestfirst )
  46. {
  47.     x1_16 = toint( floor( x1 / 16 ) );
  48.     y1_16 = toint( floor( y1 / 16 ) );
  49.     x2_16 = toint( floor( x2 / 16 ) );
  50.     y2_16 = toint( floor( y2 / 16 ) );
  51.    
  52.     if( !notestfirst && isset( this.tiles, this._getkey( x1_16, y1_16 ) ) )
  53.         return 0, x1, y1;
  54.     if( x1_16 == x2_16 && y1_16 == y2_16 )
  55.         return null;
  56.    
  57.     x16 = x1_16;
  58.     y16 = y1_16;
  59.     xdist = x2 - x1;
  60.     ydist = y2 - y1;
  61.     stepX = if( xdist >= 0, 1, -1 );
  62.     stepY = if( ydist >= 0, 1, -1 );
  63.     len = sqrt( xdist * xdist + ydist * ydist );
  64.     if( xdist == 0 )
  65.     {
  66.         tMaxX = 3.8e+10;
  67.         tDeltaX = 0;
  68.     }
  69.     else
  70.     {
  71.         tMaxX = ( floor( x1_16 + ( xdist > 0 ) ) * 16 - x1 ) * len / xdist; // should be +
  72.         tDeltaX = 16 * len / abs( xdist );
  73.     }
  74.     if( ydist == 0 )
  75.     {
  76.         tMaxY = 3.8e+10;
  77.         tDeltaY = 0;
  78.     }
  79.     else
  80.     {
  81.         tMaxY = ( floor( y1_16 + ( ydist > 0 ) ) * 16 - y1 ) * len / ydist; // should be +
  82.         tDeltaY = 16 * len / abs( ydist );
  83.     }
  84.     t = if( tMaxX < tMaxY, tMaxX, tMaxY );
  85.    
  86.     while( x16 != x2_16 || y16 != y2_16 )
  87.     {
  88.         if( tMaxX < tMaxY )
  89.         {
  90.             t += tMaxX;
  91.             tMaxX += tDeltaX;
  92.             x16 += stepX;
  93.         }
  94.         else
  95.         {
  96.             t = tMaxY;
  97.             tMaxY += tDeltaY;
  98.             y16 += stepY;
  99.         }
  100.        
  101.         if( isset( this.tiles, this._getkey( x16, y16 ) ) )
  102.         {
  103.             q = t / len;
  104.             q1 = 1 - q;
  105.             return q, x1 * q1 + x2 * q, y1 * q1 + y2 * q;
  106.         }
  107.     }
  108.    
  109.     return null;
  110. }
  111.  
  112. function _aabb_aabb_resolve( ax1, ay1, ax2, ay2, bx1, by1, bx2, by2 )
  113. {
  114.     // in an intersection all of these are non-negative
  115.     dx1 = ax2 - bx1;
  116.     dx2 = bx2 - ax1;
  117.     dy1 = ay2 - by1;
  118.     dy2 = by2 - ay1;
  119.    
  120.     // find smallest of those and resolve assuming BB1 is to be moved
  121.     if( dx1 < dx2 )
  122.     {
  123.         if( dx1 < dy1 )
  124.         {
  125.             if( dx1 < dy2 )
  126.                 return -dx1, 0;
  127.             else // dy2
  128.                 return 0, dy2;
  129.         }
  130.         else // dy1
  131.         {
  132.             if( dy1 < dy2 )
  133.                 return 0, -dy1;
  134.             else // dy2
  135.                 return 0, dy2;
  136.         }
  137.     }
  138.     else // dx2
  139.     {
  140.         if( dx2 < dy1 )
  141.         {
  142.             if( dx2 < dy2 )
  143.                 return dx2, 0;
  144.             else
  145.                 return 0, dy2;
  146.         }
  147.         else // dy1
  148.         {
  149.             if( dy1 < dy2 )
  150.                 return 0, -dy1;
  151.             else // dy2
  152.                 return 0, dy2;
  153.         }
  154.     }
  155. }
  156.  
  157. function ColGrid.aabbtest( x1, y1, x2, y2 )
  158. {
  159.     x1_16 = toint( floor( x1 / 16 ) );
  160.     y1_16 = toint( floor( y1 / 16 ) );
  161.     x2_16 = toint( floor( x2 / 16 ) );
  162.     y2_16 = toint( floor( y2 / 16 ) );
  163.    
  164.     nx = 0;
  165.     ny = 0;
  166.     isc = 0;
  167.    
  168.     for( y16 = y1_16; y16 <= y2_16; ++y16 )
  169.     {
  170.         for( x16 = x1_16; x16 <= x2_16; ++x16 )
  171.         {
  172.             if( isset( this.tiles, this._getkey( x16, y16 ) ) )
  173.             {
  174.                 (cx,cy) = _aabb_aabb_resolve( x1, y1, x2, y2, x16 * 16, y16 * 16, x16 * 16 + 16, y16 * 16 + 16 );
  175.                 nx += cx;
  176.                 ny += cy;
  177.                 isc++;
  178.             }
  179.         }
  180.     }
  181.    
  182.     if( isc )
  183.     {
  184.         nx /= isc;
  185.         ny /= isc;
  186.     }
  187.    
  188.     if( nx != 0 || ny != 0 )
  189.     {
  190.         nd = sqrt( nx * nx + ny * ny );
  191.         nx /= nd;
  192.         ny /= nd;
  193.         return true, nx, ny, nd;
  194.     }
  195. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement