Advertisement
RefresherTowel

Binary Space Partitioning in GML

Aug 23rd, 2023
1,147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #macro CELLSIZE 16
  2. #macro MIN_LEAF_SIZE CELLSIZE*15
  3. #macro MAX_LEAF_SIZE CELLSIZE*45
  4.  
  5. ///@func    BSP(function)
  6. ///@param   {function}  _func
  7. ///@desc    Runs the binary space partition formula, creating leaves until the created leaves
  8. ///         are below a specific size. If you want to run a function on the "smallest" leaves
  9. ///         (which are basically the rooms, if using for dungeon generation), supply that function
  10. ///         as the function argument in BSP
  11. function BSP(_func) {
  12.     leafs = [];
  13.  
  14.     array_push(leafs,new Leaf(0,0,width,height));
  15.  
  16.     var _split = true;
  17.     while (_split) {
  18.         _split = false;
  19.         var _leaf_len = array_length(leafs);
  20.         for (var i=0;i<_leaf_len;i++) {
  21.             var _leaf = leafs[i];
  22.             if (_leaf.child[0] == undefined && _leaf.child[1] == undefined) {
  23.                 if (_leaf.width > MAX_LEAF_SIZE || _leaf.height > MAX_LEAF_SIZE) {
  24.                     if (_leaf.Split()) {
  25.                         array_push(leafs,_leaf.child[0]);
  26.                         array_push(leafs,_leaf.child[1]);
  27.                         _split = true;
  28.                     }
  29.                 }
  30.             }
  31.         }
  32.     }
  33.  
  34.     var _leaf_len = array_length(leafs);
  35.     for (var i=0;i<_leaf_len;i++) {
  36.         var _leaf = leafs[i];
  37.         with (_leaf) {
  38.             if (child[0] == undefined && child[1] == undefined) {
  39.                 _func();
  40.             }
  41.         }
  42.     }
  43. }
  44.  
  45. ///@func    Leaf(x, y, width, height, parent)
  46. ///@param   {real}      _x
  47. ///@param   {real}      _y
  48. ///@param   {real}      _width
  49. ///@param   {real}      _height
  50. ///@param   {struct}    _parent
  51. function Leaf(_x,_y,_width,_height,_parent = undefined) constructor {
  52.     x = _x;
  53.     y = _y;
  54.     width = _width;
  55.     height = _height;
  56.     child[0] = undefined;
  57.     child[1] = undefined;
  58.     connected = undefined;
  59.     parent = _parent;
  60.     rm = undefined;
  61.    
  62.     Split = function() {
  63.         if (child[0] != undefined || child[1] != undefined) {
  64.             return false;
  65.         }
  66.         var _splith = irandom(1);
  67.         if (width > height && width / height >= 1.5) {
  68.             _splith = false;
  69.         }
  70.         else if (height > width && height / width >= 1.5) {
  71.             _splith = true;
  72.         }
  73.         var _max = (_splith ? height : width) - MIN_LEAF_SIZE;
  74.         if (_max <= MIN_LEAF_SIZE) {
  75.             return false;
  76.         }
  77.         var _split = irandom_range(MIN_LEAF_SIZE,_max);
  78.         if (_splith) {
  79.             child[0] = new Leaf(x,y,width,_split,self);
  80.             child[1] = new Leaf(x,y+_split,width,height-_split,self);
  81.         }
  82.         else {
  83.             child[0] = new Leaf(x,y,_split,height,self);
  84.             child[1] = new Leaf(x+_split,y,width-_split,height,self);
  85.         }
  86.         return true;
  87.     }
  88.    
  89.     GetRoom = function() {
  90.         if (rm != undefined) {
  91.             return rm;
  92.         }
  93.         else {
  94.             var lrm = undefined;
  95.             var rrm = undefined;
  96.             if (child[0] != undefined) {
  97.                 lrm = child[0].GetRoom();
  98.             }
  99.             if (child[1] != undefined) {
  100.                 rrm = child[1].GetRoom();
  101.             }
  102.             if (lrm == undefined && rrm == undefined) {
  103.                 return undefined;
  104.             }
  105.             else if (rrm == undefined) {
  106.                 return lrm;
  107.             }
  108.             else if (lrm == undefined) {
  109.                 return rrm;
  110.             }
  111.             else if (random(1) <= 0.5) {
  112.                 return lrm;
  113.             }
  114.             else {
  115.                 return rrm;
  116.             }
  117.         }
  118.     }
  119.    
  120.     CreateRooms = function() {
  121.         if (child[0] != undefined || child[1] != undefined) {
  122.             if (child[0] != undefined) {
  123.                 child[0].CreateRooms();
  124.             }
  125.             if (child[1] != undefined) {
  126.                 child[1].CreateRooms();
  127.             }
  128.             if (child[0] != undefined && child[1] != undefined) {
  129.                 var _rm1 = child[0].GetRoom();
  130.                 var _rm2 = child[1].GetRoom();
  131.             }
  132.         }
  133.         else {
  134.             // Add the code to "create" a room here, maybe you want to create an instance, or drill out
  135.             // an area of a grid or whatever. You can just run CreateRooms() from the scope of the topmost leaf and it will
  136.             // filter down through the leaves and run on all the leaves without children (which would be the "rooms" in your
  137.             // dungeon, if you are using it for dungeon generation).
  138.         }
  139.     }
  140. }
  141.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement