// 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> /// Computes bounding rectangle around the face /// </summary> /// <param name="margin"></param> /// <returns></returns> public Rect BoundingBox(float margin = 0f) { if (IsOuter) { throw new GeomException("Bounding box is ill-defined for outer face"); } return(BoundingBoxComputer.FromPoints(OuterVertices.Select(x => x.Pos), margin)); }
public void FromVector2Test() { var ret = BoundingBoxComputer.FromPoints(m_points); Assert.IsTrue(CmpRect(expRect, ret)); ret = BoundingBoxComputer.FromPoints(m_points, 1f); Assert.IsTrue(CmpRect(expRectMargin, ret)); Assert.AreEqual(BoundingBoxComputer.FromPoints(new List <Vector2>()), new Rect()); }
private UnityEngine.Object LoadKingsTaxesLevel(XElement fileSelected, string name) { // create the output scriptable object var asset = ScriptableObject.CreateInstance <KingsTaxesLevel>(); // retrieve page data from .ipe file var items = fileSelected.Descendants("page").First().Descendants("use"); // get marker data into respective vector list asset.Villages.AddRange(GetMarkers(items, "disk")); asset.Castles.AddRange(GetMarkers(items, "square")); // normalize coordinates var total = new List <Vector2>(); total.AddRange(asset.Villages); total.AddRange(asset.Castles); var rect = BoundingBoxComputer.FromPoints(total); asset.Villages = Normalize(rect, ktSIZE, asset.Villages); asset.Castles = Normalize(rect, ktSIZE, asset.Castles); // give warning if no relevant data found if (asset.Villages.Count + asset.Castles.Count == 0) { EditorUtility.DisplayDialog("Warning", "File does not contain any villages/castles (disks and/or squares).", "OK"); } // get level arguments var args = name.Split('_').ToList(); if (args.Count > 2) { foreach (var item in args) { Debug.Log(item); } EditorUtility.DisplayDialog("Error", "Too many level arguments given in path name.", "OK"); return(asset); } else if (args.Count == 2) { if (!float.TryParse(args[1], out asset.TSpannerRatio)) { EditorUtility.DisplayDialog("Error", "Could not parse the t-spanner ratio.", "OK"); return(asset); } } return(asset); }
/// <summary> /// Creates a Unity mesh object from this triangulation /// Mapping between Unity mesh triangulation and this custom triangulation class. /// </summary> /// <returns></returns> public Mesh CreateMesh() { Mesh mesh = new Mesh(); // make indexed map of vertices var vertices = new Dictionary <Vector2, int>(); var index = 0; foreach (var t in m_Triangles) { foreach (var v in t.Vertices) { if (!vertices.ContainsKey(v)) { vertices.Add(v, index++); } } } var vertexList = vertices.Keys.ToList(); // Calculate UV's var bbox = BoundingBoxComputer.FromPoints(vertexList, 0.1f); var newUV = vertexList.Select <Vector2, Vector2>(p => Rect.PointToNormalized(bbox, p)); // Calculate mesh triangles var tri = new List <int>(); foreach (var t in m_Triangles) { tri.AddRange(new int[3] { vertices[t.P0], vertices[t.P1], vertices[t.P2] }); } // set mesh variables mesh.vertices = vertexList.Select <Vector2, Vector3>(p => p).ToArray(); mesh.uv = newUV.ToArray(); mesh.triangles = tri.ToArray(); return(mesh); }
private UnityEngine.Object LoadShepherdLevel(XElement fileSelected, string name) { // create the output scriptable object var asset = ScriptableObject.CreateInstance <ShepherdLevel>(); // retrieve page data from .ipe file var items = fileSelected.Descendants("page").First().Descendants("use"); // get marker data into respective vector list List <string> markerTypes = new List <string> { "disk", "square", "cross", "circle" }; for (int i = 0; i < markerTypes.Count; i++) { List <Vector2> sheepLocs = GetMarkers(items, markerTypes[i]); foreach (Vector2 l in sheepLocs) { asset.addSheep(l, i); } } // normalize coordinates var rect = BoundingBoxComputer.FromPoints(asset.SheepList); asset.SheepList = Normalize(rect, shSIZE, asset.SheepList); // give warning if no relevant data found if (asset.SheepList.Count == 0) { EditorUtility.DisplayDialog("Warning", "File does not contain any valid markers.", "OK"); } asset.setBudget(int.Parse(name.Split('_').Last())); return(asset); }
/// <summary> /// Loads a convex hull level. /// </summary> /// <param name="fileSelected"></param> /// <param name="name"></param> /// <returns></returns> private UnityEngine.Object LoadHullLevel(XElement fileSelected, string name) { // create the output scriptable object var asset = ScriptableObject.CreateInstance<HullLevel>(); // retrieve page data from .ipe file var items = fileSelected.Descendants("page").First().Descendants("use"); // get marker data into respective vector list asset.Points.AddRange(GetMarkers(items, "disk")); // normalize coordinates var rect = BoundingBoxComputer.FromPoints(asset.Points); asset.Points = Normalize(rect, ktSIZE, asset.Points); // give warning if no relevant data found if (asset.Points.Count == 0) { EditorUtility.DisplayDialog("Warning", "File does not contain any villages/castles (disks and/or squares).", "OK"); } return asset; }
public UnityEngine.Object LoadArtGalleryLevel(XElement fileSelected, string name) { // create the output scriptable object var asset = ScriptableObject.CreateInstance <ArtGalleryLevel>(); // retrieve page data from .ipe file var items = fileSelected.Descendants("page").First().Descendants("path").ToList(); // check that .ipe file contains one and only one polygon if (items.Count == 0) { EditorUtility.DisplayDialog("Error", "No paths (lines/polygons) found in ipe file.", "OK"); return(asset); } var outerPoints = new List <Vector2>(); var holes = new List <List <Vector2> >(); var checkPoints = new List <Vector2>(); foreach (var poly in items) { List <float> transformation = null; if (poly.Attribute("matrix") != null) { transformation = poly.Attribute("matrix").Value .Split(' ') .Select(s => float.Parse(s)) .ToList(); } // retrieve coordinates from .ipe file var points = new List <Vector2>(); foreach (var coordString in poly.Value.Split('\n')) { var coords = coordString.Split(' ').ToList(); if (coords.Count < 2) { continue; } var x = float.Parse(coords[0]); var y = float.Parse(coords[1]); if (!MathUtil.IsFinite(x) || !MathUtil.IsFinite(y)) { continue; } if (transformation != null) { // apply transformation matrix (could be made into library function) x = transformation[0] * x + transformation[2] * y + transformation[4]; y = transformation[1] * x + transformation[3] * y + transformation[5]; } points.Add(new Vector2(x, y)); } if (outerPoints.Count == 0 || new Polygon2D(outerPoints).Area < new Polygon2D(points).Area) { if (outerPoints.Count > 0) { holes.Add(outerPoints); } outerPoints = points; } else { holes.Add(points); } // Add all defining vertices to checkPoints } // normalize coordinates var rect = BoundingBoxComputer.FromPoints(outerPoints); outerPoints = Normalize(rect, agSIZE, outerPoints); checkPoints.AddRange(outerPoints); for (var i = 0; i < holes.Count; i++) { holes[i] = Normalize(rect, agSIZE, holes[i]); checkPoints.AddRange(holes[i]); } // reverse if not clockwise if (!(new Polygon2D(outerPoints).IsClockwise())) { outerPoints.Reverse(); } for (var i = 0; i < holes.Count; i++) { // reverse if not clockwise if (!(new Polygon2D(holes[i]).IsClockwise())) { holes[i].Reverse(); } } var gridPoints = ComputeGridPoints(rect, outerPoints, holes, 50); checkPoints.AddRange(gridPoints); asset.Outer = outerPoints; asset.Holes = holes.Select(h => new Vector2Array(h.ToArray())).ToList(); asset.CheckPoints = checkPoints; Debug.Log(asset.CheckPoints); // get level arguments var args = name.Split('_').ToList(); if (args.Count > 2) { EditorUtility.DisplayDialog("Error", "Too many level arguments given in path name", "OK"); return(asset); } else if (args.Count == 2) { asset.MaxNumberOfLighthouses = int.Parse(args[1]); } return(asset); }
public UnityEngine.Object LoadCastleCrushersLevel(XElement fileSelected, string name) { // create the output scriptable object var asset = ScriptableObject.CreateInstance <LinesLevel>(); var points = new List <Vector2>(); // retrieve page data from .ipe file var items = fileSelected.Descendants("page").First().Descendants("path").ToList(); foreach (var line in items) { List <float> transformation = null; if (line.Attribute("matrix") != null) { transformation = line.Attribute("matrix").Value .Split(' ') .Select(s => float.Parse(s)) .ToList(); } foreach (var coordString in line.Value.Split('\n')) { var coords = coordString.Split(' ').ToList(); if (coords.Count < 2) { continue; } var x = float.Parse(coords[0]); var y = float.Parse(coords[1]); if (!MathUtil.IsFinite(x) || !MathUtil.IsFinite(y)) { continue; } if (transformation != null) { // apply transformation matrix (could be made into library function) x = transformation[0] * x + transformation[2] * y + transformation[4]; y = transformation[1] * x + transformation[3] * y + transformation[5]; } points.Add(new Vector2(x, y)); } } // normalize coordinates var rect = BoundingBoxComputer.FromPoints(points); var height = 7f; var width = 11f; if (rect.width <= rect.height) { points = Normalize(rect, height, points); } else { points = Normalize(rect, width, points); rect = BoundingBoxComputer.FromPoints(points); if (rect.height > height) { points = Normalize(rect, height * rect.width / rect.height, points); } } //for (int i = 0; i < points.Count; i++) { // points[i] = new Vector2(((points[i].x - rect.xMin) / rect.width - 0.5f) * 15.84f, // ((points[i].y - rect.yMin) / rect.height - 0.5f) * 10 * 0.75f + 0.75f); //} var first = new List <Vector2>(); var second = new List <Vector2>(); for (int i = 0; i < points.Count;) { first.Add(points[i++]); second.Add(points[i++]); } asset.startPoints = first; asset.endPoints = second; // get level arguments var args = name.Split('_').ToList(); if (args.Count > 2) { EditorUtility.DisplayDialog("Error", "Too many level arguments given in path name", "OK"); return(asset); } else if (args.Count == 2) { asset.maxShots = int.Parse(args[1]); } Debug.Log(args[0] + ": " + asset.endPoints.Count + " walls and " + asset.maxShots + " shots"); return(asset); }
private UnityEngine.Object LoadDivideLevel(XElement fileSelected, string name) { // create the output scriptable object var asset = ScriptableObject.CreateInstance <DivideLevel>(); // retrieve page data from .ipe file var items = fileSelected.Descendants("page").First().Descendants("use"); // get marker data into respective vector list asset.Spearmen.AddRange(GetMarkers(items, "disk")); asset.Archers.AddRange(GetMarkers(items, "square")); asset.Mages.AddRange(GetMarkers(items, "cross")); // normalize coordinates var total = new List <Vector2>(); total.AddRange(asset.Spearmen); total.AddRange(asset.Archers); total.AddRange(asset.Mages); var rect = BoundingBoxComputer.FromPoints(total); asset.Spearmen = Normalize(rect, divSIZE, asset.Spearmen); asset.Archers = Normalize(rect, divSIZE, asset.Archers); asset.Mages = Normalize(rect, divSIZE, asset.Mages); // give warning if no relevant data found if (asset.Spearmen.Count + asset.Archers.Count + asset.Mages.Count == 0) { EditorUtility.DisplayDialog("Warning", "File does not contain any spearmen, archers, mages (disks, squares and/or crosses).", "OK"); } // check for even number of points if (asset.Spearmen.Count % 2 != 0) { EditorUtility.DisplayDialog("Error", "File contains uneven number of spearmen (disks).", "OK"); return(asset); } if (asset.Archers.Count % 2 != 0) { EditorUtility.DisplayDialog("Error", "File contains uneven number of archers (squares).", "OK"); return(asset); } if (asset.Mages.Count % 2 != 0) { EditorUtility.DisplayDialog("Error", "File contains uneven number of mages (crosses).", "OK"); return(asset); } // get level arguments var args = name.Split('_').ToList(); if (args.Count > 2) { EditorUtility.DisplayDialog("Error", "Too many level arguments given in path name.", "OK"); return(asset); } else if (args.Count == 2) { if (!int.TryParse(args[1], out asset.NumberOfSwaps)) { EditorUtility.DisplayDialog("Error", "Could not parse level argument number of swaps.", "OK"); return(asset); } } return(asset); }
public Rect BoundingBox(float margin = 0f) { return(BoundingBoxComputer.FromPoints(Vertices, margin)); }
public Object LoadArtGalleryLevel(XElement fileSelected, string name) { // create the output scriptable object var asset = ScriptableObject.CreateInstance <ArtGalleryLevel>(); // retrieve page data from .ipe file var items = fileSelected.Descendants("page").First().Descendants("path").ToList(); // check that .ipe file contains one and only one polygon if (items.Count == 0) { EditorUtility.DisplayDialog("Error", "No paths (lines/polygons) found in ipe file.", "OK"); return(asset); } else if (items.Count > 1) { EditorUtility.DisplayDialog("Error", "File contains too many paths (lines/polygons).", "OK"); return(asset); } // retrieve coordinates from .ipe file var points = new List <Vector2>(); foreach (var item in items[0].Value.Split('\n')) { var coords = item.Split(' ').ToList(); if (coords.Count < 2) { continue; } var x = float.Parse(coords[0]); var y = float.Parse(coords[1]); if (!MathUtil.IsFinite(x) || !MathUtil.IsFinite(y)) { continue; } points.Add(new Vector2(x, y)); } // normalize coordinates var rect = BoundingBoxComputer.FromPoints(points); Normalize(rect, agSIZE, ref points); asset.Outer = points; // reverse if not clockwise if (!asset.Polygon.IsClockwise()) { points.Reverse(); asset.Outer = points; } // get level arguments var args = name.Split('_').ToList(); if (args.Count > 2) { EditorUtility.DisplayDialog("Error", "Too many level arguments given in path name", "OK"); return(asset); } else if (args.Count == 2) { asset.MaxNumberOfLighthouses = int.Parse(args[1]); } return(asset); }