// Converts the top cell to sand if certain criteria are met // This modifies terrain based on neighbor stacks // Thus it should only be called after all cell stacks are generated void AddSand(CellStack cellStack) { if (cellStack.Count() == terrain.waterLevel) { HexCoordinates[] neighbors = cellStack.coordinates.GetNeighbors(); for (int i = 0; i < 6; i++) { CellStack neighbor = GetCellStackFromWorldCoords(neighbors[i]); // The neighbor cell stack might not be in this chunk if (neighbor == null) { TerrainChunk neighborChunk = terrain.GetChunkFromWorldCoords(neighbors[i]); if (neighborChunk != null) { neighbor = neighborChunk.GetCellStackFromWorldCoords(neighbors[i]); } } if (neighbor != null) { if (neighbor.Count() < terrain.waterLevel) { cellStack.Pop(); cellStack.Push(CellType.Sand); break; } } } } }
CellStack CreateCellStack(int x, int z, int height) { CellStack cellStack = ScriptableObject.CreateInstance <CellStack>(); HexCoordinates coords = HexCoordinates.FromOffsetCoordinates(x + (int)offsetOrigin.x, z + (int)offsetOrigin.y); Vector2Int indexWithinChunk = new Vector2Int(x % size, z % size); cellStack.Init(coords, indexWithinChunk); cellStack.Push(CellType.Bedrock); int numStoneTiles = (int)(height * terrain.stoneHeightPercentage); // Generate terrian based on stack height for (int i = 0; i < height; i++) { CellType newCell; if (height >= terrain.waterLevel - 1 && i == height - 1) { newCell = CellType.Grass; } else if (i < numStoneTiles) { newCell = CellType.Stone; } else { newCell = CellType.Dirt; } cellStack.Push(newCell); } if (showCoordinates && gridCanvas != null) { Vector3 position = cellStack.coordinates.ToChunkPosition(); position += HexMetrics.heightVector * (cellStack.Count() + 1); Text label = Instantiate <Text>(terrain.cellLabelPrefab); label.rectTransform.SetParent(gridCanvas.transform, false); label.rectTransform.anchoredPosition3D = new Vector3(position.x, position.z, -position.y); label.text = cellStack.coordinates.ToStringOnSeparateLines(); } return(cellStack); }
// Adds a tree on top of stack if certain criteria are met void AddTree(CellStack cellStack) { if (cellStack.Count() > terrain.waterLevel && (cellStack.Peek() == CellType.Grass || cellStack.Peek() == CellType.Dirt)) { Vector2Int offset = cellStack.indexWithinChunk; Vector3 treePos = transform.position + new Vector3(offset.x * HexMetrics.innerRadius * 2 + offset.y % 2 * HexMetrics.innerRadius, transform.localPosition.y + HexMetrics.height * cellStack.Count(), offset.y * HexMetrics.outerRadius * 1.5f); // Randomly rotate the tree so it looks less uniform float rotation = UnityEngine.Random.Range(0, 359); Vector3 treeRot = new Vector3(0, rotation, 0); TerrainObject tree = GameObject.Instantiate(treePrefab); tree.Init(cellStack.coordinates, offset); tree.transform.SetParent(transform); tree.transform.position = treePos; tree.transform.rotation = Quaternion.Euler(treeRot); terrainObjects[offset.x, offset.y] = tree; } }
void GenerateStackMesh(int x, int z, CellStack stack) { int stackHeight = stack.Count(); Vector2 worldOffset = new Vector2(x + chunk.offsetOrigin.x, z + chunk.offsetOrigin.y); Vector3 center = HexCoordinates.FromOffsetCoordinates(x, z).ToChunkPosition(); center += new Vector3(0, transform.localPosition.y, 0); center += stackHeight * HexMetrics.heightVector; CellType topCell = stack.Peek(); Material topMaterial = getTopMaterial(topCell); List <int> topMaterialSubmesh = getSubmesh(topMaterial); //Generates the horizontal part of the terrain (top of the stack) for (int i = 0; i < 6; i++) { AddTriangleToMesh( center, center + HexMetrics.corners[i], center + HexMetrics.corners[i + 1] ); AddTriangleToSubmesh( topMaterialSubmesh, center, center + HexMetrics.corners[i], center + HexMetrics.corners[i + 1] ); } HexCoordinates[] neighbors = stack.coordinates.GetNeighbors(); Vector3 topCenter = center; //Generates the vertical part of the terrain (sides of the stack) for (int i = 0; i < 6; i++) { center = topCenter; //If we have a neighbor in this direction, check its height //If it is taller than us, ignore it (it will create the vertical wall) //If it is the same height as us, ignore it (we don't need a vertical wall) //If it is shorter than us, create a vertical wall down to its height CellStack neighbor = chunk.GetCellStackFromWorldCoords(neighbors[i]); int neighborHeight = 0; if (neighbor != null) { neighborHeight = neighbor.Count(); } for (int elevation = stackHeight; elevation > neighborHeight; elevation--) { CellType currentCell = stack.PeekAt(elevation - 1); Material sideMaterial = getSideMaterial(currentCell); List <int> sideMaterialSubmesh = getSubmesh(sideMaterial); AddTriangleToMesh( center + HexMetrics.corners[i] - HexMetrics.heightVector, center + HexMetrics.corners[i + 1], center + HexMetrics.corners[i] ); AddTriangleToSubmesh( sideMaterialSubmesh, center + HexMetrics.corners[i] - HexMetrics.heightVector, center + HexMetrics.corners[i + 1], center + HexMetrics.corners[i] ); AddTriangleToMesh( center + HexMetrics.corners[i] - HexMetrics.heightVector, center + HexMetrics.corners[i + 1] - HexMetrics.heightVector, center + HexMetrics.corners[i + 1] ); AddTriangleToSubmesh( sideMaterialSubmesh, center + HexMetrics.corners[i] - HexMetrics.heightVector, center + HexMetrics.corners[i + 1] - HexMetrics.heightVector, center + HexMetrics.corners[i + 1] ); center -= HexMetrics.heightVector; } } }
private void TouchCell(TerrainChunk chunk, HexCoordinates coords) { try { CellStack stack = chunk.GetCellStackFromWorldCoords(coords); ghostCellPrefab.SetActive(true); Vector3 ghostPosition = stack.coordinates.ToWorldPosition(terrain) + HexMetrics.ScaledHeightVector(terrain) * stack.Count(); ghostCellPrefab.transform.localPosition = ghostPosition; } catch (NullReferenceException e) { Debug.LogWarning("Trying to access null cellstack"); } }
void GenerateStackMesh(int x, int z, CellStack stack) { int stackHeight = stack.Count(); Vector2 worldOffset = new Vector2(x + chunk.offsetOrigin.x, z + chunk.offsetOrigin.y); Vector3 center = HexCoordinates.FromOffsetCoordinates(x, z).ToChunkPosition(); center += new Vector3(0, transform.localPosition.y, 0); center += stackHeight * HexMetrics.heightVector; CellType top = stack.Peek(); HexCoordinates[] neighbors = stack.coordinates.GetNeighbors(); for (int i = 0; i < 6; i++) { //Generates the horizontal part of the terrain (top of the stack) AddTriangle( center, center + HexMetrics.corners[i], center + HexMetrics.corners[i + 1] ); //Generates the vertical part of the terrain (sides of the stack) CellStack neighbor = chunk.GetCellStackFromWorldCoords(neighbors[i]); //If we have a neighbor in this direction, check its height //If it is taller than us, ignore it (it will create the vertical wall) //If it is the same height as us, ignore it (we don't need a vertical wall) //If it is shorter than us, create a vertical wall down to its height if (neighbor != null) { int neighborHeight = neighbor.Count(); float wallHeight = (stackHeight - neighborHeight) * HexMetrics.heightVector.y; if (wallHeight > 0) { Vector3 wallHeightVector = new Vector3(0, wallHeight, 0); AddTriangle( center + HexMetrics.corners[i] - wallHeightVector, center + HexMetrics.corners[i + 1], center + HexMetrics.corners[i] ); AddTriangle( center + HexMetrics.corners[i] - wallHeightVector, center + HexMetrics.corners[i + 1] - wallHeightVector, center + HexMetrics.corners[i + 1] ); } } else { AddTriangle( center + HexMetrics.corners[i] - HexMetrics.heightVector * stackHeight, center + HexMetrics.corners[i + 1], center + HexMetrics.corners[i] ); AddTriangle( center + HexMetrics.corners[i] - HexMetrics.heightVector * stackHeight, center + HexMetrics.corners[i + 1] - HexMetrics.heightVector * stackHeight, center + HexMetrics.corners[i + 1] ); } } }