public void RemoveShot(Vector3 pos) { if (shots.Count == 0) { return; } float min = Vector3.Distance(shots[0].Point1, pos); LineObject closest = shots[0]; for (int i = 1; i < shots.Count; i++) { if (Vector3.Distance(shots[i].Point1, pos) < min) // Alternatively, closest line: shots[i].line.DistanceToPoint(pos) < min { closest = shots[i]; min = shots[i].DistanceToPoint(pos); } } foreach (LineObject wall in walls) { Vector2?intersection = wall.Intersect(closest); if (intersection != null) { wall.repair(); } } shots.Remove(closest); Destroy(closest.obj); UpdateWallDestroyed(); UpdateRemainingShots(); }
void Update() { if (controller.IsLevelComplete()) { // Do nothing when level is complete return; } if (Input.GetMouseButtonDown(0) && controller.CanAddShot()) { CreateNewShot(); } else if (Input.GetMouseButton(0) && controller.CanAddShot()) { UpdateNewShotEndpoint(); } else if (Input.GetMouseButtonUp(0) && controller.CanAddShot() && shot != null) { if (shotEnd.Equals(shotStart)) { Destroy(shot); } else { LineObject newShot = new LineObject(shotStart, shotEnd, shot); controller.AddNewShot(newShot); } shot = null; } else if (Input.GetMouseButtonDown(1)) { controller.RemoveShot(Camera.main.ScreenToWorldPoint(Input.mousePosition + 10 * Vector3.forward)); } }
public void AddNewShot(LineObject shot) { shots.Add(shot); foreach (LineObject wall in walls) { Vector2?intersection = wall.Intersect(shot); if (intersection != null) { wall.Break(); } } if (CheckSolution()) { advanceButton.SetActive(true); } UpdateWallDestroyed(); UpdateRemainingShots(); }
public void GenerateNewLevel(int maxWalls) { ClearLevel(); // Generator code walls = new List <LineObject>(); List <LineObject> eventWalls = new List <LineObject>(); int N = maxWalls; while (N > 0) { Vector2 position1 = new Vector3(UnityEngine.Random.Range(MIN_WIDTH, MAX_WIDTH), UnityEngine.Random.Range(MIN_HEIGHT, MAX_HEIGHT)); Vector2 position2 = new Vector3(UnityEngine.Random.Range(MIN_WIDTH, MAX_WIDTH), UnityEngine.Random.Range(MIN_HEIGHT, MAX_HEIGHT)); LineObject newLine = new LineObject(position1, position2); if (newLine.IsHorizontal == false) { walls.Add(newLine); N -= 1; } } // Remove all too short walls walls.RemoveAll(item => item.Magnitude < MIN_WALL_SIZE); foreach (LineObject wall in walls) { eventWalls.Add(new LineObject(new Vector2(wall.Point1.x, wall.Point1.y), new Vector2(wall.Point2.x, wall.Point2.y))); // deep copy } sweep = new DownwardSweepLine(walls); List <Intersection> intersections = sweep.Run(); List <SweepEvent> eventPoints = new List <SweepEvent>(); foreach (SweepEvent ev in sweep.producedEvents) { SweepEvent copy = new SweepEvent(ev.EventType); // deep copy copy.StatusItem = new StatusItem(new LineObject(ev.StatusItem.LineObject.Point1, ev.StatusItem.LineObject.Point2)); if (ev.IntersectingStatusItem != null) { copy.IntersectingStatusItem = new StatusItem(new LineObject(ev.IntersectingStatusItem.LineObject.Point1, ev.IntersectingStatusItem.LineObject.Point2)); } eventPoints.Add(copy); } // Split intersections into multiple walls doesnt always work. If there are many walls we cant just simply split Dictionary <LineObject, List <Vector2> > map = new Dictionary <LineObject, List <Vector2> >(); for (int i = 0; i < intersections.Count; i++) { if (!map.ContainsKey(intersections[i].one)) { map.Add(intersections[i].one, new List <Vector2>()); } if (!map.ContainsKey(intersections[i].two)) { map.Add(intersections[i].two, new List <Vector2>()); } Vector2?intersection = intersections[i].one.Intersect(intersections[i].two); // safety check if (intersection != null) { map[intersections[i].one].Add((Vector2)intersection); map[intersections[i].two].Add((Vector2)intersection); } } foreach (LineObject oldSeg in map.Keys) { List <Vector2> points = map[oldSeg]; points.Add(oldSeg.Point1); points.Add(oldSeg.Point2); points.Sort((a, b) => a.x.CompareTo(b.x)); walls.Remove(oldSeg); for (int i = 0; i < points.Count - 1; i++) { walls.Add(new LineObject(points[i], points[i + 1])); } } // Remove all too short walls walls.RemoveAll(item => item.Magnitude < MIN_WALL_SIZE); // Add GameObject to the remaining walls float sizeFactor = 0.8f * (float)Math.Exp(-0.03 * ((float)walls.Count)) + 0.01f; foreach (LineObject line in walls) { Vector2 position1 = line.Point1; Vector2 position2 = line.Point2; GameObject newWall = Instantiate(wallPrefab, wallObjects); newWall.transform.Find("StartCastle").position = position1; newWall.transform.Find("EndCastle").position = position2; newWall.GetComponent <LineRenderer>().SetPosition(0, position1); newWall.GetComponent <LineRenderer>().SetPosition(1, position2); newWall.transform.Find("StartCastle").localScale = new Vector3(sizeFactor, sizeFactor, sizeFactor); newWall.transform.Find("EndCastle").localScale = new Vector3(sizeFactor, sizeFactor, sizeFactor); newWall.GetComponent <LineRenderer>().startWidth = 0.4f * sizeFactor; newWall.GetComponent <LineRenderer>().endWidth = 0.4f * sizeFactor; line.obj = newWall; } // Use ShotSolver to find the budget of shots shotSolver = new ShotSolver(walls); List <Line> greedyShots = shotSolver.GreedyCover(); maxShots = greedyShots.Count; updateEventsVis(eventWalls, eventPoints); updateSolverVis(greedyShots); }
internal StatusItem(LineObject lineObject) { LineObject = lineObject; }
public Intersection(LineObject one, LineObject two) { this.one = one; this.two = two; }