Leaf
object that we use to divide an area into small segments. Then we will generate a random room in each Leaf
. And finally, learn how to connect all the rooms corridors.Leaf
, and then draws them in the BitmapData
object, after which it is displayed on the screen (zooming in to fill the screen).Bitmap
map to the FlxTilemap
object, which generates a playable tile map and displays it on the screen. You can wander through it using the arrows:Leaf
), and divide it vertically or horizontally into two smaller sheets, and then repeat the process with smaller areas, again and again, until each area is less than or equal to the specified maximum value.Leaf
, with which you can do anything. In 3D graphics, BSP can be used to sort objects visible to the player or to recognize collisions in even smaller parts.Leaf
class. In essence, our Leaf
will be a rectangle with some additional features. Each Leaf
will contain either a pair of Leaf
subsidiaries, or a pair of Room
rooms, as well as one or two corridors.Leaf
code looks like: public class Leaf { private const MIN_LEAF_SIZE:uint = 6; public var y:int, x:int, width:int, height:int; // public var leftChild:Leaf; // Leaf public var rightChild:Leaf; // Leaf public var room:Rectangle; // , public var halls:Vector.; // , public function Leaf(X:int, Y:int, Width:int, Height:int) { // x = X; y = Y; width = Width; height = Height; } public function split():Boolean { // if (leftChild != null || rightChild != null) return false; // ! ! // // 25% , // 25% , // var splitH:Boolean = FlxG.random() > 0.5; if (width > height && width / height >= 1.25) splitH = false; else if (height > width && height / width >= 1.25) splitH = true; var max:int = (splitH ? height : width) - MIN_LEAF_SIZE; // if (max <= MIN_LEAF_SIZE) return false; // , ... var split:int = Registry.randomNumber(MIN_LEAF_SIZE, max); // , // if (splitH) { leftChild = new Leaf(x, y, width, split); rightChild = new Leaf(x, y + split, width, height - split); } else { leftChild = new Leaf(x, y, split, height); rightChild = new Leaf(x + split, y, width - split, height); } return true; // ! } }
Leaf
: const MAX_LEAF_SIZE:uint = 20; var _leafs:Vector<Leaf> = new Vector<Leaf>; var l:Leaf; // // , "" . var root:Leaf = new Leaf(0, 0, _sprMap.width, _sprMap.height); _leafs.push(root); var did_split:Boolean = true; // Vector, , . while (did_split) { did_split = false; for each (l in _leafs) { if (l.leftChild == null && l.rightChild == null) // ... { // , 75%... if (l.width > MAX_LEAF_SIZE || l.height > MAX_LEAF_SIZE || FlxG.random() > 0.25) { if (l.split()) // ! { // , Vector, _leafs.push(l.leftChild); _leafs.push(l.rightChild); did_split = true; } } } } }
Vector
(typed array) filled with leaves.Leaf
and go down to the smallest Leaf
that do not have child leaves, and then create a room in each of them.Leaf
class: public function createRooms():void { // . if (leftChild != null || rightChild != null) { // , if (leftChild != null) { leftChild.createRooms(); } if (rightChild != null) { rightChild.createRooms(); } } else { // var roomSize:Point; var roomPos:Point; // 3 x 3 - 2. roomSize = new Point(Registry.randomNumber(3, width - 2), Registry.randomNumber(3, height - 2)); // , // ( ) roomPos = new Point(Registry.randomNumber(1, width - roomSize.x - 1), Registry.randomNumber(1, height - roomSize.y - 1)); room = new Rectangle(x + roomPos.x, y + roomPos.y, roomSize.x, roomSize.y); } }
Vector
from leaves, let's call our new function from the root leaf: _leafs = new Vector<Leaf>; var l:Leaf; // // , "" . var root:Leaf = new Leaf(0, 0, _sprMap.width, _sprMap.height); _leafs.push(root); var did_split:Boolean = true; // Vector, , . while (did_split) { did_split = false; for each (l in _leafs) { if (l.leftChild == null && l.rightChild == null) // ... { // , 75%... if (l.width > MAX_LEAF_SIZE || l.height > MAX_LEAF_SIZE || FlxG.random() > 0.25) { if (l.split()) // ! { // , Vector, _leafs.push(l.leftChild); _leafs.push(l.rightChild); did_split = true; } } } } } // . root.createRooms();
public function getRoom():Rectangle { // , , . if (room != null) return room; else { var lRoom:Rectangle; var rRoom:Rectangle; if (leftChild != null) { lRoom = leftChild.getRoom(); } if (rightChild != null) { rRoom = rightChild.getRoom(); } if (lRoom == null && rRoom == null) return null; else if (rRoom == null) return lRoom; else if (lRoom == null) return rRoom; else if (FlxG.random() > .5) return lRoom; else return rRoom; } }
public function createHall(l:Rectangle, r:Rectangle):void { // . // , , , , . // , , . halls = new Vector<Rectangle>; var point1:Point = new Point(Registry.randomNumber(l.left + 1, l.right - 2), Registry.randomNumber(l.top + 1, l.bottom - 2)); var point2:Point = new Point(Registry.randomNumber(r.left + 1, r.right - 2), Registry.randomNumber(r.top + 1, r.bottom - 2)); var w:Number = point2.x - point1.x; var h:Number = point2.y - point1.y; if (w < 0) { if (h < 0) { if (FlxG.random() < 0.5) { halls.push(new Rectangle(point2.x, point1.y, Math.abs(w), 1)); halls.push(new Rectangle(point2.x, point2.y, 1, Math.abs(h))); } else { halls.push(new Rectangle(point2.x, point2.y, Math.abs(w), 1)); halls.push(new Rectangle(point1.x, point2.y, 1, Math.abs(h))); } } else if (h > 0) { if (FlxG.random() < 0.5) { halls.push(new Rectangle(point2.x, point1.y, Math.abs(w), 1)); halls.push(new Rectangle(point2.x, point1.y, 1, Math.abs(h))); } else { halls.push(new Rectangle(point2.x, point2.y, Math.abs(w), 1)); halls.push(new Rectangle(point1.x, point1.y, 1, Math.abs(h))); } } else // (h == 0) { halls.push(new Rectangle(point2.x, point2.y, Math.abs(w), 1)); } } else if (w > 0) { if (h < 0) { if (FlxG.random() < 0.5) { halls.push(new Rectangle(point1.x, point2.y, Math.abs(w), 1)); halls.push(new Rectangle(point1.x, point2.y, 1, Math.abs(h))); } else { halls.push(new Rectangle(point1.x, point1.y, Math.abs(w), 1)); halls.push(new Rectangle(point2.x, point2.y, 1, Math.abs(h))); } } else if (h > 0) { if (FlxG.random() < 0.5) { halls.push(new Rectangle(point1.x, point1.y, Math.abs(w), 1)); halls.push(new Rectangle(point2.x, point1.y, 1, Math.abs(h))); } else { halls.push(new Rectangle(point1.x, point2.y, Math.abs(w), 1)); halls.push(new Rectangle(point1.x, point1.y, 1, Math.abs(h))); } } else // (h == 0) { halls.push(new Rectangle(point1.x, point1.y, Math.abs(w), 1)); } } else // (w == 0) { if (h < 0) { halls.push(new Rectangle(point2.x, point2.y, 1, Math.abs(h))); } else if (h > 0) { halls.push(new Rectangle(point1.x, point1.y, 1, Math.abs(h))); } } }
createRooms()
function to createRooms()
function for each sheet that has a pair of child leaves: public function createRooms():void { // . if (leftChild != null || rightChild != null) { // , if (leftChild != null) { leftChild.createRooms(); } if (rightChild != null) { rightChild.createRooms(); } // , , if (leftChild != null && rightChild != null) { createHall(leftChild.getRoom(), rightChild.getRoom()); } } else { // var roomSize:Point; var roomPos:Point; // 3 x 3 - 2. roomSize = new Point(Registry.randomNumber(3, width - 2), Registry.randomNumber(3, height - 2)); // , ( ) roomPos = new Point(Registry.randomNumber(1, width - roomSize.x - 1), Registry.randomNumber(1, height - roomSize.y - 1)); room = new Rectangle(x + roomPos.x, y + roomPos.y, roomSize.x, roomSize.y); } }
Leaf
object that can be used to generate a tree of separated leaves, created random rooms in each of the leaves, and connected rooms with corridors.Source: https://habr.com/ru/post/332832/
All Articles