public Part?getPart(AxialCoordinate location) { Part?val = new Part?(); dataTable.TryGetValue(location, out val); return(val); }
private Quaternion axialToRotation(AxialCoordinate location) { // Convert an axial location to the rotation that that GameObject should be at // Step 1: Find all neighboring GameObjects List <AxialCoordinate> neighbors = hexData.getFullHexNeighbors(location); // Step 2: Pick the neighbor with the x+y value closest to 0 as the one to rotate to. This ensures that the part is always facing outwards AxialCoordinate lowestNeighbor = new AxialCoordinate { x = int.MaxValue / 3, y = int.MaxValue / 3 }; foreach (AxialCoordinate neighbor in neighbors) { if (neighbor.x + neighbor.y < lowestNeighbor.x + lowestNeighbor.y) { lowestNeighbor = neighbor; } } //Step 3: Rotate to that neighbor AxialCoordinate neighborNormal = new AxialCoordinate { x = location.x - lowestNeighbor.x, y = location.y - lowestNeighbor.y }; int rotation = hexData.getRotationFromNeighbor(neighborNormal); return(Quaternion.Euler(0, 0, rotation)); }
private bool pathExistsToPlayer(AxialCoordinate location) { // Given a location, find a path that exists from that location back to the player List <AxialCoordinate> visited = new List <AxialCoordinate>(); List <AxialCoordinate> unvisited = new List <AxialCoordinate>(); visited.Add(location); unvisited.AddRange(getFullHexNeighbors(location)); while (!visited.Contains(player) && unvisited.Count > 0) { AxialCoordinate nodeToExpand = unvisited[0]; unvisited.RemoveAt(0); visited.Add(nodeToExpand); foreach (AxialCoordinate neighbor in getFullHexNeighbors(nodeToExpand)) { if (!visited.Contains(neighbor)) { unvisited.Add(neighbor); } } } if (visited.Contains(player)) { return(true); } return(false); }
public List <AxialCoordinate> getFullHexNeighbors(AxialCoordinate location) { List <AxialCoordinate> full = new List <AxialCoordinate>(); if (getPart(location) != null && getPart(location).Value.type == -1) { // Location is a triangle, there's only one possible neighbor! AxialCoordinate?neighbor = getNeighborFromTriangle(location); if (neighbor != null) { full.Add((AxialCoordinate)neighbor); } } else { foreach (AxialCoordinate direction in directions) { AxialCoordinate neighbor = location + direction; if (getPart(neighbor) != null && getPart(neighbor).Value.type != -1) { full.Add(neighbor); } } } return(full); }
public int getRotationFromNeighbor(AxialCoordinate neighborNormal) { // Given a neighborNormal, return the rotation a triangle should be at if (neighborNormal.x == -1 && neighborNormal.y == 0) { return(90); } if (neighborNormal.x == -1 && neighborNormal.y == 1) { return(30); } if (neighborNormal.x == 0 && neighborNormal.y == 1) { return(330); } if (neighborNormal.x == 1 && neighborNormal.y == -1) { return(210); } if (neighborNormal.x == 1 && neighborNormal.y == 0) { return(270); } return(150); }
private Vector3 axialToPixel(AxialCoordinate location) { // Convert the axial position of the location to a pixel location float x; float y; x = size * Mathf.Sqrt(3f) * (location.x + location.y / 2f); y = size * (3f / 2f) * location.y; return(new Vector3(x + player.shape.transform.position.x, y + player.shape.transform.position.y, 0)); }
public bool addRandomPart(string part = "None") { int maxCount = hexData.dataTable.Count; int counter = 0; // Get a random location foreach (AxialCoordinate location in RandomKeys(hexData.dataTable)) { if (counter > maxCount) { return(false); } counter++; if (hexData.getPart(location) == null) { continue; } if (hexData.getPart(location).Value.type == -1) { continue; } List <AxialCoordinate> randLocations = hexData.getEmptyNeighbors(location); System.Random rnd = new System.Random(); if (part == "None") { part = "Triangle"; if (Random.Range(0, 2) == 1) { part = "Hexagon"; } } // Ensure that adding this part doesn't exceed the max allowed per hexagon int localMaxNeighbors; localMaxNeighbors = maxNeighbors; if (part == "Triangle") { localMaxNeighbors -= 1; } if (hexData.getFullNeighbors(location).Count >= localMaxNeighbors) { continue; } int size = randLocations.Count; AxialCoordinate randomSpot = randLocations[rnd.Next(size)]; addPart(randomSpot, part); return(true); } return(false); }
public bool addPart(AxialCoordinate location, Part?part) { // Returns true if the part was successfully added if (checkPart(location)) { dataTable[location] = part; } else { return(false); } return(true); }
public bool checkPart(AxialCoordinate location) { // Check that a part can be added to the location provided. Will return true if: // 1. location has no parts already attached // 2. a path exists from location to player if (pathExistsToPlayer(location) && getPart(location) == null) { return(true); } else { return(false); } }
public void removePart(AxialCoordinate location) { try { PhotonView destroyedObject = PhotonView.Get(((Part)hexData.getPart(location)).shape); PhotonNetwork.Destroy(destroyedObject); } catch { Debug.Log("Could not destroy Photon GameObject"); } hexData.removePart(location); }
public List <AxialCoordinate> getEmptyNeighbors(AxialCoordinate location) { List <AxialCoordinate> empty = new List <AxialCoordinate>(); if (getPart(location).Value.type == -1) { return(empty); // triangles don't have any empty neighbors } foreach (AxialCoordinate direction in directions) { AxialCoordinate neighbor = location + direction; if (getPart(neighbor) == null) { empty.Add(neighbor); } } return(empty); }
public List <AxialCoordinate> getFullNeighbors(AxialCoordinate location) { List <AxialCoordinate> full = new List <AxialCoordinate>(); if (getPart(location).Value.type == -1) { full.Add((AxialCoordinate)getNeighborFromTriangle(location)); return(full); } foreach (AxialCoordinate direction in directions) { AxialCoordinate neighbor = location + direction; if (getPart(neighbor) != null) { full.Add(neighbor); } } return(full); }
void OnCollisionEnter2D(Collision2D collision) { // Each player handles their own collisions, so only handle collisions for the local player if (!photonView.isMine) { return; } // Check if collision was with a triangle part, either a player's or an AI enemy's if (collision.collider.gameObject.tag == "Triangle" || collision.collider.gameObject.tag == "EnemyAttackingPart") { // Getting part adder class PartAdder partAdder = GameObject.FindGameObjectWithTag("PartAdder").GetComponent <PartAdder> (); // Gets the axialcoord of the object to destroy AxialCoordinate locationOfObject = partAdder.hexData.getLocation(this.gameObject.transform.position); List <AxialCoordinate> listToDestroy = partAdder.hexData.findDestroyedPartLocations(locationOfObject); // Only add points to attacker if attacked by player, not AI enemy if (collision.collider.gameObject.tag == "Triangle") { // Update score/points for attacking player PhotonView attackingView = PhotonView.Get(collision.collider.gameObject.transform.parent.gameObject); // Convert list to string data stream, as Photon cannot serialize lists var binFormatter = new BinaryFormatter(); var mStream = new MemoryStream(); binFormatter.Serialize(mStream, listToDestroy); var data = Convert.ToBase64String(mStream.GetBuffer()); // Send data to attacking player using RPC call attackingView.RPC("updateLocalPointsList", PhotonPlayer.Find(attackingView.owner.ID), data); } // Destroy appropriate parts for the collision foreach (AxialCoordinate location in listToDestroy) { partAdder.removePart(location); } } }
public AxialCoordinate getLocation(Vector3 location) { // Given a pixel coordinate, return the AxialCoordinate location of the closest part float minDistance = float.MaxValue; AxialCoordinate minCoordinate = player; foreach (KeyValuePair <AxialCoordinate, Part?> part in dataTable) { if (part.Value != null) { float distance = Vector3.Distance(location, part.Value.Value.shape.transform.position); if (distance < minDistance) { minDistance = distance; minCoordinate = part.Key; } } } return(minCoordinate); }
public List <AxialCoordinate> findDestroyedPartLocations(AxialCoordinate destroyedPartLocation) { List <AxialCoordinate> destroyedLocations = new List <AxialCoordinate>(); // Temporarily destroy the part Part?tempPart = getPart(destroyedPartLocation); removePart(destroyedPartLocation); // Search all parts to see if path is present foreach (AxialCoordinate partLocation in dataTable.Keys) { if (!pathExistsToPlayer(partLocation)) { destroyedLocations.Add(partLocation); } } // Restore the destroyed part addPart(destroyedPartLocation, tempPart); destroyedLocations.Add(destroyedPartLocation); return(destroyedLocations); }
public void addPart(AxialCoordinate location, string part) { // NOTE: type = 1 if player part. type = 0 if hexagon part. type = -1 if triangle part // Add a part to both the PartData, and the PhotonNetwork using Instantiate GameObject partType; int type; if (part == "Hexagon") { partType = hexagonPart; type = 0; } else if (part == "Triangle") { partType = trianglePart; type = -1; } else if (part == "Player") { partType = hexagonPart; type = 1; } else { Debug.LogError("Unknown part added: " + part); return; } // Freeze the player until the part has been added Vector3 playerLocation = player.shape.transform.position; Quaternion playerRotation = player.shape.transform.rotation; player.shape.transform.position = Vector3.zero; player.shape.transform.rotation = Quaternion.Euler(Vector3.zero); if (hexData.checkPart(location)) { // Only add axial rotation if the part is a triangle Quaternion rotation = player.shape.transform.rotation; if (type == -1) { rotation *= axialToRotation(location); } // Instantiate a new part GameObject newPart = PhotonNetwork.Instantiate(partType.name, axialToPixel(location), rotation, 0); // Add the part as a child of the player hexagon newPart.transform.parent = player.shape.transform; Part addedPart = new Part { shape = newPart, type = type }; hexData.addPart(location, addedPart); /*Notify replay manager that part has been added*/ EventManager.pushEventDataFloat("partadded", newPart.transform.position.z); EventManager.pushEventDataFloat("partadded", newPart.transform.position.y); EventManager.pushEventDataFloat("partadded", newPart.transform.position.x); EventManager.triggerEvent("partadded"); } // Return the player to their position before the part was added player.shape.transform.position = playerLocation; player.shape.transform.rotation = playerRotation; }
public void removePart(AxialCoordinate location) { // Remove a part dataTable[location] = null; }
public AxialCoordinate?getNeighborFromTriangle(AxialCoordinate position) { // Returns a hexagon attached to the triangle at position. Returns null if error if (getPart(position).Value.type != -1) { return(null); } int rotation = ((int)(dataTable[position].Value.shape.transform.localRotation.eulerAngles.z) + 180) % 360; AxialCoordinate neighbor; // Given a rotation (ie used for triangle), get the neighbor attached to that part if (rotation == 90) { neighbor = new AxialCoordinate { x = -1, y = 0 } } ; else if (rotation == 30) { neighbor = new AxialCoordinate { x = -1, y = 1 } } ; else if (rotation == 330) { neighbor = new AxialCoordinate { x = 0, y = 1 } } ; else if (rotation == 210) { neighbor = new AxialCoordinate { x = 1, y = -1 } } ; else if (rotation == 270) { neighbor = new AxialCoordinate { x = 1, y = 0 } } ; else { neighbor = new AxialCoordinate { x = 0, y = -1 } }; if (getPart(position + neighbor) != null) { return(position + neighbor); } return(null); } }