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); } }
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); }