Advertisement
RefresherTowel

GameMaker Tile Collisions

Oct 30th, 2022
2,175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ///***** Cloned from badwrong: https://pastebin.com/fYN34fXv ******
  2. // ********* Create ***************//
  3. bbox = new tile_bbox(mask_index); // Instance of the struct below
  4.  
  5. // ********* How to call it when moving (step event or something) *************** //
  6. bbox.move_collide(id, x, y, _vx, _vy);  // _vx and _vy are whatever your movement speeds are
  7.  
  8.  
  9. // ********* The struct ******************************//
  10. function tile_bbox(_mask) constructor
  11. {
  12.     /* Performs tile collision independent from object's bbox.
  13.      * Since we can use a separate mask here from the objects, that allows
  14.      * the object to use a different shaped mask for hit detection and not
  15.      * need a whole other "hurtbox" object.
  16.      *
  17.      * Plus this is actually faster and requires less round/floor/ceil nonsense
  18.      * to fix some internal junk.
  19.      *
  20.      * Note the "& 1" checks for odd numbered tiles as "solid", pretty usefull
  21.      * if you want waist high walls that cause movement collision but can be
  22.      * shot over with a gun or something.
  23.      */
  24.  
  25.     #macro TILE_SOLID 1
  26.     #macro TILE_ONE_WAY 2
  27.     #macro TILE_SIZE 16
  28.     #macro TILE_SIZE_M1 15
  29.    
  30.     #macro COLLIDE_VER_UP 1
  31.     #macro COLLIDE_VER_DOWN -1
  32.     #macro COLLIDE_VER_NONE 0
  33.     #macro COLLIDE_HOR_RIGHT 1
  34.     #macro COLLIDE_HOR_LEFT -1
  35.     #macro COLLIDE_HOR_NONE 0
  36.    
  37.     var _w = sprite_get_width(_mask),
  38.         _h = sprite_get_height(_mask),
  39.         _y_count = ceil(_h / TILE_SIZE),
  40.         _x_count = ceil(_w / TILE_SIZE);
  41.        
  42.     mask_sprite = _mask;
  43.    
  44.     cmap   = global.layer_collision;  
  45.     // or layer_tilemap_get_id(layer_get_id("collision_map"));
  46.     // Remember the id could change between rooms
  47.    
  48.     left   = -sprite_get_xoffset(_mask);
  49.     right  = _w - sprite_get_xoffset(_mask);
  50.     top    = -sprite_get_yoffset(_mask);
  51.     bottom = _h - sprite_get_yoffset(_mask);
  52.    
  53.     hor_count     = _y_count + 1;
  54.     hor_increment = (_h - 1) / _y_count;
  55.     ver_count     = _x_count + 1;
  56.     ver_increment = (_w - 1) / _x_count;
  57.    
  58.     on_horizontal = 0; // Useful for wall jumps
  59.     on_vertical = 0; // Can be used to set on_ground
  60.     on_one_way_platform = false;
  61.                
  62.     function move_collide(_this, _x, _y, _vx, _vy)
  63.     {
  64.         _x += _vx;
  65.         if (_vx > 0) _x = collide_right(_x, _y);
  66.         else if (_vx < 0) _x = collide_left(_x, _y);
  67.         else on_horizontal = COLLIDE_HOR_NONE;
  68.  
  69.         _y += _vy;
  70.         if (_vy > 0) _y = collide_bottom(_x, _y, _vy);
  71.         else if (_vy < 0) _y = collide_top(_x, _y);
  72.         else
  73.         {
  74.             on_vertical = COLLIDE_VER_NONE;
  75.             on_one_way_platform = false;
  76.         }
  77.        
  78.         _this.x = _x;
  79.         _this.y = _y;
  80.     }          
  81.                
  82.     function collide_right(_x, _y)
  83.     {
  84.         var _right = _x + right;
  85.         _y = round(_y + top);
  86.         for (var _i = 0; _i < hor_count; _i++)
  87.         {
  88.             if ((tilemap_get_at_pixel(cmap, _right, _y) & tile_index_mask) & 1)
  89.             {
  90.                 on_horizontal = COLLIDE_HOR_RIGHT;
  91.                 return (_right &~ TILE_SIZE_M1) - right;
  92.             }
  93.             _y += hor_increment;
  94.         }
  95.         on_horizontal = COLLIDE_HOR_NONE;
  96.         return _x;
  97.     }
  98.    
  99.     function collide_left(_x, _y)
  100.     {
  101.         var _left = _x + left;
  102.         _y = round(_y + top);
  103.         for (var _i = 0; _i < hor_count; _i++)
  104.         {
  105.             if ((tilemap_get_at_pixel(cmap, _left, _y) & tile_index_mask) & 1)
  106.             {
  107.                 on_horizontal = COLLIDE_HOR_LEFT;
  108.                 return (_left &~ TILE_SIZE_M1) + TILE_SIZE - left;
  109.             }
  110.             _y += hor_increment;
  111.         }
  112.         on_horizontal = COLLIDE_HOR_NONE;
  113.         return _x;
  114.     }
  115.    
  116.     function collide_top(_x, _y)
  117.     {
  118.         on_one_way_platform = false;
  119.         var _top = _y + top;
  120.         _x = round(_x + left);
  121.         for (var _i = 0; _i < ver_count; _i++)
  122.         {
  123.             if ((tilemap_get_at_pixel(cmap, _x, _top) & tile_index_mask) & 1)
  124.             {
  125.                 on_vertical = COLLIDE_VER_UP;
  126.                 return (_top &~ TILE_SIZE_M1) + TILE_SIZE - top;
  127.             }
  128.             _x += ver_increment;
  129.         }
  130.         on_vertical = COLLIDE_VER_NONE;
  131.         return _y;
  132.     }
  133.    
  134.     function collide_bottom(_x, _y, _vy)
  135.     {
  136.         // A bit different to account for one-way platforms
  137.        
  138.         var _bottom = _y + bottom,
  139.             _tile_top = _bottom &~ TILE_SIZE_M1,
  140.             _above_one_way = (_bottom - _vy) <= _tile_top;
  141.            
  142.         _x = round(_x + left);
  143.         for (var _i = 0; _i < ver_count; _i++)
  144.         {
  145.             var _tile_index = tilemap_get_at_pixel(cmap, _x, _bottom) & tile_index_mask,
  146.                 _on_one_way_platform = (_above_one_way && _tile_index == TILE_ONE_WAY);
  147.            
  148.             if (_tile_index & 1 || _on_one_way_platform)
  149.             {
  150.                 on_vertical = COLLIDE_VER_DOWN;
  151.                 on_one_way_platform = _on_one_way_platform;
  152.                 return _tile_top - bottom;
  153.             }
  154.             _x += ver_increment;
  155.         }
  156.         on_vertical = COLLIDE_VER_NONE;
  157.         return _y;
  158.     }
  159.    
  160.     function draw_mask(_x, _y)
  161.     {
  162.         draw_sprite(mask_sprite, 0, _x, _y);
  163.     }
  164.    
  165. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement