-
-
Save Shaun-Meechan/ac53a7434d72993e839181d50bba2d40 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
#if UNITY_EDITOR | |
using UnityEditor.SceneManagement; | |
using UnityEngine.SceneManagement; | |
#endif | |
public class WorldGeneration : MonoBehaviour | |
{ | |
[Tooltip("The biome/biomes that will be generated")] | |
public List<GameObject> tileTypesList; | |
List<GameObject> possibleTileTypes; | |
public GameObject tilePrefab; | |
public int gridWidth; | |
public int gridHeight; | |
public uint numberOfVillages; | |
public uint numberOfTowns; | |
public uint numberOfCities; | |
GameObject[,] tiles; | |
public GameObject powerOutIconPrefab; | |
public void generate() | |
{ | |
tiles = new GameObject[gridWidth, gridHeight]; | |
int randomNumber; | |
Debug.Log("Start called"); | |
for (int i = 0; i < gridHeight; i++) | |
{ | |
for (int j = 0; j < gridWidth; j++) | |
{ | |
for (int k = 0; k < tileTypesList.Count; k++) | |
{ | |
possibleTileTypes.Add(tileTypesList[k]); | |
} | |
if(i <= gridHeight /2) | |
{ | |
for (int k = 0; k < possibleTileTypes.Count; k++) | |
{ | |
if (possibleTileTypes[k].name == "Tundra") | |
{ | |
possibleTileTypes.RemoveAt(k); | |
} | |
} | |
} | |
randomNumber = pickNewTileType(); | |
//Generate an ocean at the bottom of the map | |
if (doesTileListContains("Water") && i <= 2) | |
{ | |
randomNumber = 2; | |
assignTileType(randomNumber,j,i); | |
tiles[j, i].GetComponent<Tile>().setPosition(j, i); | |
possibleTileTypes.Clear(); | |
continue; | |
} | |
//Generate a tundra area at the top of the map | |
if (doesTileListContains("Tundra") && i >= 35) | |
{ | |
if(doesTileListContains("Mountains")) | |
{ | |
randomNumber = Random.Range(5, 7); | |
} | |
else | |
{ | |
randomNumber = 6; | |
} | |
assignTileType(randomNumber,j,i); | |
//Need to create a new go here | |
tiles[j, i].GetComponent<Tile>().setPosition(j, i); | |
possibleTileTypes.Clear(); | |
continue; | |
} | |
while (checkRules(randomNumber, j, i) == false) | |
{ | |
randomNumber = pickNewTileType(); | |
} | |
assignTileType(randomNumber,j, i); | |
tiles[j,i].GetComponent<Tile>().setPosition(j,i); | |
possibleTileTypes.Clear(); | |
} | |
} | |
generateBuildings(); | |
#if UNITY_EDITOR | |
EditorSceneManager.SaveScene(SceneManager.GetActiveScene()); | |
Debug.Log("Scene saved!"); | |
#endif | |
} | |
bool checkRules(int randomNumber, int x, int y) | |
{ | |
if (randomNumber == 5 && generateMountain(x, y) == false) | |
{ | |
for (int k = 0; k < possibleTileTypes.Count; k++) | |
{ | |
if (possibleTileTypes[k].name == "Mountains") | |
{ | |
possibleTileTypes.RemoveAt(k); | |
} | |
} | |
return false; | |
} | |
//Check if we can generate some water | |
if (randomNumber == 2 && generateWater(x, y) == false) | |
{ | |
for (int k = 0; k < possibleTileTypes.Count; k++) | |
{ | |
if (possibleTileTypes[k].name == "Water") | |
{ | |
possibleTileTypes.RemoveAt(k); | |
} | |
} | |
return false; | |
} | |
//See if we can generate some desert | |
if (randomNumber == 3 && generateDesert(x, y) == false) | |
{ | |
for (int k = 0; k < possibleTileTypes.Count; k++) | |
{ | |
if (possibleTileTypes[k].name == "Desert") | |
{ | |
possibleTileTypes.RemoveAt(k); | |
} | |
} | |
return false; | |
} | |
//See if we can generate some plains | |
if (randomNumber == 0 && generatePlain(x, y) == false) | |
{ | |
for (int k = 0; k < possibleTileTypes.Count; k++) | |
{ | |
if (possibleTileTypes[k].name == "Plains") | |
{ | |
possibleTileTypes.RemoveAt(k); | |
} | |
} | |
return false; | |
} | |
return true; | |
} | |
void assignTileType(int randomNumber, int gridXPosition, int gridYPosition) | |
{ | |
switch (randomNumber) | |
{ | |
case 0: | |
GameObject go = Instantiate(tileTypesList[getIndexOfTile("Plains")], new Vector3(gridYPosition * 10, 0, gridXPosition * 10), Quaternion.identity); | |
Tile tile = go.GetComponent<Tile>(); | |
go.name = "Tiles:" + gridXPosition + " " + gridYPosition; | |
tiles[gridXPosition, gridYPosition] = go; | |
tile.setTileType(Tile.tileTypes.Plains); | |
tile.sunCoverage = 10f; | |
tile.windSpeed = 10f; | |
tile.geothermalStrength = generateGeothermalPowerValue(); | |
break; | |
case 1: | |
GameObject go1 = Instantiate(tileTypesList[getIndexOfTile("Hills")], new Vector3(gridYPosition * 10, 0, gridXPosition * 10), Quaternion.identity); | |
Tile tile1 = go1.GetComponent<Tile>(); | |
go1.name = "Tiles:" + gridXPosition + " " + gridYPosition; | |
tiles[gridXPosition, gridYPosition] = go1; | |
tile1.setTileType(Tile.tileTypes.Hills); | |
tile1.windSpeed = 20f; | |
tile1.sunCoverage = 5f; | |
tile1.geothermalStrength = generateGeothermalPowerValue(); | |
break; | |
case 2: | |
GameObject go2 = Instantiate(tileTypesList[getIndexOfTile("Water")], new Vector3(gridYPosition * 10, 0, gridXPosition * 10), Quaternion.identity); | |
Tile tile2 = go2.GetComponent<Tile>(); | |
go2.name = "Tiles:" + gridXPosition + " " + gridYPosition; | |
tiles[gridXPosition, gridYPosition] = go2; | |
tile2.setTileType(Tile.tileTypes.Water); | |
tile2.tidalStrength = 10f; | |
tile2.windSpeed = 10f; | |
tile2.sunCoverage = 10f; | |
break; | |
case 3: | |
GameObject go3 = Instantiate(tileTypesList[getIndexOfTile("Desert")], new Vector3(gridYPosition * 10, 0, gridXPosition * 10), Quaternion.identity); | |
Tile tile3 = go3.GetComponent<Tile>(); | |
go3.name = "Tiles:" + gridXPosition + " " + gridYPosition; | |
tiles[gridXPosition, gridYPosition] = go3; | |
tile3.setTileType(Tile.tileTypes.Dessert); | |
tile3.sunCoverage = 20f; | |
tile3.windSpeed = 20f; | |
tile3.geothermalStrength = generateGeothermalPowerValue(); | |
break; | |
case 4: | |
GameObject go4 = Instantiate(tileTypesList[getIndexOfTile("Forrest")], new Vector3(gridYPosition * 10, 0, gridXPosition * 10), Quaternion.identity); | |
Tile tile4 = go4.GetComponent<Tile>(); | |
go4.name = "Tiles:" + gridXPosition + " " + gridYPosition; | |
tiles[gridXPosition, gridYPosition] = go4; | |
tile4.setTileType(Tile.tileTypes.Forrest); | |
tile4.geothermalStrength = generateGeothermalPowerValue(); | |
break; | |
case 5: | |
GameObject go5 = Instantiate(tileTypesList[getIndexOfTile("Mountains")], new Vector3(gridYPosition * 10, 0, gridXPosition * 10), Quaternion.identity); | |
Tile tile5 = go5.GetComponent<Tile>(); | |
go5.name = "Tiles:" + gridXPosition + " " + gridYPosition; | |
tiles[gridXPosition, gridYPosition] = go5; | |
tile5.setTileType(Tile.tileTypes.Mountains); | |
break; | |
case 6: | |
GameObject go6 = Instantiate(tileTypesList[getIndexOfTile("Tundra")], new Vector3(gridYPosition * 10, 0, gridXPosition * 10), Quaternion.identity); | |
Tile tile6 = go6.GetComponent<Tile>(); | |
go6.name = "Tiles:" + gridXPosition + " " + gridYPosition; | |
tiles[gridXPosition, gridYPosition] = go6; | |
tile6.setTileType(Tile.tileTypes.Tundra); | |
tile6.sunCoverage = 4f; | |
tile6.windSpeed = 10f; | |
tile6.geothermalStrength = generateGeothermalPowerValue(); | |
break; | |
case 7: | |
GameObject go7 = Instantiate(tilePrefab, new Vector3(gridYPosition * 10, 0, gridXPosition * 10), Quaternion.identity); | |
Tile tile7 = go7.GetComponent<Tile>(); | |
go7.name = "Tiles:" + gridXPosition + " " + gridYPosition; | |
tiles[gridXPosition, gridYPosition] = go7; | |
tile7.setTileType(Tile.tileTypes.Building); | |
break; | |
default: | |
break; | |
} | |
} | |
int generateGeothermalPowerValue() | |
{ | |
return Random.Range(0, 11); | |
} | |
int pickNewTileType() | |
{ | |
int randomNumber = Random.Range(0, 8); | |
int[] differences = new int[possibleTileTypes.Count]; | |
int higestDifference = int.MinValue; | |
//We now need to see what possible tile type that number is closest to | |
for (int i = 0; i < differences.Length; i++) | |
{ | |
differences[i] = Mathf.Abs((int)(randomNumber - possibleTileTypes[i].GetComponent<Tile>().getTileType())); | |
} | |
for (int i = 0; i < differences.Length; i++) | |
{ | |
if(differences[i] == 0) | |
{ | |
return (int)possibleTileTypes[i].GetComponent<Tile>().getTileType(); | |
} | |
if (differences[i] > higestDifference) | |
{ | |
higestDifference = (int)possibleTileTypes[i].GetComponent<Tile>().getTileType(); | |
} | |
} | |
return higestDifference; | |
} | |
bool generateWater(int x, int y) | |
{ | |
//Check neigbours to see if we are on the border | |
if(x == 0 || x == gridWidth - 1) | |
{ | |
//On the side of the level | |
return true; | |
} | |
if(y == 0 || y == gridHeight - 1) | |
{ | |
//On the bottom or top | |
return true; | |
} | |
//We aren't on a border tile | |
//Check our left | |
if (tiles[x - 1, y].gameObject.GetComponent<Tile>().getTileType() == Tile.tileTypes.Water) | |
{ | |
return true; | |
} | |
//Check below | |
if (tiles[x, y - 1].gameObject.GetComponent<Tile>().getTileType() == Tile.tileTypes.Water) | |
{ | |
return true; | |
} | |
return false; | |
} | |
bool generateDesert(int x, int y) | |
{ | |
if (doesTileListContains("Tundra") && y >= gridHeight / 2) | |
{ | |
return false; | |
} | |
//Check neigbours to see if we are on the border | |
if (x == 0 || x == gridWidth - 1) | |
{ | |
if(y == 0) | |
{ | |
return true; | |
} | |
//Check below | |
if (tiles[x, y - 1].gameObject.GetComponent<Tile>().getTileType() != Tile.tileTypes.Tundra) | |
{ | |
return true; | |
} | |
return false; | |
} | |
if(y == 0 || y == gridHeight - 1) | |
{ | |
if (tiles[x - 1, y].gameObject.GetComponent<Tile>().getTileType() != Tile.tileTypes.Tundra) | |
{ | |
return true; | |
} | |
} | |
//We aren't on a border tile | |
//Check our left and bottom | |
if (tiles[x - 1, y].gameObject.GetComponent<Tile>().getTileType() != Tile.tileTypes.Tundra && tiles[x, y - 1].gameObject.GetComponent<Tile>().getTileType() != Tile.tileTypes.Tundra) | |
{ | |
return true; | |
} | |
return false; | |
} | |
bool generatePlain(int x, int y) | |
{ | |
//If the world has tundra and we are in the north return false | |
if (doesTileListContains("Tundra") && y >= gridHeight / 2) | |
{ | |
return false; | |
} | |
//Check neigbours to see if we are on the border | |
if (x == 0 || x == gridWidth - 1) | |
{ | |
if (y == 0) | |
{ | |
return true; | |
} | |
//Check below | |
if (tiles[x, y - 1].gameObject.GetComponent<Tile>().getTileType() != Tile.tileTypes.Tundra) | |
{ | |
return true; | |
} | |
return false; | |
} | |
if(y == 0 || y == gridHeight - 1) | |
{ | |
if (tiles[x - 1, y].gameObject.GetComponent<Tile>().getTileType() != Tile.tileTypes.Tundra) | |
{ | |
return true; | |
} | |
} | |
//We aren't on a border tile | |
//Check our left and bottom | |
if (tiles[x - 1, y].gameObject.GetComponent<Tile>().getTileType() != Tile.tileTypes.Tundra && tiles[x, y - 1].gameObject.GetComponent<Tile>().getTileType() != Tile.tileTypes.Tundra) | |
{ | |
return true; | |
} | |
return false; | |
} | |
//This should be run AFTER world generation | |
void generateBuildings() | |
{ | |
int counter = 0; | |
int x = 0; | |
int y = 0; | |
for (int i = 0; i < numberOfVillages; i++) | |
{ | |
for (int j = 0; j < 4; j++) | |
{ | |
if (counter == 0) | |
{ | |
x = Random.Range(0, gridWidth - 1); | |
y = Random.Range(4, gridHeight - 1); | |
while (validBuildingLocation(x,y,2,1) == false) | |
{ | |
x = Random.Range(0, gridWidth - 1); | |
y = Random.Range(4, gridHeight - 1); | |
} | |
} | |
if(counter == 4) | |
{ | |
x = Random.Range(4, gridWidth - 1); | |
y = Random.Range(0, gridHeight - 1); | |
while (validBuildingLocation(x, y, 2, 1) == false) | |
{ | |
x = Random.Range(0, gridWidth - 1); | |
y = Random.Range(4, gridHeight - 1); | |
} | |
counter = 0; | |
} | |
//0,1 | |
if (counter < 2) | |
{ | |
tiles[x + counter, y].GetComponent<Tile>().setTileType(Tile.tileTypes.Building); | |
tiles[x + counter, y].AddComponent<BuildingTile>(); | |
tiles[x + counter, y].GetComponent<BuildingTile>().powerOutIconPrefab = powerOutIconPrefab; | |
} | |
//2,3 | |
if(counter >= 2) | |
{ | |
tiles[x + counter - 2, y + 1].GetComponent<Tile>().setTileType(Tile.tileTypes.Building); | |
tiles[x + counter - 2, y + 1].AddComponent<BuildingTile>(); | |
tiles[x + counter - 2, y + 1].GetComponent<BuildingTile>().powerOutIconPrefab = powerOutIconPrefab; | |
} | |
counter++; | |
} | |
} | |
counter = 0; | |
for (int i = 0; i < numberOfTowns; i++) | |
{ | |
for (int j = 0; j < 8; j++) | |
{ | |
if (counter == 0) | |
{ | |
x = Random.Range(0, gridWidth - 4); | |
y = Random.Range(4, gridHeight - 1); | |
while (validBuildingLocation(x, y, 4, 1) == false) | |
{ | |
x = Random.Range(0, gridWidth - 4); | |
y = Random.Range(4, gridHeight - 1); | |
} | |
} | |
if (counter == 8) | |
{ | |
x = Random.Range(4, gridWidth - 4); | |
y = Random.Range(0, gridHeight - 1); | |
while (validBuildingLocation(x, y, 4, 1) == false) | |
{ | |
x = Random.Range(0, gridWidth - 4); | |
y = Random.Range(4, gridHeight - 1); | |
} | |
counter = 0; | |
} | |
//0,1,2,3 | |
if (counter < 4) | |
{ | |
tiles[x + counter, y].GetComponent<Tile>().setTileType(Tile.tileTypes.Building); | |
tiles[x + counter, y].AddComponent<BuildingTile>(); | |
tiles[x + counter, y].GetComponent<BuildingTile>().powerOutIconPrefab = powerOutIconPrefab; | |
getTile(x + counter, y + 1).GetComponent<Tile>().sunCoverage /= 1.5f; | |
getTile(x + counter, y + 1).GetComponent<Tile>().windSpeed /= 2; | |
} | |
//4,5,6,7 | |
if (counter >= 4) | |
{ | |
tiles[x + counter - 4, y + 1].GetComponent<Tile>().setTileType(Tile.tileTypes.Building); | |
tiles[x + counter - 4, y + 1].AddComponent<BuildingTile>(); | |
tiles[x + counter - 4, y + 1].GetComponent<BuildingTile>().powerOutIconPrefab = powerOutIconPrefab; | |
getTile(x + counter - 4, y + 2).GetComponent<Tile>().sunCoverage /= 1.5f; | |
getTile(x + counter - 4, y + 2).GetComponent<Tile>().windSpeed /= 2; | |
} | |
counter++; | |
} | |
} | |
counter = 0; | |
for (int i = 0; i < numberOfCities; i++) | |
{ | |
for (int j = 0; j < 24; j++) | |
{ | |
if (counter == 0) | |
{ | |
x = Random.Range(0, gridWidth - 8); | |
y = Random.Range(4, gridHeight - 3); | |
while (validBuildingLocation(x, y, 8, 3) == false) | |
{ | |
x = Random.Range(0, gridWidth - 8); | |
y = Random.Range(4, gridHeight - 3); | |
} | |
} | |
if (counter == 24) | |
{ | |
x = Random.Range(4, gridWidth - 8); | |
y = Random.Range(0, gridHeight - 3); | |
while (validBuildingLocation(x, y, 8, 3) == false) | |
{ | |
x = Random.Range(0, gridWidth - 8); | |
y = Random.Range(4, gridHeight - 3); | |
} | |
counter = 0; | |
} | |
//0,1,2,3,4,5,6,7 | |
if (counter < 8) | |
{ | |
tiles[x + counter, y].GetComponent<Tile>().setTileType(Tile.tileTypes.Building); | |
tiles[x + counter, y].AddComponent<BuildingTile>(); | |
tiles[x + counter, y].GetComponent<BuildingTile>().powerOutIconPrefab = powerOutIconPrefab; | |
getTile(x + counter, y + 1).GetComponent<Tile>().sunCoverage /= 1.5f; | |
getTile(x + counter, y + 1).GetComponent<Tile>().windSpeed /= 2; | |
} | |
//8,9,10,11,12,13,14,15 | |
if (counter >= 8 && counter < 16) | |
{ | |
tiles[x + counter - 8, y + 1].GetComponent<Tile>().setTileType(Tile.tileTypes.Building); | |
tiles[x + counter - 8, y + 1].AddComponent<BuildingTile>(); | |
tiles[x + counter - 8, y + 1].GetComponent<BuildingTile>().powerOutIconPrefab = powerOutIconPrefab; | |
getTile(x + counter - 8, y + 2).GetComponent<Tile>().sunCoverage /= 1.5f; | |
getTile(x + counter - 8, y + 2).GetComponent<Tile>().windSpeed /= 2; | |
} | |
if (counter >= 16) | |
{ | |
tiles[x + counter - 16, y + 2].GetComponent<Tile>().setTileType(Tile.tileTypes.Building); | |
tiles[x + counter - 16, y + 2].AddComponent<BuildingTile>(); | |
tiles[x + counter - 16, y + 2].GetComponent<BuildingTile>().powerOutIconPrefab = powerOutIconPrefab; | |
getTile(x + counter - 16, y + 2).GetComponent<Tile>().sunCoverage /= 1.5f; | |
getTile(x + counter - 16, y + 2).GetComponent<Tile>().windSpeed /= 2; | |
} | |
counter++; | |
} | |
} | |
} | |
bool validBuildingLocation(int xPosition, int yPosition, int tilesNeededX, int tilesNeededY) | |
{ | |
for (int i = 0; i < tilesNeededX; i++) | |
{ | |
if (tiles[xPosition + i,yPosition].GetComponent<Tile>().getTileType() == Tile.tileTypes.Building) | |
{ | |
return false; | |
} | |
for (int j = 0; j < tilesNeededY; j++) | |
{ | |
if (tiles[xPosition + i, yPosition + j].GetComponent<Tile>().getTileType() == Tile.tileTypes.Building) | |
{ | |
return false; | |
} | |
} | |
} | |
return true; | |
} | |
//Function to check if the list contains a tile type | |
//Must be passed a tile type based on the prefab name | |
bool doesTileListContains(string prefabName) | |
{ | |
for (int i = 0; i < tileTypesList.Count; i++) | |
{ | |
if(tileTypesList[i].name == prefabName) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
//Function to get the index of a tile type from tileTypesList | |
//Must be passed a tile type based on the prefab name | |
int getIndexOfTile(string prefabName) | |
{ | |
for (int i = 0; i < tileTypesList.Count; i++) | |
{ | |
if (tileTypesList[i].name == prefabName) | |
{ | |
return i; | |
} | |
} | |
return -1; | |
} | |
bool generateMountain(int x, int y) | |
{ | |
if(y < gridHeight/2) | |
{ | |
int randomNumber = Random.Range(0, 11); | |
if(randomNumber <= 8) | |
{ | |
return false; | |
} | |
} | |
return true; | |
} | |
public void clearAllTiles() | |
{ | |
if(tiles == null || tiles.Length == 0) | |
{ | |
fillArray(); | |
} | |
for (int i = 0; i < gridHeight; i++) | |
{ | |
for (int j = 0; j < gridWidth; j++) | |
{ | |
DestroyImmediate(tiles[j, i]); | |
} | |
} | |
tiles = null; | |
#if UNITY_EDITOR | |
EditorSceneManager.SaveScene(SceneManager.GetActiveScene()); | |
#endif | |
} | |
public GameObject getTile(int x, int y) | |
{ | |
if(tiles == null) | |
{ | |
fillArray(); | |
} | |
return tiles[x, y]; | |
} | |
public int getGridWidth() | |
{ | |
return gridWidth; | |
} | |
public int getGridHeight() | |
{ | |
return gridHeight; | |
} | |
public void testArray() | |
{ | |
if(tiles == null) | |
{ | |
Debug.Log("Tiles array is null"); | |
} | |
if(tiles.Length == 0) | |
{ | |
Debug.Log("Tiles array length is 0"); | |
} | |
Debug.Log("Tiles array seems okay"); | |
} | |
public void fillArray() | |
{ | |
tiles = new GameObject[gridWidth, gridHeight]; | |
for (int i = 0; i < gridHeight; i++) | |
{ | |
for (int j = 0; j < gridWidth; j++) | |
{ | |
tiles[j,i] = GameObject.Find("Tiles:" + j + " " + i); | |
} | |
} | |
} | |
public GameObject[,] getTilesArray() | |
{ | |
if(tiles == null || tiles.Length == 0) | |
{ | |
fillArray(); | |
} | |
return tiles; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment