/// <summary> /// Creates the improvement GameObject and switches the hex texture. /// </summary> /// <param name="hex">Hex to create the improvement on</param> /// <param name="i">Improvement to add</param> private void InitiateImprovementsOnHexs(Hex hex, Improvement i) { //get the parent chunk object; this is where we will parent the improvement objects to GameObject resourceHolder = hex.parentChunk.gameObject; if (resourceHolder == null) { Debug.LogError("Could not find the resource holder!"); } //remove current improvements Destroy(hex.iObject); //remove current resource gameobjects Destroy(hex.rObject); //switch the hex's texture to this improvement's ground texture hex.ChangeTextureToImprovement(); //spawn gameObject if there is a mesh to spawn if (i.meshToSpawn != null) { float y = (hex.worldPosition.y + hex.hexExt.y) - ((hex.hexExt.y) / 5f); if (y == 0) { y -= ((hex.worldPosition.y + hex.hexExt.y) / Random.Range(4, 8)); } GameObject holder = new GameObject(i.name + " at " + hex.AxialCoordinates, typeof(MeshFilter), typeof(MeshRenderer)); holder.GetComponent<MeshFilter>().mesh = hex.currentImprovement.meshToSpawn; holder.transform.position = new Vector3((hex.worldPosition.x + hex.hexCenter.x + Random.Range(-0.2f, 0.2f)), y, (hex.worldPosition.z + hex.hexCenter.z + Random.Range(-0.2f, 0.2f))); holder.transform.rotation = Quaternion.identity; holder.renderer.material.mainTexture = i.meshTexture; holder.transform.parent = hex.parentChunk.transform; hex.iObject = holder; } }
void OnHexClick(Hex hex, int mouseButton) { if(mouseButton == 0) { Debug.Log( "nya" ); worldManager.improvementManager.TestedAddImprovementToTile(hex, 0); } if(mouseButton == 1) { worldManager.improvementManager.RemoveImprovementFromTile(hex); } }
/// <summary> /// Checks all rules in the rule list. /// </summary> /// <param name="hex">Hex to compare the rules upon</param> /// <param name="rule">Rules to check</param> /// <param name="tileManager">The scene tile manager</param> /// <returns>If the hex passed the tests</returns> public static bool Test(Hex hex, HexRule rule, TileManager tileManager) { //check tile rules for (int i = 0; i < rule.possibleTiles.Length; i++) { //if the hex's tile type is in the list of possible tiles, break out of the loop and check features if (TestRule(hex, tileManager.tiles[rule.possibleTiles[i]]) == true) { break; } //the hex's tile type was not in the list of possible tiles, return false if (i == (rule.possibleTiles.Length - 1)) { return false; } } //check feature rules for (int i = 0; i < rule.possibleFeatures.Length; i++) { //if hex's feature type is in the list of possible features, return true since both rules have been passed if (TestRule(hex, rule.possibleFeatures[i]) == true) { return true; } //the hex's feature type was not in the list of possible features, return false if (i == (rule.possibleFeatures.Length - 1)) { return false; } } //unreachable mandatory code because c# is funky return false; }
public void ClearBorders(Hex[] hexes) { foreach(Hex h in hexes) { h.ClearBorder(); } }
public void SetBorders(Hex[] hexes, int borderID) { foreach(Hex h in hexes) { h.SetBorder(borderID); } }
/* void CalculateDistance() { int dx = Mathf.Abs(Mathf.RoundToInt(goToHex.x - currentHex.x)); int dy = Mathf.Abs(Mathf.RoundToInt(goToHex.y - currentHex.y)); int dz = Mathf.Abs(Mathf.RoundToInt(goToHex.z - currentHex.z)); int distanceA = Mathf.Max(dx, dy, dz); int distanceB = Mathf.Abs(distanceA - Mathf.Abs(Mathf.RoundToInt(mapSize.x + dx))); if (distanceA == distanceB) { distance = distanceA; } else { distance = Mathf.Min(distanceA, distanceB); } } int CalculateDistance(HexInfo start, HexInfo end) { int dx = Mathf.Abs(Mathf.RoundToInt(start.CubeGridPosition.x - end.CubeGridPosition.x)); int dy = Mathf.Abs(Mathf.RoundToInt(start.CubeGridPosition.y - end.CubeGridPosition.y)); int dz = Mathf.Abs(Mathf.RoundToInt(start.CubeGridPosition.z - end.CubeGridPosition.z)); int distanceA = Mathf.Max(dx, dy, dz); int distanceB = Mathf.Abs(distanceA - Mathf.Abs(Mathf.RoundToInt(mapSize.x + dx))); if (distanceA == distanceB) { return distanceA; } else { return Mathf.Min(distanceA, distanceB); } } void OnGUI() { //GUI.Label(new Rect(20, 0, 100, 20), goToHex.ToString()); //GUI.Label(new Rect(20, 30, 100, 20), distance.ToString("Distance: #.")); } */ // Added public IEnumerator RefreshBorders(Hex modifiedHex) { Chunk originalChunk = modifiedHex.parentChunk; Chunk[] possibleChunks = FindPossibleChunks(originalChunk); foreach (Chunk chunk in possibleChunks) { foreach (Hex hex in chunk.hexArray) { // Have to make every hex update their border texture and value hex.UpdateBorder(); } chunk.RegenerateMesh(); yield return new WaitForEndOfFrame(); } }
/// <summary> /// Check if the hex's tile type is the provided tile /// </summary> /// <param name="hex">Hex to compare to the tile</param> /// <param name="tile">Tile to compare to the hex</param> /// <returns></returns> private static bool TestRule(Hex hex, Tile tile) { if (hex.terrainType == tile) { return true; } else { return false; } }
/// <summary> /// Check if the hex's feature type is the provided feature /// </summary> /// <param name="hex">Hex to compare to the feature</param> /// <param name="feature">Feature to compare to the hex</param> /// <returns></returns> private static bool TestRule(Hex hex, Feature feature) { if (hex.terrainFeature == feature) { return true; } else { return false; } }
/// <summary> /// Spawns the provided resource on the tile. /// Optional to regenerate the chunk. /// </summary> /// <remarks> /// This can be used to force a resource to spawn, even if against it's rules. /// </remarks> /// <param name="hex">Hex to spawn the resource on</param> /// <param name="r">Resource to spawn</param> /// <param name="regenerateChunk">If the parent chunk should be regenerated</param> public void SpawnResource(Hex hex, Resource r, bool regenerateChunk) { //reset resource locations hex.resourceLocations.Clear(); //destroy previous resource objects if (hex.rObject != null) { Destroy(hex.rObject); } //if the resource has a mesh to spawn if (r.meshToSpawn != null) { //calculate y position to spawn the resources float y; if (hex.localMesh == null) { y = (worldManager.hexExt.y); if (y == 0) { y -= ((hex.worldPosition.y + worldManager.hexExt.y) / Random.Range(4, 8)); } else { y = hex.worldPosition.y + worldManager.hexExt.y + hex.currentResource.meshToSpawn.bounds.extents.y; } } else { y = (hex.localMesh.bounds.extents.y); if (y == 0) { y -= ((hex.worldPosition.y + hex.localMesh.bounds.extents.y) / Random.Range(4, 8)); } else { y = hex.worldPosition.y + hex.localMesh.bounds.extents.y + hex.currentResource.meshToSpawn.bounds.extents.y; } } //spawn a resource for each spawn amount for (int i = 0; i < r.meshSpawnAmount; i++) { //position setting float x = (worldManager.hexCenter.x + Random.Range(-0.2f, 0.2f)); float z = (worldManager.hexCenter.z + Random.Range(-0.2f, 0.2f)); hex.resourceLocations.Add(new Vector3(x, y, z)); } //number of resources int size = hex.resourceLocations.Count; //number of resources to combine if (size > 0) { //combine instances CombineInstance[] combine = new CombineInstance[size]; Matrix4x4 matrix = new Matrix4x4(); matrix.SetTRS(Vector3.zero, Quaternion.identity, Vector3.one); //skip first combine instance due to presetting for (int k = 0; k < size; k++) { combine[k].mesh = hex.currentResource.meshToSpawn; matrix.SetTRS(hex.resourceLocations[k], Quaternion.identity, Vector3.one); combine[k].transform = matrix; } //create gameobject to hold the resource meshes GameObject holder = new GameObject(r.name + " at " + hex.AxialCoordinates, typeof(MeshFilter), typeof(MeshRenderer)); //set the gameobject position to the hex position holder.transform.position = hex.worldPosition; holder.transform.parent = hex.parentChunk.transform; //set the resource mesh texture holder.renderer.material.mainTexture = r.meshTexture; //assign the combined mesh to the resource holder gameobject MeshFilter filter = holder.GetComponent<MeshFilter>(); filter.mesh = new Mesh(); filter.mesh.CombineMeshes(combine); //set the hex's resource object to the resource holder hex.rObject = holder; //UV mapping Rect rectArea; worldManager.textureAtlas.resourceLocations.TryGetValue(r, out rectArea); //temp UV data Vector2[] uv; uv = new Vector2[filter.mesh.vertexCount]; //calculate the combined UV data for (int i = 0; i < filter.mesh.vertexCount; i++) { uv[i] = new Vector2(filter.mesh.uv[i].x * rectArea.width + rectArea.x, filter.mesh.uv[i].y * rectArea.height + rectArea.y); } //assign the resource holder's UV data filter.mesh.uv = uv; } } //if needed; regenerate the chunk and it's UV data if (regenerateChunk) { hex.ChangeTextureToResource(); hex.parentChunk.RegenerateMesh(); } }
public void Update() { //selected = currentLocation.isSelected; if (currentLocation != null) { currentLocation.currentUnit = this; } //if we are selected if (selected) { //pressed "m" while we are selected to move? if (Input.GetButtonDown("Move")) { //toggle move mode if (moveMode == false) { moveMode = true; } else { moveMode = true; } } //if we are in move mode if (moveMode) { //create ray from camera ray = Camera.main.ScreenPointToRay(Input.mousePosition); //cast raycast to find disired movement grid if (Physics.Raycast(ray, out hit, 100f)) { //get obj reference to hit obj GameObject obj = hit.collider.gameObject; //is it a tile? if (obj.CompareTag("Tile")) { //have we click on this tile to move our unit? if (Input.GetMouseButtonDown(0)) { //since its a tile get the Hex script //TODO: FIX Hex hex = new Hex();//obj.GetComponent<HexInfo>(); //check to see if tile is occupied if (hex.currentUnit == null) { //unlink from current obj moveMode = false; selected = false; int movesNeeded = MovesToCompleteAction(); if (movesNeeded <= movesLeft) { print("Moving to tile: " + hex.AxialCoordinates); //actually move the unit Move(currentLocation, hex, true); movesLeft -= movesNeeded; } else { print("too far to move"); } } else { //add combat or unit switching here(in the child class) //make sure we dont attack ourselves!!! if (hex.currentUnit != (Melee)this) { //unlink from current obj moveMode = false; selected = false; print("attacking"); Attack((Melee)hex.currentUnit); } } } } } } } if (health <= 0) { GameManager.worldEvent.Invoke("Death", "Unit " + gameObject.name + " has been killed!"); currentLocation.currentUnit = null; Destroy(this.gameObject); } }
public void Move(Hex fromTile, Hex toTile, bool quickMove) { if (quickMove) { //find our obj reference to the needed grid GameObject hex = GameObject.Find("HexTile " + toTile.AxialCoordinates); //tell old tile we are no longer on it fromTile.currentUnit = null; //move unit gameObject.transform.position = new Vector3(hex.transform.position.x, (hex.transform.position.y + hex.collider.bounds.extents.y), hex.transform.position.z); //set current location currentLocation = toTile; } else { //CalculateFastestPath(fromTile.gridPosition, toTile.gridPosition); } }
/// <summary> /// Removes the improvement from the specified hex and restores its past state. /// </summary> /// <param name="hex">Hex to remove all improvements from</param> /// <example> /// The following code removes all improvements from the map. /// <code> /// using System; /// using UnityEngine; /// using CivGrid; /// /// public class ExampleClass : MonoBehaviour /// { /// WorldManager worldManager; /// ImprovementManager improvementManager; /// /// void Start() /// { /// worldManager = GameObject.FindObjectOfType<WorldManager>(); /// improvementManager = GameObject.FindObjectOfType<ImprovementManager>(); /// /// //check again for each hex if it should spawn a resource /// foreach (HexChunk chunk in worldManager.hexChunks) /// { /// foreach (HexInfo hex in chunk.hexArray) /// { /// //tries to add first improvement /// improvementManager.RemoveImprovementFromTile(hex); /// } /// } /// } /// } /// </code> /// </example> public void RemoveImprovementFromTile(Hex hex) { if (hex.currentImprovement != null) { if (hex.currentImprovement.name != "None") { //change texture of this hexagon back to its original if it has a resource it will be corrected below hex.ChangeTextureToNormalTile(); //destory improvement children Destroy(hex.iObject); //respawn resource model if (hex.currentResource.name != "None") { hex.resourceManager.SpawnResource(hex, hex.currentResource, true); } } } //return "None" hex.currentImprovement = improvements[0]; }
/// <summary> /// Adds improvement to specified hex if it meets the rule requirements. /// </summary> /// <param name="hex">Hex to attempt to add the improvement upon</param> /// <param name="improvementIndex">Index of the improvement within the improvement manager to attemp to add</param> /// <example> /// The following code attempts to add the first improvement to every tile. /// <code> /// using System; /// using UnityEngine; /// using CivGrid; /// /// public class ExampleClass : MonoBehaviour /// { /// WorldManager worldManager; /// ImprovementManager improvementManager; /// /// void Start() /// { /// worldManager = GameObject.FindObjectOfType<WorldManager>(); /// improvementManager = GameObject.FindObjectOfType<ImprovementManager>(); /// /// //check again for each hex if it should spawn a resource /// foreach (HexChunk chunk in worldManager.hexChunks) /// { /// foreach (HexInfo hex in chunk.hexArray) /// { /// //tries to add first improvement /// improvementManager.TestedAddImprovementToTile(hex, 0); /// } /// } /// } /// } /// </code> /// </example> /// <remarks> /// The index system should be based off of the inspector indexes at startup. The automatically generated "None" improvement /// is not included in the index numbering. /// </remarks> public void TestedAddImprovementToTile(Hex hex, int improvementIndex) { //if it's possible to spawn the improvement according to it's rules bool possible = false; //gets improvement from it's index Improvement improvement = improvements[improvementIndex+1]; //runs through the tests and if any return false, we can not spawn the improvement if (RuleTest.Test(hex, improvement.rule, tileManager)) { possible = true; } else { possible = false; } //spawn the improvement on the tile if (possible) { hex.currentImprovement = improvement; hex.parentChunk.worldManager.improvementManager.InitiateImprovementsOnHexs(hex, improvement); } }
public Hex[] GetNeighborsOfHex(Hex centerTile) { int[] d; Hex[] neighbors = new Hex[6]; Vector2 neighborOffsetGridPos = new Vector2(0, 0); int parity = (int)centerTile.OffsetCoordinates.y & 1; for (int i = 0; i < 6; i++) { d = offsetNeighbors[parity][i]; neighborOffsetGridPos.x = centerTile.OffsetCoordinates.x + d[0]; neighborOffsetGridPos.y = centerTile.OffsetCoordinates.y + d[1]; neighbors[i] = GetHexFromOffsetCoordinates(neighborOffsetGridPos); } return neighbors; }
/// <summary> /// Spawns the provided resource on the tile. /// Optional to regenerate the chunk. /// </summary> /// <remarks> /// This can be used to force a resource to spawn, even if against it's rules. /// </remarks> /// <param name="hex">Hex to spawn the resource on</param> /// <param name="r">Resource to spawn</param> /// <param name="regenerateChunk">If the parent chunk should be regenerated</param> public void SpawnResource(Hex hex, Resource r, bool regenerateChunk) { //reset resource locations hex.resourceLocations.Clear(); //destroy previous resource objects if (hex.rObject != null) { Destroy(hex.rObject); } //if the resource has a mesh to spawn if (r.meshToSpawn != null) { //calculate y position to spawn the resources float y; if (hex.localMesh == null) { y = (worldManager.hexExt.y); if (y == 0) { y -= ((hex.worldPosition.y + worldManager.hexExt.y) / Random.Range(4, 8)); } else { y = hex.worldPosition.y + worldManager.hexExt.y + hex.currentResource.meshToSpawn.bounds.extents.y; } } else { y = (hex.localMesh.bounds.extents.y); if (y == 0) { y -= ((hex.worldPosition.y + hex.localMesh.bounds.extents.y) / Random.Range(4, 8)); } else { y = hex.worldPosition.y + hex.localMesh.bounds.extents.y + hex.currentResource.meshToSpawn.bounds.extents.y; } } //spawn a resource for each spawn amount for (int i = 0; i < r.meshSpawnAmount; i++) { //position setting float x = (worldManager.hexCenter.x + Random.Range(-0.2f, 0.2f)); float z = (worldManager.hexCenter.z + Random.Range(-0.2f, 0.2f)); hex.resourceLocations.Add(new Vector3(x, y, z)); } //number of resources int size = hex.resourceLocations.Count; //number of resources to combine if (size > 0) { //combine instances CombineInstance[] combine = new CombineInstance[size]; Matrix4x4 matrix = new Matrix4x4(); matrix.SetTRS(Vector3.zero, Quaternion.identity, Vector3.one); //skip first combine instance due to presetting for (int k = 0; k < size; k++) { combine[k].mesh = hex.currentResource.meshToSpawn; matrix.SetTRS(hex.resourceLocations[k], Quaternion.identity, Vector3.one); combine[k].transform = matrix; } //create gameobject to hold the resource meshes GameObject holder = new GameObject(r.name + " at " + hex.AxialCoordinates, typeof(MeshFilter), typeof(MeshRenderer)); //set the gameobject position to the hex position holder.transform.position = hex.worldPosition; holder.transform.parent = hex.parentChunk.transform; //set the resource mesh texture holder.GetComponent <Renderer>().material.mainTexture = r.meshTexture; //assign the combined mesh to the resource holder gameobject MeshFilter filter = holder.GetComponent <MeshFilter>(); filter.mesh = new Mesh(); filter.mesh.CombineMeshes(combine); //set the hex's resource object to the resource holder hex.rObject = holder; //UV mapping Rect rectArea; worldManager.textureAtlas.resourceLocations.TryGetValue(r, out rectArea); //temp UV data Vector2[] uv; uv = new Vector2[filter.mesh.vertexCount]; //calculate the combined UV data for (int i = 0; i < filter.mesh.vertexCount; i++) { uv[i] = new Vector2(filter.mesh.uv[i].x * rectArea.width + rectArea.x, filter.mesh.uv[i].y * rectArea.height + rectArea.y); } //assign the resource holder's UV data filter.mesh.uv = uv; } } //if needed; regenerate the chunk and it's UV data if (regenerateChunk) { hex.ChangeTextureToResource(); hex.parentChunk.RegenerateMesh(); } }
public Hex GetOffsetNeighbour(Hex centreTile, int addedX, int addedY) { int parity = (int)centreTile.OffsetCoordinates.y & 1; Vector2 neighbourOffsetGridPos = new Vector2(centreTile.OffsetCoordinates.x + (addedY == 0 ? addedX : (addedX + parity)), centreTile.OffsetCoordinates.y + addedY); return GetHexFromOffsetCoordinates(neighbourOffsetGridPos); }
/// <summary> /// Checks if a resource should be spawned on a hexagon. /// </summary> /// <param name="hex">The hexagon to check</param> /// <example> /// The following code changes the possible resources and then re-checks each hex for the resource. /// <code> /// using System; /// using UnityEngine; /// using CivGrid; /// /// public class ExampleClass : MonoBehaviour /// { /// WorldManager worldManager; /// ResourceManager resourceManager; /// /// void Start() /// { /// worldManager = GameObject.FindObjectOfType<WorldManager>(); /// resourceManager = GameObject.FindObjectOfType<ResourceManager>(); /// /// //creates a new resource to possibly spawn /// resourceManager.AddResource(new Resource("SpecialNewResource", 15, 1, null, null, false, new HexRule(new int[] { 3, 4 }, new Feature[] { Feature.Flat }))); /// /// //check again for each hex if it should spawn a resource /// foreach (HexChunk chunk in worldManager.hexChunks) /// { /// foreach (HexInfo hex in chunk.hexArray) /// { /// resourceManager.CheckForResource(hex); /// } /// } /// } /// } /// </code> /// </example> public void CheckForResource(Hex hex) { //loop through all resources for (int i = 0; i < internalResources.Length; i++) { //get each resource and check if we can spawn them Resource r = internalResources[i]; if (r.rule != null) { //runs through the tests and if any return false, we can not spawn this resource; check the next if (RuleTest.Test(hex, r.rule, tileManager)) { //we can spawn it, but should we? int number = (int)Random.Range(0, r.rarity); if (number == 0) { //spawn resource hex.currentResource = r; SpawnResource(hex, hex.currentResource, false); return; } } } } //no resource spawned; return "None" hex.currentResource = internalResources[0]; }