Exemple #1
0
        public static void GenerateTerrain(Map map, LightingEngine lightingEngine, GraphicsDevice gd)
        {
            Generating = true;
            PercentComplete = 0;

            Thread.Sleep(1000);

            bool compoundsOK = false;

            map.Jetties.Clear();

            List<Compound> compounds = new List<Compound>();

            TileLayer terrainLayer = map.GetLayer("Terrain") as TileLayer;
            TileLayer wallLayer = map.GetLayer("Wall") as TileLayer;
            TileLayer waterLayer = map.GetLayer("Water") as TileLayer;
            TileLayer roofLayer = map.GetLayer("Roof") as TileLayer;

            float[][] noise = null;

            while (!compoundsOK)
            {
                compounds.Clear();

                for (int i = lightingEngine.LightSources.Count - 1; i >= 0; i--)
                    if (lightingEngine.LightSources[i].SpotStencil != null) lightingEngine.LightSources.RemoveAt(i);

                for (int y = 0; y < map.Width; y++)
                {
                    for (int x = 0; x < map.Height; x++)
                    {
                        terrainLayer.Tiles[x, y] = null;
                        wallLayer.Tiles[x, y] = null;
                    }
                }

                PercentComplete = 5;

                // Inital terrain
                noise = PerlinNoise.GeneratePerlinNoise(map.Width, map.Height, 8);
                for (int y = 0; y < map.Width; y++)
                {
                    for (int x = 0; x < map.Height; x++)
                        if (noise[y][x] < 0.5f)
                        {
                            terrainLayer.Tiles[x, y] = map.Tiles[WATER];
                            waterLayer.Tiles[x, y] = map.Tiles[WATER];
                        }
                        else if (noise[y][x] < 0.6f)
                        {
                            terrainLayer.Tiles[x, y] = map.Tiles[SAND];
                            waterLayer.Tiles[x, y] = null;

                        }
                        else
                        {
                            terrainLayer.Tiles[x, y] = map.Tiles[GRASS];
                            waterLayer.Tiles[x, y] = null;

                        }
                }

                PercentComplete = 10;

                // Trees
                float[][] treeNoise = PerlinNoise.GeneratePerlinNoise(map.Width, map.Height, 4);

                for (int y = 0; y < map.Width; y++)
                {
                    for (int x = 0; x < map.Height; x++)
                    {
                        if (noise[y][x] > 0.62f)
                            if (treeNoise[y][x] > 0.5f)
                                wallLayer.Tiles[x, y] = map.Tiles[TREE];
                    }
                }

                PercentComplete = 20;

                // Compounds
                CreateCompounds(map, terrainLayer, wallLayer, roofLayer, compounds, noise, 0.65f, 20000f, 20, lightingEngine, gd);
                CreateCompounds(map, terrainLayer, wallLayer, roofLayer, compounds, noise, 0.75f, 12000f, 30, lightingEngine, gd);

                // Test to see if compounds are okay
                int numOKComps = 0;
                foreach (Compound c in compounds)
                {
                    if (c.Buildings.Count(b => b.Type != BuildingType.Carpark && b.Type != BuildingType.Helipad) > 0) numOKComps++;
                }

                if (numOKComps > 5) compoundsOK = true;
            }

            PercentComplete = 35;

            // Remove stray tiles
            for (int y = 0; y < map.Width; y++)
            {
                for (int x = 0; x < map.Height; x++)
                {
                    if (GetTileIndex(map, terrainLayer, x, y) == SAND)
                        if (CountSurroundingTiles(map, terrainLayer, x, y, WATER) >= 5)
                        {
                            terrainLayer.Tiles[x, y] = map.Tiles[WATER];
                            waterLayer.Tiles[x, y] = map.Tiles[WATER];
                        }

                    //if (GetTileIndex(map, terrainLayer, (map.Width-1) - x, (map.Height-1) - y) == SAND)
                    //    if (CountSurroundingTiles(map, terrainLayer, (map.Width - 1) - x, (map.Height - 1) - y, WATER) >= 5) terrainLayer.Tiles[(map.Width - 1) - x, (map.Height - 1) - y] = map.Tiles[WATER];

                    if (GetTileIndex(map, terrainLayer, x, y) == GRASS)
                        if (CountSurroundingTiles(map, terrainLayer, x, y, SAND) >= 5) terrainLayer.Tiles[x, y] = map.Tiles[SAND];

                    //if (GetTileIndex(map, terrainLayer, (map.Width - 1) - x, (map.Height - 1) - y) == GRASS)
                    //    if (CountSurroundingTiles(map, terrainLayer, (map.Width - 1) - x, (map.Height - 1) - y, SAND) >= 5) terrainLayer.Tiles[(map.Width - 1) - x, (map.Height - 1) - y] = map.Tiles[SAND];
                }
            }

            PercentComplete = 45;

            // Jetties!
            for (int y = 40; y < map.Width - 40; y+=2)
            {
                for (int x = 40; x < map.Height - 40; x+=2)
                {
                    if (GetTileIndex(map, terrainLayer, x, y) == SAND)
                    {
                        switch (Helper.Random.Next(4))
                        {
                            case 0:
                                if (GetTileIndex(map, terrainLayer, x, y - 10) == WATER && GetTileIndex(map, terrainLayer, x, y - 4) == WATER && GetTileIndex(map, terrainLayer, x, y - 2) == SAND)
                                    if (TryMakeJetty(map, terrainLayer, waterLayer, new Point(x, y), new Point(0, -1))) continue;
                                break;
                            case 1:

                                if (GetTileIndex(map, terrainLayer, x, y + 10) == WATER && GetTileIndex(map, terrainLayer, x, y + 4) == WATER && GetTileIndex(map, terrainLayer, x, y + 2) == SAND)
                                    if (TryMakeJetty(map, terrainLayer, waterLayer, new Point(x, y), new Point(0, 1))) continue;
                                break;

                            case 2:
                                if (GetTileIndex(map, terrainLayer, x - 10, y) == WATER && GetTileIndex(map, terrainLayer, x - 4, y) == WATER && GetTileIndex(map, terrainLayer, x - 2, y) == SAND)
                                    if (TryMakeJetty(map, terrainLayer, waterLayer, new Point(x, y), new Point(-1, 0))) continue;
                                break;

                            case 3:
                                if (GetTileIndex(map, terrainLayer, x + 10, y) == WATER && GetTileIndex(map, terrainLayer, x + 4, y) == WATER && GetTileIndex(map, terrainLayer, x + 2, y) == SAND)
                                    if (TryMakeJetty(map, terrainLayer, waterLayer, new Point(x, y), new Point(1, 0))) continue;
                                break;
                        }
                    }
                }
            }

            PercentComplete = 55;

            // Detail tiling!
            for (int y = 0; y < map.Width; y++)
            {
                for (int x = 0; x < map.Height; x++)
                {

                    // Sand/Water
                    if (GetTileIndex(map, terrainLayer, x, y) == SAND)
                    {
                        // Edges
                        if (GetTileIndex(map, terrainLayer, x - 1, y) == WATER)
                            if (GetTileIndex(map, terrainLayer, x, y - 1) != WATER)
                                if (GetTileIndex(map, terrainLayer, x, y + 1) != WATER) terrainLayer.Tiles[x, y] = map.Tiles[SAND_EDGE_LEFT];

                        if (GetTileIndex(map, terrainLayer, x + 1, y) == WATER)
                            if (GetTileIndex(map, terrainLayer, x, y - 1) != WATER)
                                if (GetTileIndex(map, terrainLayer, x, y + 1) != WATER) terrainLayer.Tiles[x, y] = map.Tiles[SAND_EDGE_RIGHT];

                        if (GetTileIndex(map, terrainLayer, x, y + 1) == WATER)
                            if (GetTileIndex(map, terrainLayer, x - 1, y) != WATER)
                                if (GetTileIndex(map, terrainLayer, x + 1, y) != WATER) terrainLayer.Tiles[x, y] = map.Tiles[SAND_EDGE_DOWN];

                        if (GetTileIndex(map, terrainLayer, x, y - 1) == WATER)
                            if (GetTileIndex(map, terrainLayer, x - 1, y) != WATER)
                                if (GetTileIndex(map, terrainLayer, x + 1, y) != WATER) terrainLayer.Tiles[x, y] = map.Tiles[SAND_EDGE_UP];

                        // Corners - water inside
                        if (GetTileIndex(map, terrainLayer, x - 1, y - 1) == WATER)
                            if (GetTileIndex(map, terrainLayer, x, y - 1) != WATER)
                                if (GetTileIndex(map, terrainLayer, x - 1, y) != WATER) terrainLayer.Tiles[x, y] = map.Tiles[SAND_CORNER_INSIDE_BR];

                        if (GetTileIndex(map, terrainLayer, x - 1, y + 1) == WATER)
                            if (GetTileIndex(map, terrainLayer, x, y + 1) != WATER)
                                if (GetTileIndex(map, terrainLayer, x - 1, y) != WATER) terrainLayer.Tiles[x, y] = map.Tiles[SAND_CORNER_INSIDE_TR];

                        if (GetTileIndex(map, terrainLayer, x + 1, y - 1) == WATER)
                            if (GetTileIndex(map, terrainLayer, x, y - 1) != WATER)
                                if (GetTileIndex(map, terrainLayer, x + 1, y) != WATER) terrainLayer.Tiles[x, y] = map.Tiles[SAND_CORNER_INSIDE_BL];

                        if (GetTileIndex(map, terrainLayer, x + 1, y + 1) == WATER)
                            if (GetTileIndex(map, terrainLayer, x, y + 1) != WATER)
                                if (GetTileIndex(map, terrainLayer, x + 1, y) != WATER) terrainLayer.Tiles[x, y] = map.Tiles[SAND_CORNER_INSIDE_TL];

                        // Corners - water outside
                        if (GetTileIndex(map, terrainLayer, x - 1, y - 1) == WATER)
                            if (GetTileIndex(map, terrainLayer, x, y - 1) == WATER)
                                if (GetTileIndex(map, terrainLayer, x - 1, y) == WATER) terrainLayer.Tiles[x, y] = map.Tiles[SAND_CORNER_OUTSIDE_TL];

                        if (GetTileIndex(map, terrainLayer, x - 1, y + 1) == WATER)
                            if (GetTileIndex(map, terrainLayer, x, y + 1) == WATER)
                                if (GetTileIndex(map, terrainLayer, x - 1, y) == WATER) terrainLayer.Tiles[x, y] = map.Tiles[SAND_CORNER_OUTSIDE_BL];

                        if (GetTileIndex(map, terrainLayer, x + 1, y - 1) == WATER)
                            if (GetTileIndex(map, terrainLayer, x, y - 1) == WATER)
                                if (GetTileIndex(map, terrainLayer, x + 1, y) == WATER) terrainLayer.Tiles[x, y] = map.Tiles[SAND_CORNER_OUTSIDE_TR];

                        if (GetTileIndex(map, terrainLayer, x + 1, y + 1) == WATER)
                            if (GetTileIndex(map, terrainLayer, x, y + 1) == WATER)
                                if (GetTileIndex(map, terrainLayer, x + 1, y) == WATER) terrainLayer.Tiles[x, y] = map.Tiles[SAND_CORNER_OUTSIDE_BR];

                    }

                    // Grass/Sand
                    if (GetTileIndex(map, terrainLayer, x, y) == GRASS || GetTileIndex(map, terrainLayer, x, y) == GRASS_ALT1 || GetTileIndex(map, terrainLayer, x, y) == GRASS_ALT2)
                    {
                        // Edges
                        if (GetTileIndex(map, terrainLayer, x - 1, y) == SAND)
                            if (GetTileIndex(map, terrainLayer, x, y - 1) != SAND)
                                if (GetTileIndex(map, terrainLayer, x, y + 1) != SAND) terrainLayer.Tiles[x, y] = map.Tiles[GRASS_EDGE_LEFT];

                        if (GetTileIndex(map, terrainLayer, x + 1, y) == SAND)
                            if (GetTileIndex(map, terrainLayer, x, y - 1) != SAND)
                                if (GetTileIndex(map, terrainLayer, x, y + 1) != SAND) terrainLayer.Tiles[x, y] = map.Tiles[GRASS_EDGE_RIGHT];

                        if (GetTileIndex(map, terrainLayer, x, y + 1) == SAND)
                            if (GetTileIndex(map, terrainLayer, x - 1, y) != SAND)
                                if (GetTileIndex(map, terrainLayer, x + 1, y) != SAND) terrainLayer.Tiles[x, y] = map.Tiles[GRASS_EDGE_DOWN];

                        if (GetTileIndex(map, terrainLayer, x, y - 1) == SAND)
                            if (GetTileIndex(map, terrainLayer, x - 1, y) != SAND)
                                if (GetTileIndex(map, terrainLayer, x + 1, y) != SAND) terrainLayer.Tiles[x, y] = map.Tiles[GRASS_EDGE_UP];

                        // Corners - water inside
                        if (GetTileIndex(map, terrainLayer, x - 1, y - 1) == SAND)
                            if (GetTileIndex(map, terrainLayer, x, y - 1) != SAND)
                                if (GetTileIndex(map, terrainLayer, x - 1, y) != SAND) terrainLayer.Tiles[x, y] = map.Tiles[GRASS_CORNER_INSIDE_BR];

                        if (GetTileIndex(map, terrainLayer, x - 1, y + 1) == SAND)
                            if (GetTileIndex(map, terrainLayer, x, y + 1) != SAND)
                                if (GetTileIndex(map, terrainLayer, x - 1, y) != SAND) terrainLayer.Tiles[x, y] = map.Tiles[GRASS_CORNER_INSIDE_TR];

                        if (GetTileIndex(map, terrainLayer, x + 1, y - 1) == SAND)
                            if (GetTileIndex(map, terrainLayer, x, y - 1) != SAND)
                                if (GetTileIndex(map, terrainLayer, x + 1, y) != SAND) terrainLayer.Tiles[x, y] = map.Tiles[GRASS_CORNER_INSIDE_BL];

                        if (GetTileIndex(map, terrainLayer, x + 1, y + 1) == SAND)
                            if (GetTileIndex(map, terrainLayer, x, y + 1) != SAND)
                                if (GetTileIndex(map, terrainLayer, x + 1, y) != SAND) terrainLayer.Tiles[x, y] = map.Tiles[GRASS_CORNER_INSIDE_TL];

                        // Corners - water outside
                        if (GetTileIndex(map, terrainLayer, x - 1, y - 1) == SAND)
                            if (GetTileIndex(map, terrainLayer, x, y - 1) == SAND)
                                if (GetTileIndex(map, terrainLayer, x - 1, y) == SAND) terrainLayer.Tiles[x, y] = map.Tiles[GRASS_CORNER_OUTSIDE_TL];

                        if (GetTileIndex(map, terrainLayer, x - 1, y + 1) == SAND)
                            if (GetTileIndex(map, terrainLayer, x, y + 1) == SAND)
                                if (GetTileIndex(map, terrainLayer, x - 1, y) == SAND) terrainLayer.Tiles[x, y] = map.Tiles[GRASS_CORNER_OUTSIDE_BL];

                        if (GetTileIndex(map, terrainLayer, x + 1, y - 1) == SAND)
                            if (GetTileIndex(map, terrainLayer, x, y - 1) == SAND)
                                if (GetTileIndex(map, terrainLayer, x + 1, y) == SAND) terrainLayer.Tiles[x, y] = map.Tiles[GRASS_CORNER_OUTSIDE_TR];

                        if (GetTileIndex(map, terrainLayer, x + 1, y + 1) == SAND)
                            if (GetTileIndex(map, terrainLayer, x, y + 1) == SAND)
                                if (GetTileIndex(map, terrainLayer, x + 1, y) == SAND) terrainLayer.Tiles[x, y] = map.Tiles[GRASS_CORNER_OUTSIDE_BR];

                    }
                }
            }

            PercentComplete = 75;

            // Alt tiles
            for (int y = 0; y < map.Width; y++)
            {
                for (int x = 0; x < map.Height; x++)
                {
                    if (GetTileIndex(map, terrainLayer, x, y) == GRASS)
                    {
                        int r = rand.Next(50);
                        if (r == 9) terrainLayer.Tiles[x, y] = map.Tiles[GRASS_ALT1];
                        else if (r == 8) terrainLayer.Tiles[x, y] = map.Tiles[GRASS_ALT2];
                    }
                    if (GetTileIndex(map, terrainLayer, x, y) == SAND)
                    {
                        int r = rand.Next(50);
                        if (r == 9) terrainLayer.Tiles[x, y] = map.Tiles[SAND_ALT];
                    }

                    // Tree alts
                    if (GetTileIndex(map, wallLayer, x, y) == TREE)
                    {
                        //if (rand.Next(10) == 0)
                        //{
                            // Big tree
                        if(!TryDrawBigTree(map, wallLayer, x, y)) wallLayer.Tiles[x, y] = map.Tiles[TREES[rand.Next(TREES.Length)]];

                    }
                }
            }

            PercentComplete = 90;

            Rectangle spawnRect = new Rectangle((map.Width / 2) - 5, (map.Height / 2) - 5, 10, 10);
            bool foundspawn = false;
            while (!foundspawn)
            {
                map.HeroSpawn = TryFindSpawn(spawnRect.Left, spawnRect.Top, map, terrainLayer, out foundspawn);
                if (!foundspawn) map.HeroSpawn = TryFindSpawn(spawnRect.Right, spawnRect.Top, map, terrainLayer, out foundspawn);
                if (!foundspawn) map.HeroSpawn = TryFindSpawn(spawnRect.Left, spawnRect.Bottom, map, terrainLayer, out foundspawn);
                if (!foundspawn) map.HeroSpawn = TryFindSpawn(spawnRect.Right, spawnRect.Bottom, map, terrainLayer, out foundspawn);

                spawnRect.Inflate(5, 5);
            }

            map.GetAStarData();
            map.Compounds = compounds;

            PercentComplete = 100;
            //Generating = false;
        }