Advertisement
Badwrong

GameMaker - Tile Raycast

Nov 23rd, 2021 (edited)
1,304
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #macro TILE_SIZE 16
  2. #macro TILE_SIZE_M1 15
  3. #macro TILE_RANGE 50
  4. #macro NO_COLLISION -4
  5.  
  6. // _map is the tilemap id
  7.  
  8. function tile_raycast(_x, _y, _rx, _ry, _map)
  9. {  
  10.     // Casts a ray to test for tile collision and returns true or false if found
  11.    
  12.     _rx -= _x;
  13.     _ry -= _y;
  14.    
  15.     var _dot0 = _rx * _rx + _ry * _ry,
  16.         _dist = sqrt(_dot0) + 0.00001; // safe normalize
  17.  
  18.     _rx /= _dist;
  19.     _ry /= _dist;
  20.    
  21.     var _x_length = _ry/_rx,
  22.         _y_length = _rx/_ry,
  23.         _x_dist = sqrt(1 + _x_length * _x_length),
  24.         _y_dist = sqrt(1 + _y_length * _y_length),
  25.         _x_map  = _x div TILE_SIZE,
  26.         _y_map  = _y div TILE_SIZE,
  27.         _x_step = sign(_rx),
  28.         _y_step = sign(_ry);
  29.    
  30.     if (_rx < 0) _x_length = (_x - (_x &~ TILE_SIZE_M1)) / TILE_SIZE * _x_dist;
  31.     else  _x_length = ((_x &~ TILE_SIZE_M1) + TILE_SIZE - _x) / TILE_SIZE *_x_dist;
  32.    
  33.     if (_ry < 0) _y_length = (_y - (_y &~ TILE_SIZE_M1)) / TILE_SIZE * _y_dist;
  34.     else _y_length = ((_y &~ TILE_SIZE_M1) + TILE_SIZE - _y) / TILE_SIZE *_y_dist;
  35.        
  36.     for (var _d = 0; _d < TILE_RANGE; _d++)
  37.     {
  38.         if (_x_length < _y_length)
  39.         {
  40.             _x_map += _x_step;
  41.             if (tilemap_get(_map, _x_map, _y_map) & tile_index_mask == TILE_SOLID)
  42.             {
  43.                 _dist = _x_length * TILE_SIZE;
  44.                 _rx *= _dist;
  45.                 _ry *= _dist;
  46.                 if ((_rx * _rx + _ry * _ry) > _dot0) return false;
  47.                 else return true;
  48.             }
  49.             _x_length += _x_dist;  
  50.         }
  51.         else
  52.         {
  53.             _y_map += _y_step;
  54.             if (tilemap_get(_map, _x_map, _y_map) & tile_index_mask == TILE_SOLID)
  55.             {
  56.                 _dist = _y_length * TILE_SIZE;
  57.                 _rx *= _dist;
  58.                 _ry *= _dist;
  59.                 if ((_rx * _rx + _ry * _ry) > _dot0) return false;
  60.                 else return true;
  61.             }
  62.             _y_length += _y_dist;
  63.         }  
  64.     }
  65.     return false;
  66. }
  67.  
  68. function tile_raycast_point(_x, _y, _rx, _ry, _map)
  69. {  
  70.     // Casts a ray to (_rx, _ry) and tests for tile collision
  71.     // Returns a point (x, y) if found or NO_COLLISION
  72.    
  73.     _rx -= _x;
  74.     _ry -= _y;
  75.    
  76.     var _dot0 = _rx * _rx + _ry * _ry,
  77.         _dist = sqrt(_dot0) + 0.00001; // safe normalize
  78.  
  79.     _rx /= _dist;
  80.     _ry /= _dist;
  81.    
  82.     var _x_length = _ry/_rx,
  83.         _y_length = _rx/_ry,
  84.         _x_dist = sqrt(1 + _x_length * _x_length),
  85.         _y_dist = sqrt(1 + _y_length * _y_length),
  86.         _x_map  = _x div TILE_SIZE,
  87.         _y_map  = _y div TILE_SIZE,
  88.         _x_step = sign(_rx),
  89.         _y_step = sign(_ry);
  90.    
  91.     if (_rx < 0) _x_length = (_x - (_x &~ TILE_SIZE_M1)) / TILE_SIZE * _x_dist;
  92.     else  _x_length = ((_x &~ TILE_SIZE_M1) + TILE_SIZE - _x) / TILE_SIZE *_x_dist;
  93.    
  94.     if (_ry < 0) _y_length = (_y - (_y &~ TILE_SIZE_M1)) / TILE_SIZE * _y_dist;
  95.     else _y_length = ((_y &~ TILE_SIZE_M1) + TILE_SIZE - _y) / TILE_SIZE *_y_dist;
  96.        
  97.     for (var _d = 0; _d < TILE_RANGE; _d++)
  98.     {
  99.         if (_x_length < _y_length)
  100.         {
  101.             _x_map += _x_step;
  102.             if (tilemap_get(_map, _x_map, _y_map) & tile_index_mask == TILE_SOLID)
  103.             {
  104.                 _dist = _x_length * TILE_SIZE;
  105.                 _rx *= _dist;
  106.                 _ry *= _dist;
  107.                 if ((_rx * _rx + _ry * _ry) > _dot0) return NO_COLLISION;
  108.                 else return { x : _x + _rx, y : _y + _ry }
  109.             }
  110.             _x_length += _x_dist;  
  111.         }
  112.         else
  113.         {
  114.             _y_map += _y_step;
  115.             if (tilemap_get(_map, _x_map, _y_map) & tile_index_mask == TILE_SOLID)
  116.             {
  117.                 _dist = _y_length * TILE_SIZE;
  118.                 _rx *= _dist;
  119.                 _ry *= _dist;
  120.                 if ((_rx * _rx + _ry * _ry) > _dot0) return NO_COLLISION;
  121.                 else return { x : _x + _rx, y : _y + _ry }
  122.             }
  123.             _y_length += _y_dist;
  124.         }  
  125.     }
  126.     return NO_COLLISION;
  127. }
  128.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement