示例#1
0
        public void PartitionAround(Rectangle boundingRect)
        {
            float startX = (float)boundingRect.Left / Map.MapWidth;
            float startY = (float)boundingRect.Top / Map.MapHeight;
            float endX = (float)boundingRect.Right/ Map.MapWidth;
            float endY = (float)boundingRect.Bottom/ Map.MapHeight;

            // Create partitions around the carved out space, and don't partition the carved out space further

            // Here is how we create the partitions around the carved out space (marked with " XX ").  The #s
            // represent the splits...
            // ________________________
            // |                      |
            // |                      |
            // |                      |
            // |____1_________________|
            // |        |    |        |
            // |        | XX 4        |
            // |        |____|___3____|
            // |        |             |
            // |        2             |
            // |        |             |
            // |________|_____________|

            // Do first split (#1) horizontally along the top edge of the carved out space
            this.SplitOrientation = Orientation.Vertical;
            this.SplitLocation = startX;
            if (startY == RegionEdges.Top)
                LeftChild = null;    // Carved out partition abuts the TopEdge, so no need to create a 'Left' part
            else
            {
                LeftChild = new DungeonBSPNode(RegionEdges.Left, RegionEdges.Top, RegionEdges.Right, startY);
                if (WeShouldSplit(startY - RegionEdges.Top))
                    LeftChild.Partition();
            }
            RightChild = new DungeonBSPNode(RegionEdges.Left, startY, RegionEdges.Right, RegionEdges.Bottom);

            // Do second split (#2) vertically along the left edge of the carved out space
            RightChild.SplitOrientation = Orientation.Horizontal;
            RightChild.SplitLocation = startY;
            if (startX == RegionEdges.Left)
                RightChild.LeftChild = null;    // Carved out partition abuts the LeftEdge, so no need to create a 'Left' part
            else
            {
                RightChild.LeftChild = new DungeonBSPNode(RegionEdges.Left, startY, startX, RegionEdges.Bottom);
                if (WeShouldSplit(startX - RegionEdges.Left))
                    RightChild.LeftChild.Partition();
            }
            RightChild.RightChild = new DungeonBSPNode(startX, startY, RegionEdges.Right, RegionEdges.Bottom);

            // Do third split (#3) horizontally along the bottom edge of the carved out space
            RightChild.RightChild.SplitOrientation = Orientation.Vertical;
            RightChild.RightChild.SplitLocation = endY;
            if (RegionEdges.Bottom == endY)
                RightChild.RightChild.RightChild = null;    // Carved out partition abuts the BottomEdge, so no need to create a 'Right' part
            else
            {
                RightChild.RightChild.RightChild = new DungeonBSPNode(startX, endY, RegionEdges.Right, RegionEdges.Bottom);
                if (WeShouldSplit(RegionEdges.Bottom - endY))
                    RightChild.RightChild.RightChild.Partition();
            }
            RightChild.RightChild.LeftChild = new DungeonBSPNode(startX, startY, RegionEdges.Right, endY);

            // Do fourth split (#4) vertically along the right edge of the carved out space
            RightChild.RightChild.LeftChild.SplitOrientation = Orientation.Horizontal;
            RightChild.RightChild.LeftChild.SplitLocation = endX;
            if (RegionEdges.Right == endX)    // Carved out partition abuts the RightEdge, so no need to create a 'Right' part
                RightChild.RightChild.LeftChild.RightChild = null;
            else
            {
                RightChild.RightChild.LeftChild.RightChild = new DungeonBSPNode(endX, startY, RegionEdges.Right, endY);
                if (WeShouldSplit(RegionEdges.Right - endX))
                    RightChild.RightChild.LeftChild.RightChild.Partition();
            }

            // Finally, partition the carved out space (and don't further partition it)
            RightChild.RightChild.LeftChild.LeftChild = new DungeonBSPNode(startX, startY, endX, endY);

            // Mark that the carved-out partition is pre-populated (don't add a room to it)
            RightChild.RightChild.LeftChild.LeftChild.RoomBuilt = true;
            RightChild.RightChild.LeftChild.LeftChild.BoundingRect = boundingRect;
        }
        private DungeonBSPNode PartitionDungeon()
        {
            // Initialize a few variables.  These'll eventually be removed
            DungeonBSPNode.Map = TargetMap;

            // I eventually want to share the random # generator across all objects, so that all that's
            // necessary to completely recreate a particular run is the initial Seed & the list of user inputs/
            DungeonBSPNode.rand = TargetMap.rand;

            // Create the root node;  it covers the entire space (0.0,0.0) - (1.0,1.0)
            DungeonBSPNode rootNode = new DungeonBSPNode(0.0f, 0.0f, 1.0f, 1.0f);

            // Add Special Room before partitioning
            /*            if (false) // place special room
            {
                Room prefabRoom = Room.LoadRandom();

                int xSpecialRoomStart = 20;
                int ySpecialRoomStart = 20;
                prefabRoom.BoundingRect = new Rectangle(prefabRoom.BoundingRect.Left + xSpecialRoomStart,
                                                        prefabRoom.BoundingRect.Top + ySpecialRoomStart,
                                                        prefabRoom.BoundingRect.Width, prefabRoom.BoundingRect.Height);

                // Add the room to the Map.
                TargetMap.PaintRoom(xSpecialRoomStart, ySpecialRoomStart, prefabRoom.RoomCells);

                // Partition the remaining dungeon layer around the placed room
                rootNode.PartitionAround(prefabRoom.BoundingRect);
            }
            else
            {
            */                // No special room
                rootNode.Partition();
            //            }
            return rootNode;
        }
示例#3
0
        /// <summary>
        /// Partitions (splits) this node into two halves, and then creates child nodes for
        /// each half and recursively partitions both of them (if they are not 'too small').
        /// </summary>
        public void Partition()
        {
            // Choose the axis along which we'll partition (split) this node.  If this is a very
            // narrow node in one axis, then favor the other axis in order to minimize long corridor-like rooms.
            if (RegionEdges.Width / RegionEdges.Height > MaxPartitionSizeRatio)
                SplitOrientation = Orientation.Horizontal;
            else if (RegionEdges.Height / RegionEdges.Width > MaxPartitionSizeRatio)
                SplitOrientation = Orientation.Vertical;
            else
                SplitOrientation = (rand.Next(2) == 1) ? Orientation.Horizontal : Orientation.Vertical;

            // Split the Node.
            if (SplitOrientation == Orientation.Horizontal)
            {
                // Pick the location along the XAxis (between the LeftEdge and RightEdge) at which we will split.
                SplitLocation = RegionEdges.Left + HomogenizedRandomValue() * RegionEdges.Width;

                // Create our two child nodes
                LeftChild = new DungeonBSPNode(RegionEdges.Left, RegionEdges.Top, SplitLocation, RegionEdges.Bottom);
                RightChild = new DungeonBSPNode(SplitLocation, RegionEdges.Top, RegionEdges.Right, RegionEdges.Bottom);

                SetDebugNames();

                // Partition child nodes if either is not yet too small
                if (WeShouldSplit(SplitLocation - RegionEdges.Left))
                    LeftChild.Partition();
                if (WeShouldSplit(RegionEdges.Right - SplitLocation))
                    RightChild.Partition();
            }
            else // Vertical split
            {
                // Pick the location along the YAxis (between the TopEdge and BottomEdge) at which we will split.
                SplitLocation = RegionEdges.Top + HomogenizedRandomValue() * RegionEdges.Height;

                // Create our two (Left = upper and Right = lower) child nodes
                LeftChild = new DungeonBSPNode(RegionEdges.Left, RegionEdges.Top, RegionEdges.Right, SplitLocation);
                RightChild = new DungeonBSPNode(RegionEdges.Left, SplitLocation, RegionEdges.Right, RegionEdges.Bottom);

                SetDebugNames();

                // Partition child nodes if either is not yet too small
                if (WeShouldSplit(SplitLocation - RegionEdges.Top))
                    LeftChild.Partition();
                if (WeShouldSplit(RegionEdges.Bottom - SplitLocation))
                    RightChild.Partition();
            }
        }