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 }); } }
public static void Generate([NotNull] ForesterArgs args) { if (args == null) { throw new ArgumentNullException("args"); } args.Validate(); List <Tree> treeList = new List <Tree>(); if (args.Operation == ForesterOperation.Conserve) { FindTrees(args, treeList); } if (args.TreeCount > 0 && treeList.Count > args.TreeCount) { treeList = treeList.Take(args.TreeCount).ToList(); } if (args.Operation == ForesterOperation.Replant || args.Operation == ForesterOperation.Add) { switch (args.Shape) { case TreeShape.Rainforest: PlantRainForestTrees(args, treeList); break; case TreeShape.Mangrove: PlantMangroves(args, treeList); break; default: PlantTrees(args, treeList); break; } } if (args.Operation != ForesterOperation.ClearCut) { ProcessTrees(args, treeList); if (args.Foliage) { foreach (Tree tree in treeList) { tree.MakeFoliage(); } } if (args.Wood) { foreach (Tree tree in treeList) { tree.MakeTrunk(); } } } }
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)); }
public static void Plant([NotNull] ForesterArgs args, Vector3I treeCoordinate) { List <Tree> treeList = new List <Tree> { new Tree { Args = args, Height = args.Height, Pos = treeCoordinate } }; switch (args.Shape) { case TreeShape.Rainforest: PlantRainForestTrees(args, treeList); break; case TreeShape.Mangrove: PlantMangroves(args, treeList); break; default: PlantTrees(args, treeList); break; } ProcessTrees(args, treeList); if (args.Foliage) { foreach (Tree tree in treeList) { tree.MakeFoliage(); } } if (args.Wood) { foreach (Tree tree in treeList) { tree.MakeTrunk(); } } }
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--; } } } }
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) }); } }
public void Copy(Tree other) { Args = other.Args; Pos = other.Pos; Height = other.Height; }
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; } }
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++; } }