private void SetBiomeConfigGroupIdByParentBiomeConfig(BiomeConfig biomeConfig, BiomeConfig parentBiomeConfig) { if (parentBiomeConfig.groupId == int.MinValue) { if (borderBiomeIds.Contains(parentBiomeConfig.biomeId)) { for (int i = 0; i < parentBiomeConfig.biomeIsBorder.Count; i++) { BiomeConfig parentBorderBiome = GetBiomeConfigById(parentBiomeConfig.biomeIsBorder[i]); SetBiomeConfigGroupIdByParentBiomeConfig(parentBiomeConfig, parentBorderBiome); } } if (isleBiomeIds.Contains(parentBiomeConfig.biomeId)) { for (int j = 0; j < parentBiomeConfig.IsleInBiome.Count; j++) { BiomeConfig parentIslandBiome = GetBiomeConfigById(parentBiomeConfig.IsleInBiome[j]); SetBiomeConfigGroupIdByParentBiomeConfig(parentBiomeConfig, parentIslandBiome); } } } if (biomeConfig.groupId != int.MinValue && biomeConfig.groupId != parentBiomeConfig.groupId) { throw new Exception("生物群落id为" + biomeConfig.biomeId + "已存在组id分配,当前所属组id为:" + biomeConfig.groupId + ",想要为其分配组id为:" + parentBiomeConfig.groupId); } biomeConfig.groupId = parentBiomeConfig.groupId; }
public Texture2D GetTexture() { int xSize = 16; int zSize = 16; int chunkWidth = picWidth / 16; int chunkDepth = picHeight / 16; Texture2D tex = new Texture2D(chunkWidth * xSize, chunkDepth * zSize); ArraysCache cache = ArraysCacheManager.GetCache(); for (int x = 0; x < chunkWidth; x++) { for (int z = 0; z < chunkDepth; z++) { int[] result = mainLayer.getInts(cache, x * xSize, z * zSize, xSize, zSize); cache.release(); for (int i = 0; i < result.Length; i++) { int tempX = i % xSize; int tempZ = i / xSize; Color c; int biomeId = ((result[i] & BiomeBits)); BiomeConfig biomeConfig = WorldConfig.Instance.GetBiomeConfigById(biomeId); c = biomeConfig.color; tex.SetPixel(x * xSize + tempX, z * zSize + tempZ, c); } } } tex.Apply(); return(tex); }
//borderBiomeConfig为当前的边界生物群落,replaceBiomeId当前的边界群落能替换成的生物群落id public void addBiome(BiomeConfig borderBiomeConfig, int replaceBiomeId) { this.bordersFrom[replaceBiomeId] = new bool[WorldConfig.Instance.GetMaxBiomeCount()]; for (int i = 0; i < this.bordersFrom[replaceBiomeId].Length; i++) { BiomeConfig biomeConfig = WorldConfig.Instance.GetBiomeConfigOrNullById(i); this.bordersFrom[replaceBiomeId][i] = biomeConfig == null || !borderBiomeConfig.notBorderNear.Contains(biomeConfig.biomeId); } this.bordersTo[replaceBiomeId] = borderBiomeConfig.biomeId; }
private void SetBiomeConfigGroupId(BiomeConfig biomeConfig, int parentGroupId) { if (biomeConfig.groupId == int.MinValue) { biomeConfig.groupId = parentGroupId; } else { throw new Exception("生物群落id为" + biomeConfig.biomeId + "已存在组id分配,当前所属组id为:" + biomeConfig.groupId + ",想要为其分配组id为:" + parentGroupId); } }
public void Regist(BiomeConfig biomeConfig) { if (!_map.ContainsKey(biomeConfig.biomeId)) { _map.Add(biomeConfig.biomeId, biomeConfig); if (biomeConfig.biomeSize > _maxDepth) { _maxDepth = biomeConfig.biomeSize; } return; } throw new Exception("已配置id为" + biomeConfig.biomeId + "的生物群落!"); }
private void CalculateBiomeFactor(int x, int z, int ySections, float noiseHeight, BiomeConfig centerBiomeConfig) { float volatilitySum = 0f; float heightSum = 0f; float biomeWeightSum = 0f; float nextBiomeHeight, nextBiomeWeight; int lookRadius = centerBiomeConfig.smoothRadius; for (int nextX = -lookRadius; nextX <= lookRadius; nextX++) { for (int nextZ = -lookRadius; nextZ <= lookRadius; nextZ++) { int biomeId = this.biomeArray[(x + nextX + this.maxSmoothRadius) + (NOISE_MAX_Z + this.maxSmoothDiameter) * (z + nextZ + this.maxSmoothRadius)]; BiomeConfig nextBiomeConfig = WorldConfig.Instance.GetBiomeConfigById(biomeId); nextBiomeHeight = nextBiomeConfig.biomeHeight; //当前高度越高,权重会越小(即表示挥发性和高度都会越小) nextBiomeWeight = this.nearBiomeWeightArray[(nextX + this.maxSmoothRadius) + maxSmoothDiameter * (nextZ + this.maxSmoothRadius)] / (Math.Abs(nextBiomeHeight) + 1f); if (nextBiomeHeight > centerBiomeConfig.biomeHeight) { nextBiomeWeight /= 2.0f; } volatilitySum += nextBiomeConfig.biomeVolatility * nextBiomeWeight; heightSum += nextBiomeConfig.biomeHeight * nextBiomeWeight; biomeWeightSum += nextBiomeWeight; } } volatilitySum /= biomeWeightSum; heightSum /= biomeWeightSum; //防止最终值等于0 volatilitySum = volatilitySum * 0.9f + 0.1f; //将-10~10f转换为-1f~1f heightSum /= 10f; this.volatilityFactor = volatilitySum * 4f; float rate = (float)WorldConfig.Instance.baseTerrainHeight / OneOfTwoHeight; heightSum += noiseHeight * 0.2f; if (heightSum < 0f) { heightSum *= rate; } heightSum = (heightSum + 1.2f) / 2.4f; float offset = (WorldConfig.Instance.baseTerrainHeight - OneOfTwoHeight) / (float)Chunk.chunkHeight; this.heightFactor = ySections * (heightSum + offset); }
private void GenerateEntity(Chunk chunk, BiomeConfig biomeConfig) { for (int i = 0; i < biomeConfig.entityParams.Count; i++) { EntityParam entityParam = biomeConfig.entityParams[i]; if (_random.Range(0, 100) < entityParam.productRate) { for (int j = 0; j < entityParam.maxNum; j++) { int x = _random.Range(1, Chunk.chunkWidth - 1); int z = _random.Range(1, Chunk.chunkDepth - 1); if (chunk.GetBiomeId(x, z, true) != biomeConfig.biomeId) { continue; } DispatchEntity(chunk, x, z, entityParam); } } } }
private void GeneratePopulation(Chunk chunk, BiomeConfig biomeConfig) { for (int i = 0; i < biomeConfig.populationParams.Count; i++) { PopulationParam populationParam = biomeConfig.populationParams[i]; if (_random.Range(0, 100) < populationParam.productRate) { IDecoration decoration = DecorationFactory.GetDecoration(populationParam.decorationType); for (int j = 0; j < populationParam.frequency; j++) { int x = _random.Range(0, Chunk.chunkWidth); int z = _random.Range(0, Chunk.chunkDepth); if (chunk.GetBiomeId(x, z, true) != biomeConfig.biomeId) { continue; } DispatchDecoration(chunk, x, z, populationParam, decoration, biomeConfig.biomeId); } } } }
public void Generate(Chunk chunk) { _biomes.Clear(); _random.seed = chunk.chunkSeed; for (int x = 0; x < Chunk.chunkWidth; x++) { for (int z = 0; z < Chunk.chunkDepth; z++) { int biomeId = chunk.GetBiomeId(x, z, true); if (!_biomes.Contains(biomeId)) { _biomes.Add(biomeId); } } } for (int i = 0; i < _biomes.Count; i++) { BiomeConfig biomeConfig = WorldConfig.Instance.GetBiomeConfigById(_biomes[i]); GeneratePopulation(chunk, biomeConfig); GenerateEntity(chunk, biomeConfig); } }
public static Layer GetBaseLayer() { Layer mainLayer = new LayerEmpty(2); for (int depth = 0; depth <= WorldConfig.Instance.GenerateDepth; depth++) { mainLayer = new LayerZoom(2001 + depth, mainLayer); if (depth == WorldConfig.Instance.LandSize) { mainLayer = new LayerLand(1, mainLayer, WorldConfig.Instance.LandRarity); mainLayer = new LayerZoomFuzzy(1000, mainLayer); } //使陆地失真(即有可能产生的陆地,也有可能将陆地变为水) if (depth >= WorldConfig.Instance.LandSize && depth < WorldConfig.Instance.LandSize + WorldConfig.Instance.LandFuzzy) { mainLayer = new LayerLandRandom(depth, mainLayer); } if (WorldConfig.Instance.HasGroupConfigInDepth(depth)) { mainLayer = new LayerBiomeGroups(100, mainLayer, depth); } if (WorldConfig.Instance.HasBiomeConfigInDepth(depth)) { mainLayer = new LayerBiome(depth, mainLayer, depth); } // if(WorldConfig.Instance.riverRarity == depth) // { // mainLayer = new LayerRiverInit(132,mainLayer); // } // // if(WorldConfig.Instance.riverSize == depth) // { // mainLayer = new LayerRiver(5 + depth,mainLayer); // } LayerBiomeBorder layerBiomeBorder = new LayerBiomeBorder(200 + depth); bool hasBorder = false; for (int i = 0; i < WorldConfig.Instance.biomeConfigs.Count; i++) { BiomeConfig biomeConfig = WorldConfig.Instance.biomeConfigs[i]; if (biomeConfig.biomeSizeWhenIsle == depth && WorldConfig.Instance.isleBiomeIds.Contains(biomeConfig.biomeId) && biomeConfig.IsleInBiome.Count > 0) { LayerBiomeInBiome layerBiomeInBiome = new LayerBiomeInBiome(400 + biomeConfig.biomeId, mainLayer); layerBiomeInBiome.biomeConfig = biomeConfig; for (int j = 0; j < biomeConfig.IsleInBiome.Count; j++) { int isleBiomeId = biomeConfig.IsleInBiome[j]; if (isleBiomeId == DefaultBiome.Ocean.id) { layerBiomeInBiome.inOcean = true; } else { layerBiomeInBiome.biomeIsles[isleBiomeId] = true; } } layerBiomeInBiome.chance = biomeConfig.biomeRarityWhenIsle; mainLayer = layerBiomeInBiome; } if (biomeConfig.biomeSizeWhenBorder == depth && WorldConfig.Instance.borderBiomeIds.Contains(biomeConfig.biomeId) && biomeConfig.biomeIsBorder.Count > 0) { hasBorder = true; for (int j = 0; j < biomeConfig.biomeIsBorder.Count; j++) { int replaceBiomeId = biomeConfig.biomeIsBorder[j]; layerBiomeBorder.addBiome(biomeConfig, replaceBiomeId); } } } if (hasBorder) { layerBiomeBorder.child = mainLayer; mainLayer = layerBiomeBorder; } } mainLayer = new LayerOutputDefault(1000, mainLayer); mainLayer = new LayerSmooth(400, mainLayer); return(mainLayer); }
private void AddBiomeBlocks(Chunk chunk) { int dryBlocksOnSurface = 256; int chunkX = chunk.worldPos.x; int chunkZ = chunk.worldPos.z; for (int x = 0; x < Chunk.chunkWidth; x++) { for (int z = 0; z < Chunk.chunkDepth; z++) { BiomeConfig biomeConfig = WorldConfig.Instance.GetBiomeConfigById(this.biomeArray[x + Chunk.chunkDepth * z]); // int surfaceBlocksNoise = (int)_surfaceNoiseGen.GetValue(chunkX + x,chunkZ + z); int surfaceBlocksNoise = 1; Block currentSurfaceBlock = biomeConfig.surfaceBlock; Block currentGroundBlock = biomeConfig.groundBlock; int surfaceBlocksCount = int.MinValue; int currentWaterLevel = this.waterLevel[x * Chunk.chunkDepth + z]; for (int y = heightCap - 1; y >= 0; y--) { Block curBlock = chunk.GetBlock(x, y, z, true); if (curBlock.BlockType == BlockType.Air) { surfaceBlocksCount = int.MinValue; } else if (curBlock.EqualOther(biomeConfig.stoneBlock)) { if (surfaceBlocksCount == int.MinValue) { if (surfaceBlocksNoise <= 0 && biomeConfig.removeSurfaceStone) { currentSurfaceBlock = air; currentGroundBlock = biomeConfig.groundBlock; } /*else if((y > currentWaterLevel - 3) && (y < currentWaterLevel + 2)) * { * currentSurfaceBlock = biomeConfig.surfaceBlock; * currentGroundBlock = biomeConfig.groundBlock; * } */ if ((y < currentWaterLevel) && (y > biomeConfig.waterLevelMin) && currentSurfaceBlock.BlockType == BlockType.Air) { currentSurfaceBlock = biomeConfig.waterBlock; } surfaceBlocksCount = surfaceBlocksNoise; if (surfaceBlocksNoise <= 0) { surfaceBlocksCount += 3; } if (y > currentWaterLevel - 2) { chunk.SetBlock(x, y, z, currentSurfaceBlock, true); } else { chunk.SetBlock(x, y, z, currentGroundBlock, true); } } else if (surfaceBlocksCount > 0) { surfaceBlocksCount--; chunk.SetBlock(x, y, z, currentGroundBlock, true); } } } } } }
private void GenerateTerrainNoise(int xOffset, int yOffset, int zOffset, int maxYSections) { if (this.rawTerrain == null || (this.rawTerrain.Length != NOISE_MAX_X * maxYSections * NOISE_MAX_Z)) { this.rawTerrain = new float[NOISE_MAX_X * maxYSections * NOISE_MAX_Z]; } for (int x = 0; x < NOISE_MAX_X; x++) { for (int z = 0; z < NOISE_MAX_Z; z++) { int biomeId = this.biomeArray[(x + this.maxSmoothRadius) + (NOISE_MAX_Z + this.maxSmoothDiameter) * (z + this.maxSmoothRadius)]; BiomeConfig biomeConfig = WorldConfig.Instance.GetBiomeConfigById(biomeId); //输出值为-0.5~0.5f float noiseHeight = _heightTerrainNoiseGen.GetValue(xOffset + x, zOffset + z); //将noiseHeight转换到-1~1f if (noiseHeight < 0f) { if (noiseHeight < -1f) { noiseHeight = -1f; } noiseHeight -= biomeConfig.maxAverageDepth; } else { if (noiseHeight > 1f) { noiseHeight = 1f; } noiseHeight += biomeConfig.maxAverageHeight; } this.waterLevelRaw[x * NOISE_MAX_Z + z] = (byte)biomeConfig.waterLevelMax; CalculateBiomeFactor(x, z, maxYSections - 1, noiseHeight, biomeConfig); for (int y = 0; y < maxYSections; y++) { float output = 0; float selectNoise = _fractureNoiseSelect.GetValue((xOffset + x), (yOffset + y), (zOffset + z)); selectNoise = (selectNoise + 1f) / 2f; if (selectNoise < biomeConfig.volatilityWeight1) { output = _fractureNoiseGen1.GetValue(xOffset + x, yOffset + y, zOffset + z) * biomeConfig.volatility1; } else if (selectNoise > biomeConfig.volatilityWeight2) { output = _fractureNoiseGen2.GetValue(xOffset + x, yOffset + y, zOffset + z) * biomeConfig.volatility2; } else { float fracture1 = _fractureNoiseGen1.GetValue(xOffset + x, yOffset + y, zOffset + z) * biomeConfig.volatility1; float fracture2 = _fractureNoiseGen2.GetValue(xOffset + x, yOffset + y, zOffset + z) * biomeConfig.volatility2; output = fracture1 + (fracture2 - fracture1) * selectNoise; } if (!biomeConfig.disableNotchHeightControl) { float output_notchHeight; //越到地平线形变越严重 output_notchHeight = ((this.heightFactor - y) / this.volatilityFactor); if (output_notchHeight > 0) { output_notchHeight += output_notchHeight * 10f + 1; } output += output_notchHeight; if (y > maxYSections - 4) { float subMaxLastThreeLayerY = (y - (maxYSections - 4)) / 3.0f; output = output * (1.0f - subMaxLastThreeLayerY) - subMaxLastThreeLayerY; } } output += biomeConfig.heightMatrix[y]; this.rawTerrain[(x * NOISE_MAX_Z + z) * maxYSections + y] = output; } } } }
private void GenerateBiomeAndTerrain(Chunk chunk) { int chunkX = chunk.worldPos.x; int chunkZ = chunk.worldPos.z; int maxYSections = heightCap / 8 + 1; int oneEightOfHeight = heightCap / 8; this.biomeArray = _biomeGenerator.GetBiomesUnZoomed(this.biomeArray, chunkX / 4 - this.maxSmoothRadius, chunkZ / 4 - this.maxSmoothRadius, NOISE_MAX_X + this.maxSmoothDiameter, NOISE_MAX_Z + this.maxSmoothDiameter); GenerateTerrainNoise(chunkX / 4, 0, chunkZ / 4, maxYSections); this.biomeArray = _biomeGenerator.GetBiomes(this.biomeArray, chunkX, chunkZ, Chunk.chunkWidth, Chunk.chunkDepth); float oneOfEight = 0.125f; float oneOfFourth = 0.25f; for (int x = 0; x < NOISE_MAX_X - 1; x++) { for (int z = 0; z < NOISE_MAX_Z - 1; z++) { float waterLevel_x0z0 = this.waterLevelRaw[x * NOISE_MAX_Z + z] & 0xff; float waterLevel_x0z1 = this.waterLevelRaw[x * NOISE_MAX_Z + (z + 1)] & 0xff; float waterLevel_x1z0 = ((this.waterLevelRaw[(x + 1) * NOISE_MAX_Z + z] & 0xff) - waterLevel_x0z0) * oneOfFourth; float waterLevel_x1z1 = ((this.waterLevelRaw[(x + 1) * NOISE_MAX_Z + (z + 1)] & 0xff) - waterLevel_x0z1) * oneOfFourth; for (int x_piece = 0; x_piece < 4; x_piece++) { float waterLevelForArray = waterLevel_x0z0; float subZ1_0 = (waterLevel_x0z1 - waterLevel_x0z0) * oneOfFourth; for (int z_piece = 0; z_piece < 4; z_piece++) { this.waterLevel[(x * 4 + x_piece) * Chunk.chunkDepth + (z * 4 + z_piece)] = (byte)waterLevelForArray; waterLevelForArray += subZ1_0; } waterLevel_x0z0 += waterLevel_x1z0; waterLevel_x0z1 += waterLevel_x1z1; } for (int y = 0; y < oneEightOfHeight; y++) { float x0z0 = this.rawTerrain[(x * NOISE_MAX_Z + z) * maxYSections + y]; float x0z1 = this.rawTerrain[(x * NOISE_MAX_Z + (z + 1)) * maxYSections + y]; float x1z0 = this.rawTerrain[((x + 1) * NOISE_MAX_Z + z) * maxYSections + y]; float x1z1 = this.rawTerrain[((x + 1) * NOISE_MAX_Z + (z + 1)) * maxYSections + y]; float x0z0y1 = (this.rawTerrain[(x * NOISE_MAX_Z + z) * maxYSections + (y + 1)] - x0z0) * oneOfEight; float x0z1y1 = (this.rawTerrain[(x * NOISE_MAX_Z + (z + 1)) * maxYSections + (y + 1)] - x0z1) * oneOfEight; float x1z0y1 = (this.rawTerrain[((x + 1) * NOISE_MAX_Z + z) * maxYSections + (y + 1)] - x1z0) * oneOfEight; float x1z1y1 = (this.rawTerrain[((x + 1) * NOISE_MAX_Z + (z + 1)) * maxYSections + (y + 1)] - x1z1) * oneOfEight; for (int y_piece = 0; y_piece < 8; y_piece++) { float d11 = x0z0; float d12 = x0z1; float d13 = (x1z0 - x0z0) * oneOfFourth; float d14 = (x1z1 - x0z1) * oneOfFourth; for (int x_piece = 0; x_piece < 4; x_piece++) { float result = d11; float subZ1_0 = (d12 - d11) * oneOfFourth; for (int z_piece = 0; z_piece < 4; z_piece++) { int tx = x * 4 + x_piece; int ty = y * 8 + y_piece; int tz = z * 4 + z_piece; terrain[(tx * Chunk.chunkDepth + tz) * heightCap + ty] = result; // terrain[x * 4 + x_piece,y * 8 + y_piece,z * 4 + z_piece] = result; result += subZ1_0; } d11 += d13; d12 += d14; } x0z0 += x0z0y1; x0z1 += x0z1y1; x1z0 += x1z0y1; x1z1 += x1z1y1; } } } } for (int x = 0; x < Chunk.chunkWidth; x++) { for (int z = 0; z < Chunk.chunkDepth; z++) { BiomeConfig biomeConfig = WorldConfig.Instance.GetBiomeConfigById(this.biomeArray[x + Chunk.chunkDepth * z]); int curWaterLevel = waterLevel[x * Chunk.chunkDepth + z] & 0xff; for (int y = Chunk.chunkHeight - 1; y >= 0; y--) { Block b = air; if (y < heightCap) { if (y < curWaterLevel && y > biomeConfig.waterLevelMin) { b = water; } if (terrain[(x * Chunk.chunkDepth + z) * heightCap + y] > 0f) { b = biomeConfig.stoneBlock; } } chunk.SetBlock(x, y, z, b, true); } } } }
void Awake() { Instance = this; _biomeGroupConfigMap = new Dictionary <int, BiomeGroupConfig>(); _biomeConfigMap = new Dictionary <int, BiomeConfig>(); if (biomeGroupConfigs == null) { return; } if (biomeConfigs == null) { return; } for (int i = 0; i < biomeGroupConfigs.Count; i++) { for (int j = 0; j < biomeConfigs.Count; j++) { if (biomeGroupConfigs[i].biomeIds.Contains(biomeConfigs[j].biomeId)) { biomeGroupConfigs[i].Regist(biomeConfigs[j]); SetBiomeConfigGroupId(biomeConfigs[j], biomeGroupConfigs[i].groupId); } } if (!_biomeGroupConfigMap.ContainsKey(biomeGroupConfigs[i].groupId)) { if (biomeGroupConfigs[i].isUsing) { _biomeGroupConfigMap.Add(biomeGroupConfigs[i].groupId, biomeGroupConfigs[i]); } } else { throw new Exception("已存在id为:" + biomeGroupConfigs[i].groupId + "的生物群落组!"); } if (biomeGroupConfigs[i].groupSize > _maxDepth && biomeGroupConfigs[i].isUsing) { _maxDepth = biomeGroupConfigs[i].groupSize; } } for (int j = 0; j < biomeConfigs.Count; j++) { biomeConfigs[j].Init(this); if (!_biomeConfigMap.ContainsKey(biomeConfigs[j].biomeId)) { if (biomeConfigs[j].biomeId > _maxBiomeId) { _maxBiomeId = biomeConfigs[j].biomeId; } _biomeConfigMap.Add(biomeConfigs[j].biomeId, biomeConfigs[j]); } else { throw new Exception("已存在id为:" + biomeConfigs[j].biomeId + "的生物群落!"); } if (biomeConfigs[j].smoothRadius > _maxSmoothRadius) { _maxSmoothRadius = biomeConfigs[j].smoothRadius; } } GetBiomeConfigById(0).groupId = 0; for (int j = 0; j < biomeConfigs.Count; j++) { if (borderBiomeIds.Contains(biomeConfigs[j].biomeId)) { for (int i = 0; i < biomeConfigs[j].biomeIsBorder.Count; i++) { BiomeConfig parentBorderBiome = GetBiomeConfigById(biomeConfigs[j].biomeIsBorder[i]); SetBiomeConfigGroupIdByParentBiomeConfig(biomeConfigs[j], parentBorderBiome); } } if (isleBiomeIds.Contains(biomeConfigs[j].biomeId)) { for (int i = 0; i < biomeConfigs[j].IsleInBiome.Count; i++) { BiomeConfig parentIslandBiome = GetBiomeConfigById(biomeConfigs[j].IsleInBiome[i]); SetBiomeConfigGroupIdByParentBiomeConfig(biomeConfigs[j], parentIslandBiome); } } } }