Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- using UnityEngine;
- public class TerrainGenerator : MonoBehaviour //############ i believe that this code works only for chunks with even size !!!!!!!!!!!!!!
- {
- public const int MaxDev = 20; // maximum deviation for the new seed
- public int[] localSeed = new[] { -1, -1, -1, -1 }; //density%, grass%, bush%, tree%
- private int[] initSeed = new[] { 40, 50, 20, 30 };
- public List<string> elementNames; //elementNames[1] corresponds to localSeed[1]
- private Dictionary<string, bool> takenArea = new Dictionary<string, bool>();
- private struct TerrainElement
- {
- public GameObject prefab;
- public int width;
- public int height;
- public int area;
- public int layer;
- public TerrainElement(GameObject prefab, int width, int height, int layer)
- {
- this.prefab = prefab;
- this.width = width;
- this.height = height;
- this.layer = layer;
- this.area = height * width;
- }
- }
- Dictionary<string, TerrainElement> terrainElements;
- private void Awake()
- {
- elementNames = new List<string>();
- elementNames.Add("empty");
- terrainElements = new Dictionary<string, TerrainElement>();
- TerrainElement tree = new TerrainElement(Resources.Load<GameObject>("Prefabs/Tree"), 3, 3, -4); //width, height, layer
- TerrainElement bush = new TerrainElement(Resources.Load<GameObject>("Prefabs/Bush"), 1, 1, -2);
- TerrainElement grass = new TerrainElement(Resources.Load<GameObject>("Prefabs/Grass"), 1, 1, -1);
- elementNames.Add("grass");
- terrainElements.Add("grass", grass); //seed[1]
- elementNames.Add("bush");
- terrainElements.Add("bush", bush); // seed[2]
- elementNames.Add("tree");
- terrainElements.Add("tree", tree); // seed[3]
- }
- public void Initialize(List<int[]> seeds)
- {
- localSeed = GenerateSeed(seeds);
- GenerateTerrain(localSeed);
- }
- public void GenerateTerrain(int[] seed)
- {
- /*
- * chunk size - 121
- * bush size - 1 data - 1
- * grass size - 1 data - 2
- * tree size - 4 data - 3
- */
- if (IsSeedProper(seed))
- {
- int freeArea = Chunk.ChunkSize * Chunk.ChunkSize * seed[0] / 100;
- int amount;
- for (int x = 1; x < elementNames.Count; x++)
- {
- TerrainElement toLoad = terrainElements[elementNames[x]];
- amount = freeArea * seed[x] / 100 / toLoad.area;
- SpawnStruct(toLoad, amount);
- }
- }
- }
- private void SpawnStruct(TerrainElement terrainElement, int amount)
- {
- GameObject prefab = terrainElement.prefab;
- int width = terrainElement.width;
- int height = terrainElement.height;
- int fromCenter = Mathf.RoundToInt(Chunk.fromCenter);
- Vector3 spot;
- int x = Random.Range(-fromCenter, fromCenter - width + 1); //makes sure that whole terrain element gets spawned inside of the chunk
- int y = Random.Range(-fromCenter + height, fromCenter + 1); //because x and y represent top left 1x1 part of the element
- for (int i = 0; i < amount; i++)
- {
- while (!DoesFit(x, y, width, height)) //checks if terrain element can fit if it's top right corner is at x y
- {
- x = Random.Range(-fromCenter, fromCenter - width + 1);
- y = Random.Range(-fromCenter + height, fromCenter + 1);
- }
- spot = new Vector3(x + width / 2f, y - height / 2f, 0); //we align the sprite with the grid
- GameObject temp;
- temp = Instantiate(prefab, transform.position + spot, Quaternion.identity);
- temp.transform.parent = gameObject.transform;
- temp.transform.position += new Vector3(0, 0, terrainElement.layer);
- }
- }
- private string VecToString(int x, int y)
- {
- return x.ToString() + y.ToString();
- }
- private bool DoesFit(int xPos, int yPos, int width, int height){
- for(int x = xPos; x < xPos + width; x++) //xpos and ypos represent top left of element, so we need to check the rest of the right side for obstructions
- {
- for(int y = yPos; y > yPos - height; y--) // same, as above, but this time we check the area below y
- {
- if (takenArea.ContainsKey(VecToString(x, y)))
- {
- return false;
- }
- }
- }
- for (int x = xPos; x < xPos + width; x++) //only works if we can safely insert element onto the chunk, fills out taken area
- {
- for (int y = yPos; y > yPos - height; y--)
- {
- takenArea.Add(VecToString(x, y), true);
- }
- }
- return true;
- }
- public int[] GenerateSeed(List<int[]> seeds)
- {
- int paramCount = Chunk.Params;
- List<int[]> initializedSeeds = new List<int[]>();
- foreach(int[] seed in seeds) // we filter out empty seeds and store them in nonNullSeeds
- {
- if(IsSeedProper(seed))
- {
- initializedSeeds.Add(seed);
- }
- }
- if(initializedSeeds.Count == 0) // if every single seed was null we give our seed a random value
- {
- return new int[] {35, 50, 25, 25};
- }
- int[] averageOfParams = new int[paramCount]; //this array will be used to get the average of parameters from neighbouring cells
- System.Array.Clear(averageOfParams, 0, paramCount); // fill out with zeros
- foreach (int[] seed in initializedSeeds) //we sum up seed values
- {
- for(int x = 0; x < paramCount; x++)
- {
- averageOfParams[x] += seed[x];
- }
- }
- for(int x = 0; x < paramCount; x++) //gets the average for every value and randomly changes it by Max Deviation value
- {
- averageOfParams[x] /= initializedSeeds.Count;
- if(x != 0)
- {
- averageOfParams[x] += Random.Range(-MaxDev, MaxDev);
- if(averageOfParams[x] < 10)
- {
- averageOfParams[x] = 10;
- }
- if(averageOfParams[x] >= 100)
- {
- averageOfParams[x] = 99;
- }
- }
- }
- int leftTo100 = 100 - ArraySum(averageOfParams, 1, averageOfParams.Length - 1); // checks how far off are we from 100%
- int changeBy = leftTo100 / 3;
- int lastAdj = leftTo100 - changeBy * 3;
- for(int x = 1; x < paramCount; x++)
- {
- averageOfParams[x] += changeBy;
- }
- averageOfParams[Random.Range(1, 4)] += lastAdj;
- return averageOfParams;
- }
- private int ArraySum(int[] arr, int start, int end)
- {
- int total = 0;
- for(int x = start; x <= end; x++)
- {
- total += arr[x];
- }
- return total;
- }
- public int[] GetSeed()
- {
- return localSeed;
- }
- public bool IsSeedProper(int[] seed)
- {
- foreach(int x in seed)
- {
- if(x < 0)
- {
- return false;
- }
- }
- return true;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement