/// <summary> /// Check if the current solution is correct by checking if every sheep is within the correct area /// </summary> /// <param name="vd">The vertical decomposition</param> /// <returns>Number of wrong sheep</returns> public int CheckSolution(VerticalDecomposition vd) { int wrong = 0; foreach (GameObject sheep in this.m_sheep) { Vector2 sheep_pos = new Vector2(sheep.transform.position.x, sheep.transform.position.y); // Check if the owner of the area that the sheep is located in is equal to the sheeps owner Trapezoid trap = vd.Search(sheep_pos); Face area = trap.bottom.face; // Debug.Log("Face corresponding to the area of the sheep position: " + area + "\nArea owner: " + area.owner + "\n" + trap.show()); if (area.owner != sheep.GetComponent <OwnerScript>().GetOwner()) { wrong += 1; } } Debug.LogAssertion("The current solution is " + (wrong == 0 ? "correct!" : "wrong!") + "\n" + (this.m_sheep.Count - wrong) + " out of " + this.m_sheep.Count + " correct"); // Update shepherd count text UpdateText(wrong); continueButton.SetActive(wrong == 0); return(wrong); }
// Random endless level generation // Determines the amount of shepherds placed based on the current level number private ShepherdLevel CreateEndlessLevel(int level) { // create the output scriptable object var asset = ScriptableObject.CreateInstance <ShepherdLevel>(); // place the shepherds and sheep randomly List <Vector2> shepherds = RandomPos(level + 4); List <Vector2> sheep = RandomPos(2 * (level + 4)); // Print locations string sls = "Shepherd locations: \n"; foreach (Vector2 v in shepherds) { sls += "(" + v.x + ", " + v.y + "), "; } Debug.Log(sls); string shls = "Sheep locations: \n"; foreach (Vector2 v in sheep) { shls += "(" + v.x + ", " + v.y + "), "; } Debug.Log(shls); // Construct the voronoi diagram corresponding to the shepherd locations StartVoronoi(); foreach (Vector2 me in shepherds) { // Add vertex to the triangulation and update the voronoi Delaunay.AddVertex(m_delaunay, me); m_delaunay.SetOwner(me, Random.Range(0, 4)); m_dcel = Voronoi.Create(m_delaunay); } // Create vertical decomposition VerticalDecomposition vd = VertDecomp(m_dcel); // Use the vertical decomposition to determine the ownership of each sheep // and add the sheep to the level foreach (Vector2 s in sheep) { Trapezoid trap = vd.Search(s); Face area = trap.bottom.face; int i = area.owner; asset.addSheep(s, i); } // Normalize coordinates var rect = BoundingBoxComputer.FromPoints(asset.SheepList); asset.SheepList = Normalize(rect, 6f, asset.SheepList); // Set shepherd budget asset.setBudget(shepherds.Count); return(asset); }
/// <summary> /// Draw the vertical decomposition vd /// </summary> /// <param name="vd"></param> public static void DrawVD(VerticalDecomposition vd) { GL.Begin(GL.LINES); GL.Color(Color.cyan); foreach (Trapezoid t in vd.traps) { // only need to draw left bounds since very rightmost is always out of frame var l1 = intersect(t.top, t.left); var l2 = intersect(t.bottom, t.left); GL.Vertex3(l1.x, l1.y, 0); GL.Vertex3(l2.x, l2.y, 0); } GL.End(); }
// Handle inputs each frame void Update() { if (Input.GetKeyDown("c")) { VoronoiDrawer.CircleOn = !VoronoiDrawer.CircleOn; } if (Input.GetKeyDown("e")) { VoronoiDrawer.EdgesOn = !VoronoiDrawer.EdgesOn; } if (Input.GetKeyDown("v")) { VoronoiDrawer.VoronoiOn = !VoronoiDrawer.VoronoiOn; } // Handle mouse clicks if (Input.GetMouseButtonUp(0)) // LMB was clicked this frame { // Cast a ray, get everything it hits RaycastHit2D[] hit = Physics2D.RaycastAll(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero, Mathf.Infinity); if (hit.Length > 0) // If we hit something { // Grab the top hit GameObject GameObject lastHitObject = hit[hit.Length - 1].collider.gameObject; // If a shepherd was clicked, remove it if (lastHitObject.name == "shepherd(Clone)") { m_shepherds.Remove(lastHitObject); // remove from shepherd clone list shepherdLocs.Remove(lastHitObject.transform.position); // remove location from list Destroy(lastHitObject); // Create new Delaunay triangulation m_delaunay = Delaunay.Create(); foreach (KeyValuePair <Vector2, int> o in shepherdLocs) { Delaunay.AddVertex(m_delaunay, o.Key); m_delaunay.SetOwner(o.Key, o.Value); } // Create new Voronoi diagram m_dcel = Voronoi.Create(m_delaunay); VoronoiDrawer.setDCEL(m_dcel); // Create vertical decomposition and check solution if (shepherdLocs.Count > 0) { VerticalDecomposition vd = VertDecomp(m_dcel); Debug.LogAssertion("The current solution is " + (CheckSolution(vd) == 0 ? "correct!" : "wrong!")); VoronoiDrawer.SetVD(vd); } else { // If we do not have any shepherds, do not create vertical decomposition // Solution without shepherds is always wrong Debug.LogAssertion("The current solution is wrong!"); continueButton.SetActive(false); UpdateText(m_sheep.Count); } // Update Voronoi drawing UpdateMesh(); } } else // LMB was clicked on empty space { // Add shepherd at mouse location var mousePos = Input.mousePosition; if (!EventSystem.current.IsPointerOverGameObject() && shepherdLocs.Count < budget) { mousePos.z = 2.0f; var objectPos = Camera.main.ScreenToWorldPoint(mousePos); var obj = Instantiate(m_shepherdPrefab, objectPos, Quaternion.identity); SpriteRenderer sr = obj.GetComponent <SpriteRenderer>(); sr.color = Colors[m_activeShepherd]; // The new vertex var me = new Vector2(objectPos.x, objectPos.y); // store owner of vertex shepherdLocs.Add(me, m_activeShepherd); m_shepherds.Add(obj); // Add vertex to the triangulation Delaunay.AddVertex(m_delaunay, me); m_delaunay.SetOwner(me, m_activeShepherd); // Update Voronoi m_dcel = Voronoi.Create(m_delaunay); VoronoiDrawer.setDCEL(m_dcel); // Create vertical decomposition and check solution VerticalDecomposition vd = VertDecomp(m_dcel); CheckSolution(vd); // Update VD in drawer VoronoiDrawer.SetVD(vd); // Update Voronoi drawing UpdateMesh(); } } } }
public static void SetVD(VerticalDecomposition vd) { verticalDecomposition = vd; }