Guest User

collision_resolution.cpp

a guest
May 11th, 2013
102
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //
  2. #define INDEX( Z, X, Y ) Z->data[ (X) + ((Y) * Z->width) ]
  3. #define ISWALL( Z, X, Y ) ((Z->data[ (X) + ((Y) * Z->width) ] & cWall ) > 0 )
  4.  
  5. //
  6. void preprocess( sMapInfo *map )
  7. {
  8.     // mask out all push data
  9.     for ( uint32 i=0; i<map->width * map->height; i++ )
  10.         map->data[ i ] &= 0xF0;
  11.  
  12.     // vertical process
  13.     for ( uint32 x=0; x < map->width; x++ )
  14.     {
  15.         // check if is wall
  16.         int prev = ISWALL( map, x, 0 );
  17.         //
  18.         for ( uint32 y=1; y < map->height; y++ )
  19.         {
  20.             // sample the current tile
  21.             int cur = ISWALL( map, x, y );
  22.             // check for a wall gradient
  23.             switch (cur - prev)
  24.             {
  25.             case ( -1 ): INDEX( map, x, y-1 ) |= cQLower; break;
  26.             case (  1 ): INDEX( map, x, y   ) |= cQUpper; break;
  27.             }
  28.             //
  29.             prev = cur;
  30.         }
  31.     }
  32.  
  33.     // horozontal process
  34.     for ( uint32 y=0; y < map->height; y++ )
  35.     {
  36.         // check if is wall
  37.         int prev = ISWALL( map, 0, y );
  38.         //
  39.         for ( uint32 x=1; x < map->width; x++ )
  40.         {
  41.             // sample the current tile
  42.             int cur = ISWALL( map, x, y );
  43.             // check for a wall gradient
  44.             switch (cur - prev)
  45.             {
  46.             case ( -1 ): INDEX( map, x-1, y ) |= cQRight; break;
  47.             case (  1 ): INDEX( map, x  , y ) |= cQLeft ; break;
  48.             }
  49.             //
  50.             prev = cur;
  51.         }
  52.     }
  53. }
  54.  
  55. //
  56. int limiti( int min, int cur, int max )
  57. {
  58.     if ( cur < min ) return min;
  59.     if ( cur > max ) return max;
  60.                      return cur;
  61. }
  62.  
  63. //
  64. int absi( int a )
  65. {
  66.     if ( a < 0 ) return -a;
  67.                  return  a;
  68. }
  69.  
  70. //
  71. int select_from_absmin( int a, int b )
  72. {
  73.     int i = a;
  74.     int j = b;
  75.     if ( a < 0 ) a = -a;
  76.     if ( b < 0 ) a = -b;
  77.     if ( a < b ) return i;
  78.                  return j;
  79. }
  80.  
  81.  
  82. //
  83. bool collide( sMapInfo *map, sCollideInfo *info )
  84. {
  85.     //
  86.     int ts = map->tileSize;
  87.  
  88.     //
  89.     int x1 = info->px - (info->w / 2);
  90.     int y1 = info->py - (info->h / 2);
  91.     int x2 = x1       +  info->w;
  92.     int y2 = y1       +  info->h;
  93.  
  94.     // comvert into clipped map space
  95.     x1 = limiti( 0, x1 / ts, map->width -1 );
  96.     x2 = limiti( 0, x2 / ts, map->width -1 );
  97.     y1 = limiti( 0, y1 / ts, map->height-1 );
  98.     y2 = limiti( 0, y2 / ts, map->height-1 );
  99.    
  100.     //
  101.     int dp_x = 0xFFFF;
  102.     int dp_y = 0xFFFF;
  103.  
  104.     //
  105.     for ( int y=y1; y<=y2; y++ )
  106.     {
  107.         for ( int x=x1; x<=x2; x++ )
  108.         {
  109.             // extract this tile
  110.             uint8 tile = map->data[ x + y*map->width ];
  111.  
  112.             // skip if not a blocking tile
  113.             if ( (tile & cWall) == 0 )
  114.                 continue;
  115.  
  116.             //
  117.             int quad[4] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
  118.  
  119.             // find all of the splits
  120.             if ( (tile & cQUpper) != 0 ) quad[0] =  (y   *ts) - (info->py + info->h / 2);
  121.             if ( (tile & cQLower) != 0 ) quad[1] = ((y+1)*ts) - (info->py - info->h / 2);
  122.             if ( (tile & cQLeft ) != 0 ) quad[2] =  (x   *ts) - (info->px + info->w / 2);
  123.             if ( (tile & cQRight) != 0 ) quad[3] = ((x+1)*ts) - (info->px - info->w / 2);
  124.  
  125.             // select each quadrant from comparison of their abs min
  126.             quad[0] = select_from_absmin( quad[0], quad[1] );
  127.             quad[2] = select_from_absmin( quad[2], quad[3] );
  128.  
  129.             // select the smallest split axis from this tile
  130.             if ( absi( quad[2] ) < absi( quad[0] ) )
  131.             {
  132.                 // x - axis
  133.                 // save if smaller then our current split
  134.                 if ( absi( quad[2] ) < absi( dp_x ) ) dp_x = quad[2];
  135.             }
  136.             else
  137.             {
  138.                 // y - axis
  139.                 // save if smaller then our current split
  140.                 if ( absi( quad[0] ) < absi( dp_y ) ) dp_y = quad[0];
  141.             }
  142.  
  143.         }
  144.     }
  145.  
  146.     // resolve a split on any axis
  147.     if ( dp_x != 0xFFFF ) info->px += dp_x;
  148.     if ( dp_y != 0xFFFF ) info->py += dp_y;
  149.  
  150.     // did we have a split
  151.     return (dp_x != 0xFFFF) || (dp_y != 0xFFFF);
  152. }
RAW Paste Data