Пример #1
0
        private static void ProcessTrees( ForesterArgs args, IList<Tree> treelist )
        {
            TreeShape[] shapeChoices;
            switch ( args.Shape ) {
                case TreeShape.Stickly:
                    shapeChoices = new[]{ TreeShape.Normal,
                                          TreeShape.Bamboo,
                                          TreeShape.Palm };
                    break;

                case TreeShape.Procedural:
                    shapeChoices = new[]{ TreeShape.Round,
                                          TreeShape.Cone };
                    break;

                default:
                    shapeChoices = new[] { args.Shape };
                    break;
            }

            for ( int i = 0; i < treelist.Count; i++ ) {
                TreeShape newshape = shapeChoices[args.Rand.Next( 0, shapeChoices.Length )];
                Tree newTree;
                switch ( newshape ) {
                    case TreeShape.Normal:
                        newTree = new NormalTree();
                        break;

                    case TreeShape.Bamboo:
                        newTree = new BambooTree();
                        break;

                    case TreeShape.Palm:
                        newTree = new PalmTree();
                        break;

                    case TreeShape.Round:
                        newTree = new RoundTree();
                        break;

                    case TreeShape.Cone:
                        newTree = new ConeTree();
                        break;

                    case TreeShape.Rainforest:
                        newTree = new RainforestTree();
                        break;

                    case TreeShape.Mangrove:
                        newTree = new MangroveTree();
                        break;

                    default:
                        throw new ArgumentException( "Unknown tree shape type" );
                }
                newTree.Copy( treelist[i] );

                if ( args.MapHeightLimit ) {
                    int height = newTree.Height;
                    int ybase = newTree.Pos[1];
                    int mapHeight = args.Map.Height;
                    int foliageHeight;
                    if ( args.Shape == TreeShape.Rainforest ) {
                        foliageHeight = 2;
                    } else {
                        foliageHeight = 4;
                    }
                    if ( ybase + height + foliageHeight > mapHeight ) {
                        newTree.Height = mapHeight - ybase - foliageHeight;
                    }
                }

                if ( newTree.Height < 1 )
                    newTree.Height = 1;
                newTree.Prepare();
                treelist[i] = newTree;
            }
        }
Пример #2
0
        private static void PlantRainForestTrees( ForesterArgs args, ICollection<Tree> treelist )
        {
            int treeHeight = args.Height;

            int existingTreeNum = treelist.Count;
            int remainingTrees = args.TreeCount - existingTreeNum;

            const int shortTreeFraction = 6;
            int attempts = 0;
            for ( int i = 0; i < remainingTrees && attempts < MaxTries; attempts++ ) {
                float randomfac =
                    ( float )( ( Math.Sqrt( args.Rand.NextDouble() ) * 1.618 - .618 ) * args.HeightVariation + .5 );

                int height;
                if ( i % shortTreeFraction == 0 ) {
                    height = ( int )( treeHeight + randomfac );
                } else {
                    height = ( int )( treeHeight - randomfac );
                }
                Vector3I xyz = FindRandomTreeLocation( args, height );
                if ( xyz.Y < 0 )
                    continue;

                xyz.Y++;

                bool displaced = false;
                // ReSharper disable LoopCanBeConvertedToQuery
                foreach ( Tree otherTree in treelist ) {
                    Vector3I otherLoc = otherTree.Pos;
                    float otherheight = otherTree.Height;
                    int tallx = otherLoc[0];
                    int tallz = otherLoc[2];
                    float dist = ( float )Math.Sqrt( Sqr( tallx - xyz.X + .5 ) + Sqr( tallz - xyz.Z + .5 ) );
                    float threshold = ( otherheight + height ) * .193f;
                    if ( dist < threshold ) {
                        displaced = true;
                        break;
                    }
                }
                // ReSharper restore LoopCanBeConvertedToQuery
                if ( displaced )
                    continue;
                treelist.Add( new RainforestTree {
                    Args = args,
                    Pos = xyz,
                    Height = height
                } );
                i++;
            }
        }
Пример #3
0
        private static void PlantTrees( ForesterArgs args, ICollection<Tree> treelist )
        {
            int treeheight = args.Height;

            int attempts = 0;
            while ( treelist.Count < args.TreeCount && attempts < MaxTries ) {
                attempts++;
                int height = args.Rand.Next( treeheight - args.HeightVariation,
                                             treeheight + args.HeightVariation + 1 );

                Vector3I treeLoc = FindRandomTreeLocation( args, height );
                if ( treeLoc.Y < 0 )
                    continue;
                else
                    treeLoc.Y++;
                treelist.Add( new Tree {
                    Args = args,
                    Height = height,
                    Pos = treeLoc
                } );
            }
        }
Пример #4
0
        private static void PlantMangroves( ForesterArgs args, ICollection<Tree> treelist )
        {
            int treeheight = args.Height;

            int attempts = 0;
            while ( treelist.Count < args.TreeCount && attempts < MaxTries ) {
                attempts++;
                int height = args.Rand.Next( treeheight - args.HeightVariation,
                                             treeheight + args.HeightVariation + 1 );
                int padding = ( int )( height / 3f + 1 );
                int mindim = Math.Min( args.Map.Width, args.Map.Length );
                if ( padding > mindim / 2.2 ) {
                    padding = ( int )( mindim / 2.2 );
                }
                int x = args.Rand.Next( padding, args.Map.Width - padding - 1 );
                int z = args.Rand.Next( padding, args.Map.Length - padding - 1 );
                int top = args.Map.Height - 1;

                int y = top - DistanceToBlock( args.Map, new Vector3F( x, z, top ), Vector3F.Down, Block.Air, true );
                int dist = DistanceToBlock( args.Map, new Vector3F( x, z, y ), Vector3F.Down, Block.Water, true );

                if ( dist > height * .618 || dist == 0 ) {
                    continue;
                }

                y += ( int )Math.Sqrt( height - dist ) + 2;
                treelist.Add( new Tree {
                    Args = args,
                    Height = height,
                    Pos = new Vector3I( x, y, z )
                } );
            }
        }
Пример #5
0
        private static void FindTrees( ForesterArgs args, ICollection<Tree> treelist )
        {
            int treeheight = args.Height;

            for ( int x = 0; x < args.Map.Width; x++ ) {
                for ( int z = 0; z < args.Map.Length; z++ ) {
                    int y = args.Map.Height - 1;
                    while ( true ) {
                        int foliagetop = args.Map.SearchColumn( x, z, args.FoliageBlock, y );
                        if ( foliagetop < 0 )
                            break;
                        y = foliagetop;
                        Vector3I trunktop = new Vector3I( x, y - 1, z );
                        int height = DistanceToBlock( args.Map, new Vector3F( trunktop ), Vector3F.Down, args.TrunkBlock, true );
                        if ( height == 0 ) {
                            y--;
                            continue;
                        }
                        y -= height;
                        if ( args.Height > 0 ) {
                            height = args.Rand.Next( treeheight - args.HeightVariation,
                                                     treeheight + args.HeightVariation + 1 );
                        }
                        treelist.Add( new Tree {
                            Args = args,
                            Pos = new Vector3I( x, y, z ),
                            Height = height
                        } );
                        y--;
                    }
                }
            }
        }
Пример #6
0
 private static Vector3I FindRandomTreeLocation( ForesterArgs args, int height )
 {
     int padding = ( int )( height / 3f + 1 );
     int mindim = Math.Min( args.Map.Width, args.Map.Length );
     if ( padding > mindim / 2.2 ) {
         padding = ( int )( mindim / 2.2 );
     }
     int x = args.Rand.Next( padding, args.Map.Width - padding - 1 );
     int z = args.Rand.Next( padding, args.Map.Length - padding - 1 );
     int y = args.Map.SearchColumn( x, z, args.PlantOn );
     return new Vector3I( x, y, z );
 }
Пример #7
0
 public void Copy( Tree other )
 {
     Args = other.Args;
     Pos = other.Pos;
     Height = other.Height;
 }
Пример #8
0
        public Map GenerateMap()
        {
            Map map = new Map(null, args.MapWidth, args.MapLength, args.MapHeight, true);


            // Match water coverage
            float desiredWaterLevel = .5f;

            if (args.MatchWaterCoverage)
            {
                ReportProgress(2, "Heightmap Processing: Matching water coverage");
                desiredWaterLevel = Noise.FindThreshold(heightmap, args.WaterCoverage);
            }


            // Calculate above/below water multipliers
            float aboveWaterMultiplier = 0;

            if (desiredWaterLevel != 1)
            {
                aboveWaterMultiplier = (args.MaxHeight / (1 - desiredWaterLevel));
            }


            // Apply power functions to above/below water parts of the heightmap
            if (args.BelowFuncExponent != 1 || args.AboveFuncExponent != 1)
            {
                ReportProgress(5, "Heightmap Processing: Adjusting slope");
                for (int x = heightmap.GetLength(0) - 1; x >= 0; x--)
                {
                    for (int y = heightmap.GetLength(1) - 1; y >= 0; y--)
                    {
                        if (heightmap[x, y] < desiredWaterLevel)
                        {
                            float normalizedDepth = 1 - heightmap[x, y] / desiredWaterLevel;
                            heightmap[x, y] = desiredWaterLevel - (float)Math.Pow(normalizedDepth, args.BelowFuncExponent) * desiredWaterLevel;
                        }
                        else
                        {
                            float normalizedHeight = (heightmap[x, y] - desiredWaterLevel) / (1 - desiredWaterLevel);
                            heightmap[x, y] = desiredWaterLevel + (float)Math.Pow(normalizedHeight, args.AboveFuncExponent) * (1 - desiredWaterLevel);
                        }
                    }
                }
            }

            // Calculate the slope
            if (args.CliffSmoothing)
            {
                ReportProgress(2, "Heightmap Processing: Smoothing");
                slopemap = Noise.CalculateSlope(Noise.GaussianBlur5X5(heightmap));
            }
            else
            {
                slopemap = Noise.CalculateSlope(heightmap);
            }

            float[,] altmap = null;
            if (args.MaxHeightVariation != 0 || args.MaxDepthVariation != 0)
            {
                ReportProgress(5, "Heightmap Processing: Randomizing");
                altmap = new float[map.Width, map.Length];
                int blendmapDetailSize = (int)Math.Log(Math.Max(args.MapWidth, args.MapLength), 2) - 2;
                new Noise(rand.Next(), NoiseInterpolationMode.Cosine).PerlinNoise(altmap, 3, blendmapDetailSize, 0.5f, 0, 0);
                Noise.Normalize(altmap, -1, 1);
            }

            int snowStartThreshold = args.SnowAltitude - args.SnowTransition;
            int snowThreshold      = args.SnowAltitude;

            ReportProgress(10, "Filling");
            for (int x = heightmap.GetLength(0) - 1; x >= 0; x--)
            {
                for (int y = heightmap.GetLength(1) - 1; y >= 0; y--)
                {
                    int   level;
                    float slope;
                    if (heightmap[x, y] < desiredWaterLevel)
                    {
                        float depth = args.MaxDepth;
                        if (altmap != null)
                        {
                            depth += altmap[x, y] * args.MaxDepthVariation;
                        }
                        slope = slopemap[x, y] * depth;
                        level = args.WaterLevel - (int)Math.Round(Math.Pow(1 - heightmap[x, y] / desiredWaterLevel, args.BelowFuncExponent) * depth);

                        if (args.AddWater)
                        {
                            if (args.WaterLevel - level > 3)
                            {
                                map.SetBlock(x, y, args.WaterLevel, bDeepWaterSurface);
                            }
                            else
                            {
                                map.SetBlock(x, y, args.WaterLevel, bWaterSurface);
                            }
                            for (int i = args.WaterLevel; i > level; i--)
                            {
                                map.SetBlock(x, y, i, bWater);
                            }
                            for (int i = level; i >= 0; i--)
                            {
                                if (level - i < SeaFloorThickness)
                                {
                                    map.SetBlock(x, y, i, bSeaFloor);
                                }
                                else
                                {
                                    map.SetBlock(x, y, i, bBedrock);
                                }
                            }
                        }
                        else
                        {
                            if (blendmap != null && blendmap[x, y] > .25 && blendmap[x, y] < .75)
                            {
                                map.SetBlock(x, y, level, bCliff);
                            }
                            else
                            {
                                if (slope < args.CliffThreshold)
                                {
                                    map.SetBlock(x, y, level, bGroundSurface);
                                }
                                else
                                {
                                    map.SetBlock(x, y, level, bCliff);
                                }
                            }

                            for (int i = level - 1; i >= 0; i--)
                            {
                                if (level - i < groundThickness)
                                {
                                    if (blendmap != null && blendmap[x, y] > CliffsideBlockThreshold && blendmap[x, y] < (1 - CliffsideBlockThreshold))
                                    {
                                        map.SetBlock(x, y, i, bCliff);
                                    }
                                    else
                                    {
                                        if (slope < args.CliffThreshold)
                                        {
                                            map.SetBlock(x, y, i, bGround);
                                        }
                                        else
                                        {
                                            map.SetBlock(x, y, i, bCliff);
                                        }
                                    }
                                }
                                else
                                {
                                    map.SetBlock(x, y, i, bBedrock);
                                }
                            }
                        }
                    }
                    else
                    {
                        float height;
                        if (altmap != null)
                        {
                            height = args.MaxHeight + altmap[x, y] * args.MaxHeightVariation;
                        }
                        else
                        {
                            height = args.MaxHeight;
                        }
                        slope = slopemap[x, y] * height;
                        if (height != 0)
                        {
                            level = args.WaterLevel + (int)Math.Round(Math.Pow(heightmap[x, y] - desiredWaterLevel, args.AboveFuncExponent) * aboveWaterMultiplier / args.MaxHeight * height);
                        }
                        else
                        {
                            level = args.WaterLevel;
                        }

                        bool snow = args.AddSnow &&
                                    (level > snowThreshold ||
                                     (level > snowStartThreshold && rand.NextDouble() < (level - snowStartThreshold) / (double)(snowThreshold - snowStartThreshold)));

                        if (blendmap != null && blendmap[x, y] > .25 && blendmap[x, y] < .75)
                        {
                            map.SetBlock(x, y, level, bCliff);
                        }
                        else
                        {
                            if (slope < args.CliffThreshold)
                            {
                                map.SetBlock(x, y, level, (snow ? Block.White : bGroundSurface));
                            }
                            else
                            {
                                map.SetBlock(x, y, level, bCliff);
                            }
                        }

                        for (int i = level - 1; i >= 0; i--)
                        {
                            if (level - i < groundThickness)
                            {
                                if (blendmap != null && blendmap[x, y] > CliffsideBlockThreshold && blendmap[x, y] < (1 - CliffsideBlockThreshold))
                                {
                                    map.SetBlock(x, y, i, bCliff);
                                }
                                else
                                {
                                    if (slope < args.CliffThreshold)
                                    {
                                        if (snow)
                                        {
                                            map.SetBlock(x, y, i, Block.White);
                                        }
                                        else
                                        {
                                            map.SetBlock(x, y, i, bGround);
                                        }
                                    }
                                    else
                                    {
                                        map.SetBlock(x, y, i, bCliff);
                                    }
                                }
                            }
                            else
                            {
                                map.SetBlock(x, y, i, bBedrock);
                            }
                        }
                    }
                }
            }

            if (args.AddCaves || args.AddOre)
            {
                AddCaves(map);
            }

            if (args.AddBeaches)
            {
                ReportProgress(5, "Processing: Adding beaches");
                AddBeaches(map);
            }

            if (args.AddTrees)
            {
                ReportProgress(5, "Processing: Planting trees");
                if (args.AddGiantTrees)
                {
                    Map outMap = new Map(null, map.Width, map.Length, map.Height, false)
                    {
                        Blocks = (byte[])map.Blocks.Clone()
                    };
                    var foresterArgs = new ForesterArgs
                    {
                        Map       = map,
                        Rand      = rand,
                        TreeCount = (int)(map.Width * map.Length * 4 / (1024f * (args.TreeSpacingMax + args.TreeSpacingMin) / 2)),
                        Operation = Forester.ForesterOperation.Add,
                        PlantOn   = bGroundSurface
                    };
                    foresterArgs.BlockPlacing += (sender, e) => outMap.SetBlock(e.Coordinate, e.Block);
                    Forester.Generate(foresterArgs);
                    map = outMap;
                }
                GenerateTrees(map);
            }

            ReportProgress(0, "Generation complete");

            map.Metadata["_Origin", "GeneratorName"]    = "fCraft";
            map.Metadata["_Origin", "GeneratorVersion"] = Updater.LatestStable.ToString();
            map.Metadata["_Origin", "GeneratorParams"]  = args.Serialize().ToString(SaveOptions.DisableFormatting);
            return(map);
        }