示例#1
0
    /// <summary>
    /// Gets all continuous left/right Lines from the given level using all the walls in the given column.
    /// The Lines are indexed by all wall bounds that make up part of that indexed Line.
    /// </summary>
    public static void GetVerticalLines(FillData data, WallToLines associations, int col)
    {
        int      startingY, currentY;
        Interval temp;
        ColType  current;
        bool     rightCol = (col == data.Map.GetLength(0) - 1);

        //Do the algorithm for both the left and the right of the column.
        int currentCol;

        for (int dir = -1; dir < 2; dir += 2)
        {
            currentCol = col + dir;
            current    = (currentCol > col ? ColType.Right : ColType.Left);

            //Take care of the edge case where the whole row is a valid line.
            bool colFree = true;
            for (int j = 0; j < data.Map.GetLength(1); ++j)
            {
                if (data.GetMapAt(new Location(currentCol, j)) ||
                    !data.GetMapAt(new Location(col, j)))
                {
                    colFree = false;
                    break;
                }
            }

            //If the whole column is one line, just use that.
            if (colFree)
            {
                //If the level wraps around, use a large line.
                if (data.WrapY)
                {
                    associations.AddReferences(GetBounds(new Line(Orientation.Vertical, new Interval(0, data.Map.GetLength(1) - 1, true, 2), col)),
                                               current,
                                               new Line(Orientation.Vertical, new Interval(-data.Map.GetLength(1), 2.0f * data.Map.GetLength(1), true, 2), (col + currentCol) * 0.5f));
                }
                else
                {
                    associations.AddReferences(GetBounds(new Line(Orientation.Vertical, new Interval(0, data.Map.GetLength(1) - 1, true, 2), col)),
                                               current,
                                               new Line(Orientation.Vertical, new Interval(0, data.Map.GetLength(1) - 1, true, 2), col));
                }
            }

            //Otherwise, go through one wall at a time and build individual collections of Lines.
            else
            {
                //An edge is a whole Line if it spans an unbroken column of walls with no walls covering the edge.

                //Use a counter to run through the whole column in groups of unbroken walls.
                startingY = 0;
                currentY  = 0;
                temp      = null;
                while (startingY < data.Map.GetLength(1))
                {
                    //Get the next valid spot to start from.
                    while ((!data.GetMapAt(new Location(col, startingY)) ||
                            data.GetMapAt(new Location(currentCol, startingY))) &&
                           startingY < data.Map.GetLength(1))
                    {
                        currentY += 1;
                        startingY = currentY;
                    }
                    if (startingY >= data.Map.GetLength(1))
                    {
                        break;
                    }

                    //Keep the counter going as long as the next spot is valid (i.e.
                    //  there is a wall to the side but not in the way).
                    while (data.GetMapAt(new Location(col, currentY + 1)) &&
                           !data.GetMapAt(new Location(currentCol, currentY + 1)) &&
                           currentY < data.Map.GetLength(1))
                    {
                        currentY += 1;
                    }

                    //Now make the line.
                    temp = new Interval(startingY, currentY, true, 2);
                    associations.AddReferences(GetBounds(new Line(Orientation.Vertical, temp, col)),
                                               current,
                                               new Line(Orientation.Vertical, temp, (col + currentCol) * 0.5f));

                    //If this is near the top, wrap it around to the bottom.
                    if (data.WrapY && temp.Start < 2.0f)
                    {
                        associations.AddReferences(GetBounds(new Line(Orientation.Vertical, temp + data.WorldSize.Y, col)),
                                                   current,
                                                   new Line(Orientation.Vertical, temp + data.WorldSize.Y, (col + currentCol) * 0.5f));
                    }

                    //Move to the next spot in the column.
                    startingY = currentY + 1;
                    currentY  = startingY;
                }

                //If the level wraps around in the Y, take the last Line and wrap it around.
                if (temp != null && data.WrapY)
                {
                    associations.AddReferences(GetBounds(new Line(Orientation.Vertical, temp - data.WorldSize.Y, col)),
                                               current,
                                               new Line(Orientation.Vertical, temp - data.WorldSize.Y, (col + currentCol) * 0.5f));
                }
            }
        }
    }
示例#2
0
    /// <summary>
    /// Gets all continuous top/bottom Lines from the given level using all the walls in the given row.
    /// The Lines are indexed by all wall bounds that make up part of that indexed Line.
    /// </summary>
    public static void GetHorizontalLines(FillData data, WallToLines associations, int row)
    {
        int      startingX, currentX;
        Interval temp;
        ColType  current;
        bool     bottomRow = (row == data.Map.GetLength(1) - 1);

        //Do the algorithm for both above and below the row.
        int currentRow;

        for (int dir = -1; dir < 2; dir += 2)
        {
            currentRow = row + dir;
            current    = (currentRow < row ? ColType.Bottom : ColType.Top);

            //There is one special case: the whole row is a valid line.
            bool rowFree = true;
            for (int i = 0; i < data.Map.GetLength(0); ++i)
            {
                if (data.GetMapAt(new Location(i, currentRow)) ||
                    !data.GetMapAt(new Location(i, row)))
                {
                    rowFree = false;
                    break;
                }
            }

            //If the whole row is one line, just use that.
            if (rowFree)
            {
                //If the level wraps around, use a large line.
                if (data.WrapX)
                {
                    associations.AddReferences(GetBounds(new Line(Orientation.Horizontal, new Interval(0, data.Map.GetLength(0) - 1, true, 2), row)),
                                               current,
                                               new Line(Orientation.Horizontal, new Interval(-data.Map.GetLength(0), 2.0f * data.Map.GetLength(0), true, 2), (row + currentRow) * 0.5f));
                }
                else
                {
                    associations.AddReferences(GetBounds(new Line(Orientation.Horizontal, new Interval(0, data.Map.GetLength(0) - 1, true, 2), row)),
                                               current,
                                               new Line(Orientation.Horizontal, new Interval(0, data.Map.GetLength(0) - 1, true, 2), row));
                }
            }

            //Otherwise, go through one wall at a time and build individual collections of Lines.
            else
            {
                //An edge is a whole Line if it spans an unbroken row of walls with no walls covering the edge.

                //Use a counter to run through the whole row in groups of unbroken rows.
                startingX = 0;
                currentX  = 0;
                temp      = null;
                while (startingX < data.Map.GetLength(0))
                {
                    //Get the next valid spot to start from.
                    while ((!data.GetMapAt(new Location(startingX, row)) ||
                            data.GetMapAt(new Location(startingX, currentRow))) &&
                           startingX < data.Map.GetLength(0))
                    {
                        currentX += 1;
                        startingX = currentX;
                    }
                    if (startingX >= data.Map.GetLength(0))
                    {
                        break;
                    }

                    //Keep the counter going as long as the next spot is valid (i.e.
                    //  there is a wall in this row but not above/underneath).
                    while (data.GetMapAt(new Location(currentX + 1, row)) &&
                           !data.GetMapAt(new Location(currentX + 1, currentRow)) &&
                           currentX < data.Map.GetLength(0))
                    {
                        currentX += 1;
                    }

                    //Now make the line.
                    temp = new Interval(startingX, currentX, true, 2);
                    associations.AddReferences(GetBounds(new Line(Orientation.Horizontal, temp, row)),
                                               current,
                                               new Line(Orientation.Horizontal, temp, (row + currentRow) * 0.5f));

                    //If this is near the left, wrap it around to the right.
                    if (data.WrapX && temp.Start < 2.0f)
                    {
                        associations.AddReferences(GetBounds(new Line(Orientation.Horizontal, temp + data.WorldSize.X, row)),
                                                   current,
                                                   new Line(Orientation.Horizontal, temp + data.WorldSize.X, (row + currentRow) * 0.5f));
                    }

                    //Move to the next spot in the row.
                    startingX = currentX + 1;
                    currentX  = startingX;
                }

                //If the level wraps around in the X, take the last Line and wrap it around.
                if (temp != null && data.WrapX)
                {
                    associations.AddReferences(GetBounds(new Line(Orientation.Horizontal, temp - data.WorldSize.X, row)),
                                               current,
                                               new Line(Orientation.Horizontal, temp - data.WorldSize.X, (row + currentRow) * 0.5f));
                }
            }
        }
    }