public static bool AppendPieceH(LevelPiece left, LevelPiece right, bool noExcept = false)
        {
            Pair L1ExitCoord  = GetExitCoord(ref left.File);   // Get entry and exit coords
            Pair L2EntryCoord = GetEntryCoord(ref right.File);

            // check for mismatch in level exit/entrance
            //if (left.CeilingEx != right.CeilingEn) FixCeiling(ref left, ref right);
            //if (left.FloorEx   != right.FloorEn)   FixFloor(ref left, ref right);

            // establish level boundaries and new level size
            Pair L1Origin = new Pair(), L2Origin = new Pair();                      // initialize

            GetLevelOrigins(L1ExitCoord, L2EntryCoord, ref L1Origin, ref L2Origin); // set the values in this function

            // calculate dimensions for new level
            int width  = L1ExitCoord.Second + right.File.header.width - L2EntryCoord.Second + 1;
            int height = Math.Max(L1Origin.First + left.File.header.height, L2Origin.First + right.File.header.height);

            // check for and correct ceiling and floor compatibility
            LevelPiece transition = new LevelPiece(new LevelFile(0, 0)); Pair TOrigin = new Pair();

            if (left.CeilingEx != right.CeilingEn || left.FloorEx != right.FloorEn)
            {
                transition     = CheckCeilingFloor(ref left, ref right);
                TOrigin.First  = L1Origin.First + L1ExitCoord.First - transition.File.header.height + 2;
                TOrigin.Second = L2Origin.Second;
                width++; L2Origin.Second++;
            }

            // noExcept is used to make sure that the entrances and exits
            // can be added without triggering the size limitation
            if (!noExcept && (height > UsableHeight || width > UsableWidth))
            {
                return(false);
            }

            TempLevel = GetNewLevelFile(width, height);             // create new level
            CopyToCoords(ref left.File, ref TempLevel, L1Origin);   // copy left  level into new level
            if (transition.File.header.height != 0)
            {
                CopyToCoords(ref transition.File, ref TempLevel, TOrigin);
            }
            CopyToCoords(ref right.File, ref TempLevel, L2Origin);  // copy right level into new level

            // get rid of old entrances
            int index = (L1Origin.First + L1ExitCoord.First) * TempLevel.header.width + (L1Origin.Second + L1ExitCoord.Second);

            TempLevel.data.tag[index] = TileID.Empty;
            index = (L2Origin.First + L2EntryCoord.First) * TempLevel.header.width + (L2Origin.Second + L2EntryCoord.Second);
            TempLevel.data.tag[index] = TileID.Empty;

            // set canvas piece info
            Canvas.File      = TempLevel;
            Canvas.FloorEn   = left.FloorEn;
            Canvas.FloorEx   = right.FloorEx;
            Canvas.CeilingEn = left.CeilingEn;
            Canvas.CeilingEx = right.CeilingEx;

            return(true);
        }
        public static bool GetNextPiece(int maxHeight, int maxWidth)
        {
            var pool = new List <LevelPiece>();

            foreach (LevelPiece piece in Pieces)
            {
                if (piece.Name != LastPiece.Name)
                {
                    if (EntranceDirection == Direction.Any || piece.Entrance == EntranceDirection) // entrance check
                    //if (piece.CeilingEn == Canvas.CeilingEx && piece.FloorEn == Canvas.FloorEx)
                    {
                        if (ExitDirection == Direction.Any || piece.Exit == ExitDirection)                    // exit check
                        {
                            if (piece.File.header.height <= maxHeight && piece.File.header.width <= maxWidth) // piece size check
                            {
                                pool.Add(piece);
                            }
                        }
                    }
                }
            }

            if (pool.Count == 0)
            {
                return(false);
            }
            else
            {
                NextPiece = pool[RNG.random.Next(0, pool.Count())];
            }
            return(true);
        }
        static LevelPiece CheckCeilingFloor(ref LevelPiece left, ref LevelPiece right)
        {
            Pair L1ExitCoord  = GetExitCoord(ref left.File);
            Pair L2EntryCoord = GetEntryCoord(ref right.File);

            int        ceilingHeight = 0;
            LevelPiece transition    = new LevelPiece(new LevelFile(1, 3));

            if (left.CeilingEx != right.CeilingEn) // check ceiling height
            {
                TileID sidePiece = TileID.SmallSideL;
                if (left.CeilingEx)
                {
                    ceilingHeight = GetCeilingHeight(left.File, L1ExitCoord);
                }
                else
                {
                    ceilingHeight = GetCeilingHeight(right.File, L2EntryCoord); sidePiece = TileID.SmallSideR;
                }
                transition = new LevelPiece(new LevelFile(1, ceilingHeight + 2));
                for (int i = 1; i < ceilingHeight; i++)
                {
                    if (RNG.CoinFlip())
                    {
                        transition.File.data.back1[i] = sidePiece;
                    }
                }
            }

            int lh = transition.File.header.height;

            if (left.FloorEx || right.FloorEn) // check floor
            {
                if (left.CeilingEx)
                {
                    transition.File.data.back1[lh - 2] = TileID.LargeCornerBL;
                }
                else if (right.CeilingEn)
                {
                    transition.File.data.back1[lh - 2] = TileID.LargeCornerBR;
                }
                transition.File.data.active[lh - 1] = TileID.Solid; // add ground
            }

            //LevelFile tempFile = GetNewLevelFile(left.File.header.width + 1, left.File.header.height);
            //Pair tCoords = new Pair(L1ExitCoord.First - ceilingHeight, left.File.header.width - 1);

            //CopyToCoords(ref left.File, ref tempFile, new Pair(0,0));
            //CopyToCoords(ref transition.File, ref tempFile, new Pair(0,0));

            return(transition);
        }
        static void InitGenInfo()
        {
            LastPiece         = new LevelPiece();
            NextPiece         = new LevelPiece();
            EntranceDirection = Direction.Left;
            ExitDirection     = Direction.Right;
            WidthRemaining    = UsableWidth;

            if (RNG.CoinFlip())
            {
                Canvas.FloorEx = true; Canvas.CeilingEx = true;
            }
            ;
            //CameraBounds = { }
        }
        public static bool GetPieceEntrances(ref LevelPiece piece)
        {
            int index = 0;
            int lw    = piece.File.header.width;
            int lh    = piece.File.header.height;

            for (int i = 0; i < lh; i++)
            {
                for (int j = 0; j < lw; j++)
                {
                    index = i * lw + j;

                    switch (piece.File.data.tag[index])
                    {
                    case TileID.GreenTransitionL:
                        piece.Entrance = Direction.Left;
                        break;

                    case TileID.GreenTransitionD:
                        piece.Entrance = Direction.Down;
                        break;

                    case TileID.YellowTransitionR:
                        piece.Exit = Direction.Right;
                        break;

                    case TileID.YellowTransitionU:
                        piece.Exit = Direction.Up;
                        break;
                    }
                }
            }

            if (piece.Entrance != Direction.None && piece.Exit != Direction.None)
            {
                return(true);
            }
            else
            {
                Console.WriteLine($"Piece {piece.Name} is missing an entrance or exit.");
                return(false);
            }
        }
Exemplo n.º 6
0
        public static PiecePool LoadPiecePool(string fileName, string folder)
        {
            PiecePool pool = new PiecePool();

            pool.Name = fileName;
            //pool.Folder = folder;
            pool.Pieces = new List <LevelPiece>();

            var doc = XDocument.Load($"data/piecepools/{pool.Name}.xml");    // open levelpool file

            pool.Active = Convert.ToBoolean(doc.Root.Attribute("enabled").Value == "True");
            pool.Order  = Convert.ToInt16(doc.Root.Attribute("order").Value);
            pool.Author = (doc.Root.Attribute("author").Value);
            pool.Source = doc.Root.Attribute("source").Value;
            foreach (var element in doc.Root.Elements())
            {
                if (element.Name == "piece")
                {
                    var piece = new LevelPiece {
                    };
                    piece.Name      = element.Attribute("name").Value;
                    piece.Folder    = pool.Name;
                    piece.File      = LevelManip.Load($"data/levelpieces/{piece.Folder}/{piece.Name}.lvl");
                    piece.CeilingEn = Convert.ToBoolean(element.Attribute("ceilingEn").Value);
                    piece.CeilingEx = Convert.ToBoolean(element.Attribute("ceilingEx").Value);
                    piece.FloorEn   = Convert.ToBoolean(element.Attribute("floorEn").Value);
                    piece.FloorEx   = Convert.ToBoolean(element.Attribute("floorEx").Value);

                    if (element.Attribute("marginTop") != null)
                    {
                        piece.Margin.Top = Convert.ToInt32(element.Attribute("marginTop").Value);
                    }
                    if (element.Attribute("marginBottom") != null)
                    {
                        piece.Margin.Bottom = Convert.ToInt32(element.Attribute("marginTop").Value);
                    }

                    pool.Pieces.Add(piece);
                }
            }
            pool.NumPieces = pool.Pieces.Count.ToString() + " pieces";
            return(pool);
        }
        public static LevelFile CreateLevel(/*Direction EnDir = Direction.Right, Direction ExDir = Direction.Right*/) // later I will want to be able to specify the entrance and exit direction
        {
            InitGenInfo();                                                                                            // Initialize the generator info

            /*if (!*/
            GetNextPiece(100, 100);
            //)    // select first piece
            //{ Console.WriteLine("null starting level"); return null; }
            Canvas = NextPiece;    // initializes canvas to first piece selected
            //Canvas.CeilingEn = NextPiece.CeilingEn;
            //Canvas.CeilingEx = NextPiece.CeilingEx;
            //Canvas.FloorEn = NextPiece.FloorEn;
            //Canvas.FloorEx = NextPiece.FloorEx;

            int numPieces = 0;

            while (true)
            {
                LastPiece = NextPiece;                                      // the old new piece becomes the new old piece
                Direction entranceDir = (Direction)(-(int)LastPiece.Exit);  // get the opposite direction of the exit
                WidthRemaining = UsableWidth - Canvas.File.header.width;    // The amount of space left before reaching the usable width limit

                if (!AttemptAddPiece())
                {
                    break;                     // try to add a new piece. if this fails, break from the loop
                }
                if (Canvas.File.header.height >= UsableHeight || Canvas.File.header.width >= UsableWidth)
                {
                    break;   // perform size check
                }
                numPieces++; // piece number check
                if (numPieces >= MaxPieces)
                {
                    break;
                }
            }

            //int widthToReach = Canvas.header.height * 16 / 9;    // The width required to meet a 16:9 aspect ratio
            //int difference = widthToReach - Canvas.header.width; // If the level is too thin, we want to add more pieces.

            // Finalizing the level, Add entrance and exit landing
            if (Canvas.CeilingEn)
            {
                AppendPieceH(LTransitionC, Canvas, true);
            }
            else
            {
                AppendPieceH(LTransition, Canvas, true);
            }
            if (Canvas.CeilingEx)
            {
                AppendPieceH(Canvas, RTransitionC, true);
            }
            else
            {
                AppendPieceH(Canvas, RTransition, true);
            }



            FillEmptySpace(); // fill in top/bottom

            // add camera bounds
            //int vert = level.header.height / 2;
            //int width = level.header.width;
            //int index = vert * width + (width - 2);     // right camera tile
            //level.data.tag[index] = TileID.CameraBounds;
            //index = vert * width + 1;                   // left camera tile
            //level.data.tag[index] = TileID.CameraBounds;
            // vertical camera bounds are not set, they should just naturally work out

            return(Canvas.File);
        }