コード例 #1
0
        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);
        }
コード例 #2
0
 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]
         );
 }
コード例 #3
0
        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);
        }
コード例 #4
0
        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);
        }