/// <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);
        }
Exemplo n.º 3
0
        /// <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();
                    }
                }
            }
        }
Exemplo n.º 5
0
 public static void SetVD(VerticalDecomposition vd)
 {
     verticalDecomposition = vd;
 }