public void GenerateWater(VoxelChunk chunk, float maxHeight) { int waterHeight = Math.Min((int)(VoxelConstants.ChunkSizeY * NormalizeHeight(SeaLevel + 1.0f / VoxelConstants.ChunkSizeY, maxHeight)), VoxelConstants.ChunkSizeY - 1); var iceID = VoxelLibrary.GetVoxelType("Ice"); for (var x = 0; x < VoxelConstants.ChunkSizeX; ++x) { for (var z = 0; z < VoxelConstants.ChunkSizeZ; ++z) { var biome = Overworld.GetBiomeAt(new Vector3(x, 0, z) + chunk.Origin, chunk.Manager.World.WorldScale, chunk.Manager.World.WorldOrigin); var topVoxel = VoxelHelpers.FindFirstVoxelBelow(new VoxelHandle( chunk, new LocalVoxelCoordinate(x, VoxelConstants.ChunkSizeY - 1, z))); for (var y = 0; y <= waterHeight; ++y) { var vox = new VoxelHandle(chunk, new LocalVoxelCoordinate(x, y, z)); if (vox.IsEmpty && y > topVoxel.Coordinate.Y) { if (biome.WaterSurfaceIce && y == waterHeight) { vox.RawSetType(iceID); } else { vox.QuickSetLiquid(biome.WaterIsLava ? LiquidType.Lava : LiquidType.Water, WaterManager.maxWaterLevel); } } } } } }
override public void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera) { base.Update(gameTime, chunks, camera); if (CachedBiome == null) { var biome = Overworld.GetBiomeAt(LocalPosition, chunks.World.WorldScale, chunks.World.WorldOrigin); CachedBiome = biome.Name; } var factor = 1.0f; if (GoodBiomes.Contains(CachedBiome)) { factor = 1.5f; } if (BadBiomes.Contains(CachedBiome)) { factor = 0.5f; } GrowthTime += gameTime.ElapsedGameTime.TotalMinutes * factor; var scale = (float)(MinSize + (MaxSize - MinSize) * (GrowthTime / GrowthHours)); ReScale(scale); if (GrowthTime >= GrowthHours) { CreateAdult(); } }
public void GenerateWater(VoxelChunk chunk) { int waterHeight = (int)(SeaLevel * VoxelConstants.ChunkSizeY) + 1; var iceID = VoxelLibrary.GetVoxelType("Ice"); for (var x = 0; x < VoxelConstants.ChunkSizeX; ++x) { for (var z = 0; z < VoxelConstants.ChunkSizeZ; ++z) { var biome = Overworld.GetBiomeAt(new Vector3(x, 0, z) + chunk.Origin, chunk.Manager.World.WorldScale, chunk.Manager.World.WorldOrigin); var topVoxel = VoxelHelpers.FindFirstVoxelBelow(new VoxelHandle( chunk, new LocalVoxelCoordinate(x, VoxelConstants.ChunkSizeY - 1, z))); for (var y = 0; y <= waterHeight; ++y) { var vox = new VoxelHandle(chunk, new LocalVoxelCoordinate(x, y, z)); if (vox.IsEmpty && y > topVoxel.Coordinate.Y) { if (biome.WaterSurfaceIce && y == waterHeight) { vox.RawSetType(iceID); } else { vox.QuickSetLiquid(LiquidType.Water, WaterManager.maxWaterLevel); } } } Vector2 vec = Overworld.WorldToOverworld(new Vector2(x + chunk.Origin.X, z + chunk.Origin.Z), chunk.Manager.World.WorldScale, chunk.Manager.World.WorldOrigin); if (topVoxel.Coordinate.Y < VoxelConstants.ChunkSizeY - 1 && Overworld.GetWater(Overworld.Map, vec) == Overworld.WaterType.Volcano) { var localCoord = topVoxel.Coordinate.GetLocalVoxelCoordinate(); topVoxel = new VoxelHandle(topVoxel.Chunk, new LocalVoxelCoordinate( localCoord.X, localCoord.Y + 1, localCoord.Z)); if (topVoxel.IsEmpty) { topVoxel.QuickSetLiquid(LiquidType.Lava, WaterManager.maxWaterLevel); } } } } }
public void GenerateSurfaceLife(Dictionary <string, Dictionary <string, int> > creatureCounts, VoxelChunk Chunk, float maxHeight) { //int waterHeight = (int)(VoxelConstants.ChunkSizeY * NormalizeHeight(SeaLevel + 1.0f / VoxelConstants.ChunkSizeY, maxHeight)); for (var x = 0; x < VoxelConstants.ChunkSizeX; ++x) { for (var z = 0; z < VoxelConstants.ChunkSizeZ; ++z) { var biomeData = Overworld.GetBiomeAt(new Vector3(x + Chunk.Origin.X, 0, z + Chunk.Origin.Z), Chunk.Manager.World.WorldScale, Chunk.Manager.World.WorldOrigin); var topVoxel = VoxelHelpers.FindFirstVoxelBelow(new VoxelHandle( Chunk, new LocalVoxelCoordinate(x, VoxelConstants.ChunkSizeY - 1, z))); if (!topVoxel.IsValid || topVoxel.Coordinate.Y == 0 || topVoxel.Coordinate.Y >= 60) // Lift to some kind of generator settings? { continue; } var above = VoxelHelpers.GetVoxelAbove(topVoxel); if (above.IsValid && above.LiquidLevel != 0) { continue; } foreach (var animal in biomeData.Fauna) { if (MathFunctions.RandEvent(animal.SpawnProbability)) { if (!creatureCounts.ContainsKey(biomeData.Name)) { creatureCounts[biomeData.Name] = new Dictionary <string, int>(); } var dict = creatureCounts[biomeData.Name]; if (!dict.ContainsKey(animal.Name)) { dict[animal.Name] = 0; } if (dict[animal.Name] < animal.MaxPopulation) { EntityFactory.CreateEntity <Body>(animal.Name, topVoxel.WorldPosition + Vector3.Up * 1.5f); } break; } } if (topVoxel.Type.Name != biomeData.SoilLayer.VoxelType) { continue; } foreach (VegetationData veg in biomeData.Vegetation) { if (topVoxel.GrassType == 0) { continue; } if (MathFunctions.RandEvent(veg.SpawnProbability) && NoiseGenerator.Noise(topVoxel.Coordinate.X / veg.ClumpSize, veg.NoiseOffset, topVoxel.Coordinate.Z / veg.ClumpSize) >= veg.ClumpThreshold) { topVoxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.SoilLayer.VoxelType)); var treeSize = MathFunctions.Rand() * veg.SizeVariance + veg.MeanSize; var tree = EntityFactory.CreateEntity <Plant>(veg.Name, topVoxel.WorldPosition + new Vector3(0.5f, 1.0f, 0.5f), Blackboard.Create("Scale", treeSize)); break; } } } } }
private static void UpdateChunk(VoxelChunk chunk) { var addGrassToThese = new List <Tuple <VoxelHandle, byte> >(); for (var y = 0; y < VoxelConstants.ChunkSizeY; ++y) { // Skip empty slices. if (chunk.Data.VoxelsPresentInSlice[y] == 0) { continue; } for (var x = 0; x < VoxelConstants.ChunkSizeX; ++x) { for (var z = 0; z < VoxelConstants.ChunkSizeZ; ++z) { var voxel = new VoxelHandle(chunk, new LocalVoxelCoordinate(x, y, z)); // Allow grass to decay if (voxel.GrassType != 0) { var decal = GrassLibrary.GetGrassType(voxel.GrassType); if (decal.NeedsSunlight && !voxel.Sunlight) { voxel.GrassType = 0; } else if (decal.Decay) { voxel.GrassDecay -= 1; if (voxel.GrassDecay == 0) { var newDecal = GrassLibrary.GetGrassType(decal.BecomeWhenDecays); if (newDecal != null) { voxel.GrassType = newDecal.ID; } else { voxel.GrassType = 0; } } } } //#if false else if (voxel.Type.GrassSpreadsHere) { // Spread grass onto this tile - but only from the same biome. // Don't spread if there's an entity here. var entityPresent = chunk.Manager.World.EnumerateIntersectingObjects( new BoundingBox(voxel.WorldPosition + new Vector3(0.1f, 1.1f, 0.1f), voxel.WorldPosition + new Vector3(0.9f, 1.9f, 0.9f)), CollisionType.Static).Any(); if (entityPresent) { continue; } var biome = Overworld.GetBiomeAt(voxel.Coordinate.ToVector3(), chunk.Manager.World.WorldScale, chunk.Manager.World.WorldOrigin); var grassyNeighbors = VoxelHelpers.EnumerateManhattanNeighbors2D(voxel.Coordinate) .Select(c => new VoxelHandle(voxel.Chunk.Manager.ChunkData, c)) .Where(v => v.IsValid && v.GrassType != 0) .Where(v => biome == Overworld.GetBiomeAt(v.Coordinate.ToVector3(), chunk.Manager.World.WorldScale, chunk.Manager.World.WorldOrigin)) .ToList(); if (grassyNeighbors.Count > 0) { if (MathFunctions.RandEvent(0.1f)) { addGrassToThese.Add(Tuple.Create(voxel, grassyNeighbors[MathFunctions.RandInt(0, grassyNeighbors.Count)].GrassType)); } } } //#endif } } } foreach (var v in addGrassToThese) { var l = v.Item1; var grassType = GrassLibrary.GetGrassType(v.Item2); if (grassType.NeedsSunlight && !l.Sunlight) { continue; } l.GrassType = v.Item2; } }
public void RebuildMoteLayer(int Y) { var moteList = new List <NewInstanceData>(); // Enumerate voxels. for (var x = 0; x < VoxelConstants.ChunkSizeX; ++x) { for (var z = 0; z < VoxelConstants.ChunkSizeZ; ++z) { // Don't generate motes if above is not empty if (Y < VoxelConstants.ChunkSizeY - 1) { var voxelAbove = new VoxelHandle(this, new LocalVoxelCoordinate(x, Y + 1, z)); if (!voxelAbove.IsEmpty || voxelAbove.LiquidLevel != 0) { continue; } } var v = new VoxelHandle(this, new LocalVoxelCoordinate(x, Y, z)); // Don't generate in empty voxels. if (v.IsEmpty) { continue; } if (!v.IsExplored) { continue; } // Find biome type. var biomeData = Overworld.GetBiomeAt(v.WorldPosition, Manager.World.WorldScale, Manager.World.WorldOrigin); // Don't generate if not on grass type. if (v.GrassType == 0 || GrassLibrary.GetGrassType(v.GrassType).Name != biomeData.GrassDecal) { continue; } // Biomes can contain multiple types of mote. foreach (var moteDetail in biomeData.Motes) { // Lower mote if voxel is ramped. float vOffset = 0.0f; if (v.RampType != RampType.None) { vOffset = -0.5f; } var vPos = v.WorldPosition * moteDetail.RegionScale; float value = MoteNoise.Noise(vPos.X, vPos.Y, vPos.Z); if (!(Math.Abs(value) > moteDetail.SpawnThreshold)) { continue; } float s = MoteScaleNoise.Noise(vPos.X, vPos.Y, vPos.Z) * moteDetail.MoteScale; var smallNoise = ClampVector(VertexNoise.GetRandomNoiseVector(vPos * 20.0f) * 20.0f, 0.4f); smallNoise.Y = 0.0f; var mote = GenerateGrassMote( Manager.World, v.WorldPosition + new Vector3(0.5f, 1.0f + s * 0.5f + vOffset, 0.5f) + smallNoise, new Color(v.Sunlight ? 255 : 0, 128, 0), s, moteDetail.Name); moteList.Add(mote); } } } MoteRecords[Y] = moteList; }
public void HandleAmbientSound() { AmbienceTimer.Update(DwarfTime.LastTime); if (!AmbienceTimer.HasTriggered && !firstAmbience) { return; } firstAmbience = false; // Before doing anything, determine if there is a rain or snow storm. if (Weather.IsRaining()) { PlaySpecialAmbient("sfx_amb_rain_storm"); return; } if (Weather.IsSnowing()) { PlaySpecialAmbient("sfx_amb_snow_storm"); return; } // First check voxels to see if we're underground or underwater. var vox = VoxelHelpers.FindFirstVisibleVoxelOnScreenRay(ChunkManager.ChunkData, GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2, Camera, GraphicsDevice.Viewport, 100.0f, false, null); if (vox.IsValid) { float height = WaterRenderer.GetTotalWaterHeightCells(vox); if (height > 0) { PlaySpecialAmbient("sfx_amb_ocean"); return; } else { // Unexplored voxels assumed to be cave. if (vox.IsValid && !vox.IsExplored) { PlaySpecialAmbient("sfx_amb_cave"); return; } var above = VoxelHelpers.GetVoxelAbove(vox); // Underground, do the cave test. if (above.IsValid && above.IsEmpty && above.Sunlight == false) { PlaySpecialAmbient("sfx_amb_cave"); return; } } } else { return; } // Now check for biome ambience. var pos = vox.WorldPosition; var biome = Overworld.GetBiomeAt(pos, WorldScale, WorldOrigin); if (biome != null && !string.IsNullOrEmpty(biome.DayAmbience)) { if (prevAmbience[0] != biome.DayAmbience) { if (!string.IsNullOrEmpty(prevAmbience[0])) { SoundManager.StopAmbience(prevAmbience[0]); prevAmbience[0] = null; } if (!string.IsNullOrEmpty(prevAmbience[1])) { SoundManager.StopAmbience(prevAmbience[1]); prevAmbience[1] = null; } SoundManager.PlayAmbience(biome.DayAmbience); } prevAmbience[0] = biome.DayAmbience; } if (!string.IsNullOrEmpty(biome.NightAmbience) && prevAmbience[1] != biome.NightAmbience) { prevAmbience[1] = biome.NightAmbience; SoundManager.PlayAmbience(biome.NightAmbience); } }
public void CreateMigration() { int tries = 0; float padding = 2.0f; while (tries < 10) { int side = MathFunctions.Random.Next(4); BoundingBox bounds = World.ChunkManager.Bounds; Vector3 pos = Vector3.Zero; switch (side) { case 0: pos = new Vector3(bounds.Min.X + padding, bounds.Max.Y - padding, MathFunctions.Rand(bounds.Min.Z + padding, bounds.Max.Z - padding)); break; case 1: pos = new Vector3(bounds.Max.X - padding, bounds.Max.Y - padding, MathFunctions.Rand(bounds.Min.Z + padding, bounds.Max.Z - padding)); break; case 2: pos = new Vector3(MathFunctions.Rand(bounds.Min.X + padding, bounds.Max.X - padding), bounds.Max.Y - padding, bounds.Min.Z + padding); break; case 3: pos = new Vector3(MathFunctions.Rand(bounds.Min.X + padding, bounds.Max.X - padding), bounds.Max.Y - padding, bounds.Max.Z - padding); break; } var biome = Overworld.GetBiomeAt(pos); if (biome.Fauna.Count == 0) { tries++; continue; } var randomFauna = Datastructures.SelectRandom(biome.Fauna); var testCreature = EntityFactory.CreateEntity <GameComponent>(randomFauna.Name, Vector3.Zero); if (testCreature == null) { tries++; continue; } var testCreatureAI = testCreature.GetRoot().GetComponent <CreatureAI>(); if (testCreatureAI == null || testCreatureAI.Movement.IsSessile) { testCreature.GetRoot().Delete(); tries++; continue; } var count = Creature.GetNumSpecies(testCreatureAI.Creature.Species); testCreature.GetRoot().Delete(); if (count < 30) { var randomNum = Math.Min(MathFunctions.RandInt(1, 3), 30 - count); for (int i = 0; i < randomNum; i++) { var randompos = MathFunctions.Clamp(pos + MathFunctions.RandVector3Cube() * 2, World.ChunkManager.Bounds); var vox = VoxelHelpers.FindFirstVoxelBelow(new VoxelHandle(World.ChunkManager.ChunkData, GlobalVoxelCoordinate.FromVector3(pos))); if (!vox.IsValid) { continue; } EntityFactory.CreateEntity <GameComponent>(randomFauna.Name, vox.GetBoundingBox().Center() + Vector3.Up * 1.5f); } } break; } }
private static void UpdateChunk(VoxelChunk chunk) { var addGrassToThese = new List <Tuple <VoxelHandle, byte> >(); for (var y = 0; y < VoxelConstants.ChunkSizeY; ++y) { // Skip empty slices. if (chunk.Data.VoxelsPresentInSlice[y] == 0) { continue; } for (var x = 0; x < VoxelConstants.ChunkSizeX; ++x) { for (var z = 0; z < VoxelConstants.ChunkSizeZ; ++z) { var voxel = new VoxelHandle(chunk, new LocalVoxelCoordinate(x, y, z)); // Allow grass to decay if (voxel.GrassType != 0) { var decal = GrassLibrary.GetGrassType(voxel.GrassType); if (decal.NeedsSunlight && voxel.SunColor < 255) { voxel.GrassType = 0; } else if (decal.Decay) { voxel.GrassDecay -= 1; if (voxel.GrassDecay == 0) { var newDecal = GrassLibrary.GetGrassType(decal.BecomeWhenDecays); if (newDecal != null) { voxel.GrassType = newDecal.ID; } else { voxel.GrassType = 0; } } } } else if (voxel.Type.GrassSpreadsHere) { // Spread grass onto this tile - but only from the same biome. var biome = Overworld.GetBiomeAt(voxel.Coordinate.ToVector3()); var grassyNeighbors = VoxelHelpers.EnumerateManhattanNeighbors2D(voxel.Coordinate) .Select(c => new VoxelHandle(voxel.Chunk.Manager.ChunkData, c)) .Where(v => v.IsValid && v.GrassType != 0) .Where(v => biome == Overworld.GetBiomeAt(v.Coordinate.ToVector3())) .ToList(); if (grassyNeighbors.Count > 0) { if (MathFunctions.RandEvent(0.1f)) { addGrassToThese.Add(Tuple.Create(voxel, grassyNeighbors[MathFunctions.RandInt(0, grassyNeighbors.Count)].GrassType)); } } } } } } foreach (var v in addGrassToThese) { var l = v.Item1; var grassType = GrassLibrary.GetGrassType(v.Item2); if (grassType.NeedsSunlight && l.SunColor != 255) { continue; } l.GrassType = v.Item2; } }