public FilledRegion Apply(FillData data)
    {
        //The spawning areas.
        List <Region> spawningAreas = new List <Region>();

        //Get/set some data.
        Region area = data.BeingFilled;

        PlateauGeneration.BeingFilled = data.BeingFilled;
        //If the corridor is going to be vertical, flip the width and height.
        if (area.Height > area.Width)
        {
            PlateauGeneration.BeingFilled = new Region(area.Y, area.X, area.Height, area.Width);
        }

        int numb        = PlateauGeneration.NumbPlateaus;
        int plateauSize = PlateauGeneration.PlateauWidth;

        int space  = PlateauGeneration.SpaceBetweenPlateaus;
        int border = PlateauGeneration.Border;

        //Plateau size data.
        //"maxSize" is the largest allowable hurdle height.
        int maxSize = PlateauGeneration.BeingFilled.Height - 1;

        if (area.Height > area.Width)
        {
            //Vertical.

            //Add the plateaus.
            int hurdleWidth, plateauExtent;
            for (int i = 0; i < numb; ++i)
            {
                //Get a width within the given random variation.
                hurdleWidth = (int)Math.Round((area.Width + 1) * (HurdleAverageSpaceScale + ((2 * HurdleHeightVariance * (float)GeneratorSettings.R.NextDouble()) - HurdleHeightVariance)), 0);
                //Keep it constrained.
                if (hurdleWidth > maxSize)
                {
                    hurdleWidth = maxSize;
                }
                if (hurdleWidth < 1)
                {
                    hurdleWidth = 1;
                }

                //Get the width of the plateau given the size of a hurdle.
                plateauExtent  = area.Width + 1 - hurdleWidth;
                plateauExtent /= 2;

                //Fill in the plateaus.
                data.FillRegion(true, new Region(area.Left, area.Top + border + (i * (space + plateauSize)), plateauExtent - 1, plateauSize - 1));
                if ((2 * plateauExtent) + hurdleWidth >= area.Width + 1)
                {
                    data.FillRegion(true, new Region(area.Right - plateauExtent + 1, area.Top + border + (i * (space + plateauSize)), plateauExtent - 1, plateauSize - 1));
                }
                else
                {
                    data.FillRegion(true, new Region(area.Right - plateauExtent, area.Top + border + (i * (space + plateauSize)), plateauExtent, plateauSize - 1));
                }
            }

            //Make room for any holes that the plateaus covered.
            foreach (Location l in data.HolesAlongPerimeter())
            {
                //The hole is covered if it is just left/right of the region and the space just right/left of it (respectively) is filled.
                if ((area.Touches(l.Left, true, true, false) && data.GetMapAt(l.Left)) ||
                    (area.Touches(l.Right, true, true, false) && data.GetMapAt(l.Right)))
                {
                    //Make a little tunnel under the plateau.
                    int[]  plateauSides = SteppedHallwayPattern.PlateauSides(l.Y, numb, plateauSize, space, border, area.Top, area.Bottom);
                    Region cleared;
                    if (l.X - 1 == area.Right)
                    {
                        cleared = new Region(data.BeingFilled.Right, plateauSides[0], 0, plateauSize - 1);
                    }
                    else
                    {
                        cleared = new Region(data.BeingFilled.Left, plateauSides[0], 0, plateauSize - 1);
                    }
                    data.FillRegion(false, cleared);
                }
            }
        }
        else
        {
            //Horizontal.

            //Add the plateaus.
            int hurdleHeight, plateauHeight;
            for (int i = 0; i < numb; ++i)
            {
                //Get a height within the given random variation.
                hurdleHeight = (int)Math.Round((area.Height + 1) * (HurdleAverageSpaceScale + ((2 * HurdleHeightVariance * (float)GeneratorSettings.R.NextDouble()) - HurdleHeightVariance)), 0);
                //Keep it constrained.
                if (hurdleHeight > maxSize)
                {
                    hurdleHeight = maxSize;
                }
                if (hurdleHeight < 1)
                {
                    hurdleHeight = 1;
                }

                //Get the height of the plateau given the size of a hurdle.
                plateauHeight  = area.Height + 1 - hurdleHeight;
                plateauHeight /= 2;

                //Fill in the plateaus.
                data.FillRegion(true, new Region(area.Left + border + (i * (space + plateauSize)), area.Top, plateauSize - 1, plateauHeight - 1));
                if ((2 * plateauHeight) + hurdleHeight >= area.Height + 1)
                {
                    data.FillRegion(true, new Region(area.Left + border + (i * (space + plateauSize)), area.Bottom - plateauHeight + 1, plateauSize - 1, plateauHeight - 1));
                    spawningAreas.Add(new Region(area.Left + border + (i * (space + plateauSize)), area.Top + plateauHeight, plateauSize - 1, data.BeingFilled.Height - plateauHeight - plateauHeight - 2));
                }
                else
                {
                    data.FillRegion(true, new Region(area.Left + border + (i * (space + plateauSize)), area.Bottom - plateauHeight, plateauSize - 1, plateauHeight));
                    spawningAreas.Add(new Region(area.Left + border + (i * (space + plateauSize)), area.Top + plateauHeight, plateauSize - 1, data.BeingFilled.Height - plateauHeight - plateauHeight - 1));
                }
            }
        }


        //Make room for any holes that the plateaus covered.
        foreach (Location l in data.HolesAlongPerimeter())
        {
            //Horizontal.
            if (area.Height < area.Width)
            {
                //The hole is covered if it is just below/above the region and the space above/below it (respectively) is filled.
                if ((area.Touches(l.Above, true, true, false) && data.GetMapAt(l.Above)) ||
                    (area.Touches(l.Below, true, true, false) && data.GetMapAt(l.Below)))
                {
                    //Make a little tunnel under the plateau.
                    int[] plateauSides = SteppedHallwayPattern.PlateauSides(l.X, numb, plateauSize, space, border, area.Left, area.Right);

                    Region cleared;
                    if (l.Y - 1 == area.Bottom)
                    {
                        cleared = new Region(plateauSides[0], data.BeingFilled.Bottom, plateauSize - 1, 0);
                    }
                    else
                    {
                        cleared = new Region(plateauSides[0], data.BeingFilled.Top, plateauSize - 1, 0);
                    }

                    data.FillRegion(false, cleared);
                }
            }

            //Vertical.
            else if ((area.Touches(l.Left, true, true, false) && data.GetMapAt(l.Left)) ||
                     (area.Touches(l.Right, true, true, false) && data.GetMapAt(l.Right)))
            {
                //Make a little tunnel under the plateau.
                int[] plateauSides = SteppedHallwayPattern.PlateauSides(l.Y, numb, plateauSize, space, border, area.Top, area.Bottom);

                Region cleared;
                if (l.X - 1 == area.Right)
                {
                    cleared = new Region(data.BeingFilled.Right, plateauSides[0], 0, plateauSize - 1);
                }
                else
                {
                    cleared = new Region(data.BeingFilled.Left, plateauSides[0], 0, plateauSize - 1);
                }

                data.FillRegion(false, cleared);
            }
        }

        //Return the new regions.
        return(new ThickHurdleRegion(data.BeingFilled, spawningAreas));
    }
Exemplo n.º 2
0
    public FilledRegion Apply(FillData data)
    {
        //Start on either the relative top or bottom of the corridor.
        bool top = MathF.R.NextDouble() > 0.5;

        //Set up the plateau properties.
        bool horizontal = data.BeingFilled.Width > data.BeingFilled.Height;

        if (horizontal)
        {
            Generation.BeingFilled = data.BeingFilled;
        }
        else
        {
            Generation.BeingFilled = new Region(data.BeingFilled.Y,
                                                data.BeingFilled.X,
                                                data.BeingFilled.Height,
                                                data.BeingFilled.Width);
        }

        int spaceBetween = Generation.SpaceBetweenPlateaus;
        int border       = Generation.Border;
        int plateauWidth = Generation.PlateauWidth;
        int numbPlateaus = Generation.NumbPlateaus;

        //Fill the area. Also keep track of the free space above/below plateaus.
        List <Region> freeAreas = new List <Region>();

        for (int i = 0; i < numbPlateaus; ++i)
        {
            if (top)
            {
                if (horizontal)
                {
                    data.FillRegion(true, new Region(data.BeingFilled.Left + border + (i * (spaceBetween + plateauWidth)),
                                                     data.BeingFilled.Top,
                                                     plateauWidth - 1,
                                                     data.BeingFilled.Height - 1));
                    freeAreas.Add(new Region(data.BeingFilled.Left + border + (i * (spaceBetween + plateauWidth)),
                                             data.BeingFilled.Bottom,
                                             plateauWidth - 1, 0));
                }
                else
                {
                    data.FillRegion(true, new Region(data.BeingFilled.Left,
                                                     data.BeingFilled.Top + border + (i * (spaceBetween + plateauWidth)),
                                                     data.BeingFilled.Width - 1,
                                                     plateauWidth - 1));
                    freeAreas.Add(new Region(data.BeingFilled.Left + 1,
                                             data.BeingFilled.Top + border + (i * (spaceBetween + plateauWidth)) - 1,
                                             data.BeingFilled.Width - 2, 0));
                }
            }
            else
            {
                if (horizontal)
                {
                    data.FillRegion(true, new Region(data.BeingFilled.Left + border + (i * (spaceBetween + plateauWidth)),
                                                     data.BeingFilled.Top + 1,
                                                     plateauWidth - 1,
                                                     data.BeingFilled.Height - 1));
                    freeAreas.Add(new Region(data.BeingFilled.Left + border + (i * (spaceBetween + plateauWidth)),
                                             data.BeingFilled.Top,
                                             plateauWidth - 1, 0));
                }
                else
                {
                    data.FillRegion(true, new Region(data.BeingFilled.Left + 1,
                                                     data.BeingFilled.Top + border + (i * (spaceBetween + plateauWidth)),
                                                     data.BeingFilled.Width - 1,
                                                     plateauWidth - 1));
                    freeAreas.Add(new Region(data.BeingFilled.Left + 1,
                                             data.BeingFilled.Top + border + (i * (spaceBetween + plateauWidth)) - 1,
                                             data.BeingFilled.Width - 2, 0));
                }
            }

            top = !top;
        }

        Region area = data.BeingFilled;

        //Make room for any holes that the plateaus covered.
        //TODO: Instead of clearing out the bottom, just clear that column of plateau. Possibly also do this for other plateau patterns?
        foreach (Location l in data.HolesAlongPerimeter())
        {
            //Horizontal.
            if (area.Height < area.Width)
            {
                //The hole is covered if it is just below/above the region and the space above/below it (respectively) is filled.
                if ((area.Touches(l.Above, true, true, false) && data.GetMapAt(l.Above)) ||
                    (area.Touches(l.Below, true, true, false) && data.GetMapAt(l.Below)))
                {
                    //Make a little tunnel under the plateau.
                    int[] plateauSides = SteppedHallwayPattern.PlateauSides(l.X, numbPlateaus, plateauWidth, spaceBetween, border, area.Left, area.Right);

                    Region cleared;
                    if (l.Y - 1 == area.Bottom)
                    {
                        cleared = new Region(plateauSides[0], data.BeingFilled.Bottom, plateauWidth - 1, 0);
                    }
                    else
                    {
                        cleared = new Region(plateauSides[0], data.BeingFilled.Top, plateauWidth - 1, 0);
                    }

                    data.FillRegion(false, cleared);
                }
            }

            //Vertical
            else if ((area.Touches(l.Left, true, true, false) && data.GetMapAt(l.Left)) ||
                     (area.Touches(l.Right, true, true, false) && data.GetMapAt(l.Right)))
            {
                //Make a little tunnel under the plateau.
                int[] plateauSides = SteppedHallwayPattern.PlateauSides(l.Y, numbPlateaus, plateauWidth, spaceBetween, border, area.Top, area.Bottom);

                Region cleared;
                if (l.X - 1 == area.Right)
                {
                    cleared = new Region(data.BeingFilled.Right, plateauSides[0], 0, plateauWidth - 1);
                }
                else
                {
                    cleared = new Region(data.BeingFilled.Left, plateauSides[0], 0, plateauWidth - 1);
                }

                data.FillRegion(false, cleared);
            }
        }

        if (horizontal)
        {
            return(new ZipperRegion(data.BeingFilled, freeAreas));
        }
        else
        {
            return(new ZipperRegion(data.BeingFilled, new List <Region>()));
        }
    }