Exemplo n.º 1
0
        public void DefaultCorridorGenerator(DungeonBSPNode dungeonNode)
        {
            DungeonBSPNode leftChild = dungeonNode.LeftChild;
            DungeonBSPNode rightChild = dungeonNode.RightChild;

            DiggerGnome digger = new DiggerGnome(TargetMap);

            if (leftChild == null || !leftChild.RoomBuilt)
                dungeonNode.BoundingRect = rightChild.BoundingRect;
            else if (rightChild == null || !rightChild.RoomBuilt)
                dungeonNode.BoundingRect = leftChild.BoundingRect;
            else
            {
                // Draw a corridor between our child nodes.  We have been keeping track of their bounding rectangles
                // as we've worked our way up the tree, so we can use that ensure we connect corridors to rooms
                if (dungeonNode.SplitOrientation == DungeonBSPNode.Orientation.Horizontal)
                {
                    // child nodes were split horizontally, so draw a horizontal corridor between them.
                    // If the nodes' regions overlap vertically by at least 3 (leaving room for walls), then we can just dig a
                    // single horizontal tunnel to connect them; otherwise, we need to dig an 'L' shapped corridor to connect them.
                    int minOverlappingY = Math.Max(leftChild.BoundingRect.Top, rightChild.BoundingRect.Top);
                    int maxOverlappingY = Math.Min(leftChild.BoundingRect.Bottom, rightChild.BoundingRect.Bottom);
                    if (maxOverlappingY - minOverlappingY >= 3)
                    {
                        // The regions overlap; we can dig a single horizontal corridor to connect them
                        // Determine the range of Y axis values that we can dig at in order to connect the regions
                        int corridorY = minOverlappingY + 1 + Rand.Next(maxOverlappingY - minOverlappingY - 2);

                        // Start at the border between the two regions at Y=corridorY and dig towards the outside
                        // edge of each region; we are gauranteed to eventually hit something since the regions' bounding
                        // rects overlapped.
                        digger.Dig(leftChild.BoundingRect.Right, corridorY, Direction.Left, 0, true);
                        digger.Dig(leftChild.BoundingRect.Right + 1, corridorY, Direction.Right, 0, true);
                    }
                    else
                    {
                        // They don't overlap enough; dig an 'L' shaped corridor to connect them.
                        int tunnelMeetX, tunnelMeetY;

                        // Note that some of the math below (in particular the Mins and Maxs) are because the regions *can* be slightly overlapping in
                        // the appropriate dimension; we don't draw a straight line if they overlap by less than 3 (to minimize the number of odd corridors
                        // that attach to the outside corner of a room)
                        if (leftChild.BoundingRect.Top > rightChild.BoundingRect.Top)
                        {
                            // Left child region's bounding rect is below the Right child region's bound rect.
                            //        _____
                            //   X____|   |
                            //    |   | R |
                            //    |   |___|
                            //  __|__
                            //  |   |
                            //  | L |
                            //  |___|
                            tunnelMeetX = RandomValueBetween(leftChild.BoundingRect.Left + 1, leftChild.BoundingRect.Right);
                            tunnelMeetY = RandomValueBetween(rightChild.BoundingRect.Top + 1, Math.Min(rightChild.BoundingRect.Bottom - 1, leftChild.BoundingRect.Top));
                            digger.DigDownRightCorridor(tunnelMeetX, tunnelMeetY, tunnelMeetX, tunnelMeetY);
                        }
                        else
                        {
                            // Left child region's bounding rect is above the Right child region's bound rect.
                            //    _____
                            //    |   |____X
                            //    | L |   |
                            //    |___|   |
                            //          __|__
                            //          |   |
                            //          | R |
                            //          |___|
                            tunnelMeetX = RandomValueBetween(rightChild.BoundingRect.Left + 1, rightChild.BoundingRect.Right);
                            tunnelMeetY = RandomValueBetween(leftChild.BoundingRect.Top + 1, Math.Min(leftChild.BoundingRect.Bottom - 1, rightChild.BoundingRect.Top));
                            digger.DigDownLeftLCorridor(tunnelMeetX, tunnelMeetY, tunnelMeetX, tunnelMeetY);
                        }
                    }

                    // TBD: Need to set bounding rect for Special Rooms
                }
                else // Vertical split
                {
                    // child nodes were split vertically, so draw a vertical corridor between them.
                    // If the nodes' regions overlap horizontally by at least 3 (leaving room for walls), then we can just dig a
                    // single vertical tunnel to connect them; otherwise, we need to dig an 'L' shapped corridor to connect them.
                    int minOverlappingX = Math.Max(leftChild.BoundingRect.Left, rightChild.BoundingRect.Left);
                    int maxOverlappingX = Math.Min(leftChild.BoundingRect.Right, rightChild.BoundingRect.Right);
                    if (maxOverlappingX - minOverlappingX >= 3)
                    {
                        // The regions overlap; we can dig a single vertical corridor to connect them
                        // Determine the range of X axis values that we can dig at in order to connect the regions
                        int corridorX = minOverlappingX + 1 + Rand.Next(maxOverlappingX - minOverlappingX - 2);

                        // Start at the border between the two regions at X=corridorX and dig towards the outside
                        // edge of each region; we are gauranteed to eventually hit something since the regions' bounding
                        // rects overlapped.
                        digger.Dig(corridorX, leftChild.BoundingRect.Bottom, Direction.Up, 0, true);
                        digger.Dig(corridorX, leftChild.BoundingRect.Bottom + 1, Direction.Down, 0, true);
                    }
                    else
                    {
                        // They don't overlap enough; dig an 'L' shaped corridor to connect them.
                        int tunnelMeetX, tunnelMeetY;

                        if (leftChild.BoundingRect.Left > rightChild.BoundingRect.Left)
                        {
                            //        _____
                            //        |   |
                            //        | L |
                            //        |___|
                            //  _____   |
                            //  |   |   |
                            //  | R |___|X
                            //  |___|
                            tunnelMeetX = RandomValueBetween(Math.Max(leftChild.BoundingRect.Left + 1, rightChild.BoundingRect.Right + 1), leftChild.BoundingRect.Right);
                            tunnelMeetY = RandomValueBetween(rightChild.BoundingRect.Top + 1, rightChild.BoundingRect.Bottom);
                            digger.DigUpLeftCorridor(tunnelMeetX, tunnelMeetY, tunnelMeetX, tunnelMeetY);
                        }
                        else
                        {
                            //    _____
                            //    |   |
                            //    | L |
                            //    |___|
                            //      |    _____
                            //      |    |   |
                            //     X|____| R |
                            //           |___|
                            tunnelMeetX = RandomValueBetween(leftChild.BoundingRect.Left, Math.Min(rightChild.BoundingRect.Left, leftChild.BoundingRect.Right - 1));
                            tunnelMeetY = RandomValueBetween(rightChild.BoundingRect.Top + 1, rightChild.BoundingRect.Bottom);
                            digger.DigUpRightLCorridor(tunnelMeetX, tunnelMeetY, tunnelMeetX, tunnelMeetY);
                        }
                    }
                }

                // Determine our bounding rectangle (as the union of our child nodes' rectangles).
                dungeonNode.BoundingRect = Rectangle.Union(leftChild.BoundingRect, rightChild.BoundingRect);
            }

            // TBD: Not quite right - "RoomOrCorridorBuilt" more accurate
            dungeonNode.RoomBuilt = true;
        }
Exemplo n.º 2
0
        private void BruteForceConnectRooms(DungeonBSPNode regionA, DungeonBSPNode regionB)
        {
            // We don't care if we go through existing rooms; the goal is that we actually get atypical rooms...
            DiggerGnome digger = new DiggerGnome(TargetMap);

            if (regionA.BoundingRect.Bottom < regionB.BoundingRect.Top || regionB.BoundingRect.Bottom < regionA.BoundingRect.Top)
            {
                // Vertical split.  Determine which one is the upper & lower region
                DungeonBSPNode upperRegion = (regionA.BoundingRect.Bottom <= regionB.BoundingRect.Top) ? regionA : regionB;
                DungeonBSPNode lowerRegion = (upperRegion == regionA) ? regionB : regionA;

                // If the nodes' regions overlap horizontally by at least 3 (leaving room for walls), then we can just dig a
                // single vertical tunnel to connect them; otherwise, we need to dig an 'L' shapped corridor to connect them.
                int minOverlappingX = Math.Max(upperRegion.BoundingRect.Left, lowerRegion.BoundingRect.Left);
                int maxOverlappingX = Math.Min(upperRegion.BoundingRect.Right, lowerRegion.BoundingRect.Right);
                if (maxOverlappingX - minOverlappingX >= 3)
                {
                    // The regions overlap; we can dig a single vertical corridor to connect them
                    // Determine the range of X axis values that we can dig at in order to connect the regions
                    int corridorX = minOverlappingX + 1 + Rand.Next(maxOverlappingX - minOverlappingX - 2);

                    // Start at the border between the two regions at X=corridorX and dig towards the outside
                    // edge of each region; we are gauranteed to eventually hit something since the regions' bounding
                    // rects overlapped.
                    digger.Dig(corridorX, upperRegion.BoundingRect.Bottom, Direction.Up, 0, true);
                    digger.Dig(corridorX, upperRegion.BoundingRect.Bottom + 1, Direction.Down, lowerRegion.BoundingRect.Top - (upperRegion.BoundingRect.Bottom + 1), true);
                }
                else
                {
                    // They don't overlap enough; dig an 'L' shaped corridor to connect them.
                    int tunnelMeetX, tunnelMeetY;

                    if (upperRegion.BoundingRect.Left > lowerRegion.BoundingRect.Left)
                    {
                        //        _____
                        //        |   |
                        //        | L |
                        //        |___|
                        //  _____   |
                        //  |   |   |
                        //  | R |___|X
                        //  |___|
                        tunnelMeetX = RandomValueBetween(Math.Max(upperRegion.BoundingRect.Left + 1, lowerRegion.BoundingRect.Right + 1), upperRegion.BoundingRect.Right);
                        tunnelMeetY = RandomValueBetween(lowerRegion.BoundingRect.Top + 1, lowerRegion.BoundingRect.Bottom);
                        digger.DigUpLeftCorridor(tunnelMeetX, tunnelMeetY, lowerRegion.BoundingRect.Right, upperRegion.BoundingRect.Bottom);
                    }
                    else
                    {
                        //    _____
                        //    |   |
                        //    | L |
                        //    |___|
                        //      |    _____
                        //      |    |   |
                        //     X|____| R |
                        //           |___|
                        tunnelMeetX = RandomValueBetween(upperRegion.BoundingRect.Left + 1, Math.Min(lowerRegion.BoundingRect.Left, upperRegion.BoundingRect.Right - 1));
                        tunnelMeetY = RandomValueBetween(lowerRegion.BoundingRect.Top + 1, lowerRegion.BoundingRect.Bottom);
                        digger.DigUpRightLCorridor(tunnelMeetX, tunnelMeetY, lowerRegion.BoundingRect.Left, upperRegion.BoundingRect.Bottom);
                    }
                }
            }
            else
            {
                // Horizontal split.  Determine which one is the left & right region
                DungeonBSPNode leftRegion = (regionA.BoundingRect.Right <= regionB.BoundingRect.Left) ? regionA : regionB;
                DungeonBSPNode rightRegion = (leftRegion == regionA) ? regionB : regionA;

                // If the nodes' regions overlap vertically by at least 3 (leaving room for walls), then we can just dig a
                // single horizontal tunnel to connect them; otherwise, we need to dig an 'L' shapped corridor to connect them.
                int minOverlappingY = Math.Max(leftRegion.BoundingRect.Top, rightRegion.BoundingRect.Top);
                int maxOverlappingY = Math.Min(leftRegion.BoundingRect.Bottom, rightRegion.BoundingRect.Bottom);
                if (maxOverlappingY - minOverlappingY >= 3)
                {
                    // The regions overlap; we can dig a single horizontal corridor to connect them
                    // Determine the range of Y axis values that we can dig at in order to connect the regions
                    int corridorY = minOverlappingY + 1 + Rand.Next(maxOverlappingY - minOverlappingY - 2);

                    digger.Dig(leftRegion.BoundingRect.Right, corridorY, Direction.Left, 0, true);
                    digger.Dig(leftRegion.BoundingRect.Right + 1, corridorY, Direction.Right, rightRegion.BoundingRect.Left - (leftRegion.BoundingRect.Right + 1), true);
                }
                else
                {
                    // They don't overlap enough; dig an 'L' shaped corridor to connect them.
                    int tunnelMeetX, tunnelMeetY;

                    if (leftRegion.BoundingRect.Top > rightRegion.BoundingRect.Top)
                    {
                        // Left region's bounding rect is below the Right region's bound rect.
                        //        _____
                        //   X____|   |
                        //    |   | R |
                        //    |   |___|
                        //  __|__
                        //  |   |
                        //  | L |
                        //  |___|
                        tunnelMeetX = RandomValueBetween(leftRegion.BoundingRect.Left + 1, leftRegion.BoundingRect.Right);
                        tunnelMeetY = RandomValueBetween(rightRegion.BoundingRect.Top + 1, Math.Min(rightRegion.BoundingRect.Bottom - 1, leftRegion.BoundingRect.Top));
                        digger.DigDownRightCorridor(tunnelMeetX, tunnelMeetY, rightRegion.BoundingRect.Left, leftRegion.BoundingRect.Top);
                    }
                    else
                    {
                        // Left child region's bounding rect is above the Right child region's bound rect.
                        //    _____
                        //    |   |____X
                        //    | L |   |
                        //    |___|   |
                        //          __|__
                        //          |   |
                        //          | R |
                        //          |___|
                        tunnelMeetX = RandomValueBetween(rightRegion.BoundingRect.Left + 1, rightRegion.BoundingRect.Right);
                        tunnelMeetY = RandomValueBetween(leftRegion.BoundingRect.Top + 1, Math.Min(leftRegion.BoundingRect.Bottom - 1, rightRegion.BoundingRect.Top));
                        digger.DigDownLeftLCorridor(tunnelMeetX, tunnelMeetY, leftRegion.BoundingRect.Right, rightRegion.BoundingRect.Top);
                    }
                }
            }
        }