public static DungeonTile[,] Load(string json) { var map = (JsonObject)SimpleJson.DeserializeObject(json); uint w = (uint)(long)map["width"], h = (uint)(long)map["height"]; var result = new DungeonTile[w, h]; var tiles = new Dictionary <ushort, DungeonTile>(); ushort id = 0; foreach (JsonObject tile in (JsonArray)map["dict"]) { var mapTile = new DungeonTile(); var tileType = (string)tile.GetValueOrDefault("ground", "Space"); mapTile.TileType = new TileType(tileType == "Space" ? 0xfe : (uint)tileType.GetHashCode(), tileType); mapTile.Region = tile.ContainsKey("regions") ? (string)((JsonObject)((JsonArray)tile["regions"])[0])["id"] : null; if (tile.ContainsKey("objs")) { var obj = (JsonObject)((JsonArray)tile["objs"])[0]; var tileObj = new DungeonObject { ObjectType = new ObjectType((uint)((string)obj["id"]).GetHashCode(), (string)obj["id"]) }; if (obj.ContainsKey("name")) { var attrs = (string)obj["name"]; tileObj.Attributes = attrs.Split(';') .Where(attr => !string.IsNullOrEmpty(attr)) .Select(attr => attr.Split(':')) .Select(attr => new KeyValuePair <string, string>(attr[0], attr[1])) .ToArray(); } else { tileObj.Attributes = Empty <KeyValuePair <string, string> > .Array; } mapTile.Object = tileObj; } else { mapTile.Object = null; } tiles[id++] = mapTile; } var data = RotMG.Common.IO.Zlib.Decompress(Convert.FromBase64String((string)map["data"])); var index = 0; for (var y = 0; y < h; y++) { for (var x = 0; x < w; x++) { result[x, y] = tiles[(ushort)((data[index++] << 8) | data[index++])]; } } return(result); }
private static bool CanAddRoomInTile(DungeonTile currentTile, Dungeon dungeon) { return( currentTile.X < dungeon.Width - 1 && currentTile.X > 0 && currentTile.Y < dungeon.Height - 1 && currentTile.Y > 0 && dungeon.Tiles[currentTile.X, currentTile.Y] ); }
private static bool TileHasMoreThanOnePossibleDirection(DungeonTile currentTile, Dungeon dungeon) { int possibleDirections = 0; for (int i = -1; i < 2; i++) { for (int j = -1; j < 2; j++) { if (currentTile.X + i > 0 && currentTile.X + i < dungeon.Width - 1 && currentTile.Y + j > 0 && currentTile.Y + j < dungeon.Height - 1 && dungeon.Tiles[currentTile.X + i, currentTile.Y + j]) { possibleDirections++; } } } return(possibleDirections > 1); }
public static Dungeon GenerateDungeon(DungeonGeneratorOptions options) { Dungeon dungeon = new Dungeon(); Random random = new Random(options.Seed); if (options.Seed == 0) { random = new Random(); } Stack <DungeonTile> openTiles = new Stack <DungeonTile>(); float maxCoveragePercent = options.MaxCoveragePercent; int floorCounter = 0; dungeon.Width = options.Width; dungeon.Height = options.Height; dungeon.Tiles = new bool[dungeon.Width, dungeon.Height]; // dungeon.Loot = GenerateLoot(dungeon); for (int i = 0; i < dungeon.Width; i++) { for (int j = 0; j < dungeon.Height; j++) { dungeon.Tiles[i, j] = true; // fill dungeon with walls. } } var startX = random.Next(dungeon.Width - 1); var starty = random.Next(dungeon.Height - 1); dungeon.Entrance = new DungeonTile { X = startX, Y = starty }; bool done = false; var currentTile = new DungeonTile { X = startX, Y = starty }; DungeonTile lastOpenTile = new DungeonTile { X = startX, Y = starty }; int doneConuter = 0; while (!done) { int maxLength = random.Next(3); var foundValidDirectionForCorridor = false; Direction d = (Direction)random.Next(4); DungeonTile possibleNextTile; for (int i = 0; i < 4; i++) { if (!foundValidDirectionForCorridor) { possibleNextTile = new DungeonTile { X = currentTile.X, Y = currentTile.Y }; d++; if ((int)d > 4) { d = 0; } if (d == Direction.North) { possibleNextTile.X++; } else if (d == Direction.South) { possibleNextTile.X--; } else if (d == Direction.East) { possibleNextTile.Y++; } else if (d == Direction.West) { possibleNextTile.Y--; } if (CanAddRoomInTile(possibleNextTile, dungeon)) { foundValidDirectionForCorridor = true; } } } if (foundValidDirectionForCorridor) { for (int i = 0; i < maxLength; i++) { possibleNextTile = new DungeonTile { X = currentTile.X, Y = currentTile.Y }; if (d == Direction.North) { possibleNextTile.X++; } else if (d == Direction.South) { possibleNextTile.X--; } else if (d == Direction.East) { possibleNextTile.Y++; } else if (d == Direction.West) { possibleNextTile.Y--; } if (CanAddRoomInTile(possibleNextTile, dungeon)) { foundValidDirectionForCorridor = true; currentTile = possibleNextTile; dungeon.Tiles[currentTile.X, currentTile.Y] = false; floorCounter++; if (TileHasMoreThanOnePossibleDirection(currentTile, dungeon)) { openTiles.Push(currentTile); } ; } } } else { doneConuter++; if (openTiles.Count > 0) { currentTile = openTiles.Pop(); if (openTiles.Count > 0 && random.Next(100) > 50) { currentTile = openTiles.Pop(); } } } if (doneConuter > 500) { done = true; } if (floorCounter > ((dungeon.Width * dungeon.Height) / 100) * maxCoveragePercent) { done = true; } if (done) { dungeon.Exit = new DungeonTile { X = currentTile.X, Y = currentTile.Y }; } } return(dungeon); }