Advertisement
Badwrong

GameMaker - Autotile Runtime

Sep 23rd, 2021 (edited)
2,819
1
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. function tilemap_autotile(_map, _cx, _cy, _addTile, _fill_edges = false)
  2. {
  3.                
  4.     // _map     : The tilemap id
  5.     // _cx, _cy : The cell x/y of the tile (not room x/y)
  6.     // _addTile : sets tile empty or not (true/false)
  7.                
  8.     // Set (cx, cy)
  9.     tilemap_set(_map, _addTile, _cx, _cy);
  10.  
  11.     var _row = _cx + 2, _col = _cy + 2;
  12.     _cx--;
  13.     _cy--;
  14.    
  15.     var _gw = tilemap_get_width(_map) - 1 ,
  16.         _gh = tilemap_get_height(_map) - 1;
  17.    
  18.     // Set mask for 3x3 area centered on (cx, cy)
  19.     for (var _tx = _cx, _mask = 0; _tx < _row; _tx++)
  20.         for (var _ty = _cy; _ty < _col; _ty++)
  21.         {      
  22.             if tilemap_get(_map, _tx, _ty) {
  23.                 // The mask consists of powers of 2, so take advantage of bitwise
  24.                        
  25.                 var _e  = tilemap_get(_map, _tx+1, _ty)   > 0,
  26.                     _ne = tilemap_get(_map, _tx+1, _ty-1) > 0,
  27.                     _n  = tilemap_get(_map, _tx,   _ty-1) > 0,
  28.                     _nw = tilemap_get(_map, _tx-1, _ty-1) > 0,
  29.                     _w  = tilemap_get(_map, _tx-1, _ty)   > 0,
  30.                     _sw = tilemap_get(_map, _tx-1, _ty+1) > 0,
  31.                     _s  = tilemap_get(_map, _tx,   _ty+1) > 0,
  32.                     _se = tilemap_get(_map, _tx+1, _ty+1) > 0;
  33.                        
  34.                 if (_fill_edges)
  35.                 {
  36.                     // Treat edges outside of the tilemap as if they contain tiles
  37.                     var _top   = _ty - 1 < 0,
  38.                         _bot   = _ty + 1 > _gh,
  39.                         _left  = _tx - 1 < 0 ,
  40.                         _right = _tx > _gw;
  41.                        
  42.                     _n  |= _top;
  43.                     _s  |= _bot;
  44.                     _e  |= _right;
  45.                     _w  |= _left;
  46.                     _nw |= _left || _top;
  47.                     _sw |= _left || _bot;
  48.                     _ne |= _right || _top;
  49.                     _se |= _right || _bot;
  50.                 }
  51.                    
  52.                 _mask = 0                  // = 0
  53.                     + (_w << 3)            // + 8
  54.                     + (_e << 4);           // + 16
  55.                
  56.                 if (_n) _mask = _mask | 2  // OR 2
  57.                     + (_nw && _w)          // +  1
  58.                     + ((_ne && _e) << 2);  // +  4
  59.                
  60.                 if (_s) _mask = _mask | 64 // OR 64
  61.                     + ((_sw && _w) << 5)   // +  32
  62.                     + ((_se && _e) << 7);  // + 128
  63.                    
  64.             } else _mask = -1;
  65.            
  66.             // Large switch of constants is a jump-table of O(1) at runtime no worries
  67.             switch _mask
  68.             {
  69.                 case 255 : _mask = 47; break; case 254 : _mask =  1; break; case 251 : _mask =  2; break;
  70.                 case 250 : _mask =  3; break; case 248 : _mask = 20; break; case 223 : _mask =  8; break;
  71.                 case 222 : _mask =  9; break; case 219 : _mask = 10; break; case 218 : _mask = 11; break;
  72.                 case 216 : _mask = 22; break; case 214 : _mask = 16; break; case 210 : _mask = 17; break;
  73.                 case 208 : _mask = 34; break; case 127 : _mask =  4; break; case 126 : _mask =  5; break;
  74.                 case 123 : _mask =  6; break; case 122 : _mask =  7; break; case 120 : _mask = 21; break;
  75.                 case 107 : _mask = 24; break; case 106 : _mask = 26; break; case 104 : _mask = 36; break;
  76.                 case  95 : _mask = 12; break; case  94 : _mask = 13; break; case  91 : _mask = 14; break;
  77.                 case  90 : _mask = 15; break; case  88 : _mask = 23; break; case  86 : _mask = 18; break;
  78.                 case  82 : _mask = 19; break; case  80 : _mask = 35; break; case  75 : _mask = 25; break;
  79.                 case  74 : _mask = 27; break; case  72 : _mask = 37; break; case  66 : _mask = 32; break;
  80.                 case  64 : _mask = 42; break; case  31 : _mask = 28; break; case  30 : _mask = 29; break;
  81.                 case  27 : _mask = 30; break; case  26 : _mask = 31; break; case  24 : _mask = 33; break;
  82.                 case  22 : _mask = 40; break; case  18 : _mask = 41; break; case  16 : _mask = 43; break;
  83.                 case  11 : _mask = 38; break; case  10 : _mask = 39; break; case   8 : _mask = 45; break;
  84.                 case   2 : _mask = 44; break; case   0 : _mask = 46; break; case  -1 : _mask =  0; break;
  85.             }
  86.            
  87.             // Set the new index
  88.             tilemap_set(_map, _mask, _tx, _ty);
  89.         }
  90. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement