public Cell Copy() { Cell copy = new Cell (); copy.blocked = this.blocked; copy.seen = this.seen; copy.safe = this.safe; copy.noisy = this.noisy; copy.waypoint = this.waypoint; copy.goal = this.goal; copy.cluster = this.cluster; return copy; }
public void ComputeSeenCells(Cell[][][] fullmap) { seenCells = new Cell[fullmap.Length][][]; for (int t = 0; t < fullmap.Length; t++) { seenCells[t] = new Cell[fullmap[0].Length][]; for (int x = 0; x < fullmap[0][0].Length; x++) { seenCells[t][x] = new Cell[fullmap[0][0].Length]; } } for (int t = 0; t < this.cells.Length; t++) { foreach (Vector2 p in this.cells[t]) { seenCells[t][(int)p.x][(int)p.y] = fullmap[t][(int)p.x][(int)p.y]; } } }
public List<Node> Compute(int startX, int startY, int endX, int endY, int attemps, float stepSize, float playerMaxHp, float playerSpeed, float playerDps, Cell[][][] matrix, bool smooth = false) { // Initialization tree = new KDTree (3); deathPaths = new List<List<Node>> (); nodeMatrix = matrix; //Start and ending node Node start = GetNode (0, startX, startY); start.visited = true; start.parent = null; start.playerhp = playerMaxHp; foreach (Enemy e in enemies) { start.enemyhp.Add (e, e.maxHealth); } // Prepare start and end node Node end = GetNode (0, endX, endY); tree.insert (start.GetArray (), start); // Prepare the variables Node nodeVisiting = null; Node nodeTheClosestTo = null; float tan = playerSpeed / 1; angle = 90f - Mathf.Atan (tan) * Mathf.Rad2Deg; /*Distribution algorithm * List<Distribution.Pair> pairs = new List<Distribution.Pair> (); for (int x = 0; x < matrix[0].Length; x++) for (int y = 0; y < matrix[0].Length; y++) if (((Cell)matrix [0] [x] [y]).waypoint) pairs.Add (new Distribution.Pair (x, y)); pairs.Add (new Distribution.Pair (end.x, end.y)); Distribution rd = new Distribution(matrix[0].Length, pairs.ToArray());*/ DDA dda = new DDA (tileSizeX, tileSizeZ, nodeMatrix [0].Length, nodeMatrix [0] [0].Length); //RRT algo for (int i = 0; i <= attemps; i++) { //Get random point int rt = Random.Range (1, nodeMatrix.Length); int rx = Random.Range (0, nodeMatrix [rt].Length); int ry = Random.Range (0, nodeMatrix [rt] [rx].Length); //Distribution.Pair p = rd.NextRandom(); //int rx = p.x, ry = p.y; nodeVisiting = GetNode (rt, rx, ry); if (nodeVisiting.visited || nodeVisiting.cell.blocked) { i--; continue; } nodeTheClosestTo = (Node)tree.nearest (new double[] {rx, rt, ry}); // Skip downwards movement if (nodeTheClosestTo.t > nodeVisiting.t) continue; // Skip if player is dead if (nodeTheClosestTo.playerhp <= 0) continue; // Only add if we are going in ANGLE degrees or higher Vector3 p1 = nodeVisiting.GetVector3 (); Vector3 p2 = nodeTheClosestTo.GetVector3 (); Vector3 pd = p1 - p2; if (Vector3.Angle (pd, new Vector3 (pd.x, 0f, pd.z)) < angle) { continue; } // And we have line of sight if (nodeVisiting.cell.blocked) { continue; } // Check for all alive enemies List<Cell[][][]> seenList = new List<Cell[][][]> (); foreach (Enemy e in enemies) { if (nodeTheClosestTo.enemyhp [e] > 0) seenList.Add (e.seenCells); } Node hit = dda.Los3D (nodeMatrix, nodeTheClosestTo, nodeVisiting, seenList.ToArray ()); if (hit != null) { if (hit.cell.blocked || (!simulateCombat && hit.cell.seen && !hit.cell.safe)) // Collision with obstacle, ignore. If we don't simulate combat, ignore collision with enemy continue; else { // Which enemy has seen me? Enemy toFight = null; foreach (Enemy e in enemies) { if (e.seenCells [hit.t] [hit.x] [hit.y] != null && nodeTheClosestTo.enemyhp [e] > 0) toFight = e; } // Solve the time float timef = nodeTheClosestTo.enemyhp [toFight] / (playerDps * stepSize); int timeT = Mathf.CeilToInt (timef); // Search for more enemies List<object> more = new List<object> (); foreach (Enemy e2 in enemies) { if (toFight != e2) for (int t = hit.t; t < hit.t + timeT; t++) if (e2.seenCells [t] [hit.x] [hit.y] != null && nodeTheClosestTo.enemyhp [e2] > 0) { Tuple<Enemy, int> whenSeen = new Tuple<Enemy, int> (e2, t); more.Add (whenSeen); break; // Skip this enemy } } // Did another enemy saw the player while he was fighting? if (more.Count > 0) { // Who dies when List<object> dyingAt = new List<object> (); // First, save when the first fight starts Node firstFight = NewNode (hit.t, hit.x, hit.y); firstFight.parent = nodeTheClosestTo; // Then when the first guy dies Tuple<Enemy, int> death = new Tuple<Enemy, int> (toFight, firstFight.t + timeT); dyingAt.Add (death); // And proccess the other stuff copy (nodeTheClosestTo, firstFight); firstFight.fighting.Add (toFight); // Navigation node Node lastNode = firstFight; // Solve for all enemies joining the fight foreach (object o in more) { Tuple<Enemy, int> joined = (Tuple<Enemy, int>)o; // Calculate dying time timef = timef + lastNode.enemyhp [joined.First] / (playerDps * stepSize); timeT = Mathf.CeilToInt (timef); death = new Tuple<Enemy, int> (joined.First, timeT + hit.t); dyingAt.Add (death); // Create the node structure Node startingFight = NewNode (joined.Second, hit.x, hit.y); // Add to fighting list copy (lastNode, startingFight); startingFight.fighting.Add (joined.First); // Correct parenting startingFight.parent = lastNode; lastNode = startingFight; } // Solve for all deaths foreach (object o in dyingAt) { Tuple<Enemy, int> dead = (Tuple<Enemy, int>)o; Node travel = lastNode; bool didDie = false; while (!didDie && travel.parent != null) { // Does this guy dies between two nodes? if (dead.Second > travel.parent.t && dead.Second < travel.t) { // Add the node Node adding = NewNode (dead.Second + hit.t, hit.x, hit.y); adding.fighting = new List<Enemy> (); adding.fighting.AddRange (travel.parent.fighting); // And remove the dead people adding.fighting.Remove (dead.First); adding.died = dead.First; Node remove = lastNode; // Including from nodes deeper in the tree while (remove != travel.parent) { remove.fighting.Remove (dead.First); remove = remove.parent; } // Reparent the nodes adding.parent = travel.parent; travel.parent = adding; didDie = true; } travel = travel.parent; } if (!didDie) { // The guy didn't die between, that means he's farthest away than lastNode Node adding = NewNode (dead.Second, hit.x, hit.y); copy (lastNode, adding); adding.fighting.Remove (dead.First); adding.enemyhp [dead.First] = 0; adding.died = dead.First; adding.parent = lastNode; // This is the new lastNode lastNode = adding; } } // Grab the first node with fighting Node first = lastNode; while (first.parent != nodeTheClosestTo) first = first.parent; while (first != lastNode) { Node navigate = lastNode; // And grab the node just after the first while (navigate.parent != first) navigate = navigate.parent; // Copy the damage already applied navigate.playerhp = first.playerhp; // And deal more damage foreach (Enemy dmgDealer in first.fighting) navigate.playerhp -= (navigate.t - first.t) * dmgDealer.dps * stepSize; // Goto next node first = navigate; } // Make the tree structure nodeVisiting = lastNode; } else { // Only one enemy has seen me Node toAdd = NewNode (hit.t, hit.x, hit.y); nodeVisiting = NewNode (hit.t + timeT, hit.x, hit.y); nodeVisiting.parent = toAdd; toAdd.parent = nodeTheClosestTo; copy (nodeTheClosestTo, toAdd); toAdd.fighting.Add (toFight); copy (nodeTheClosestTo, nodeVisiting); nodeVisiting.playerhp = toAdd.playerhp - timef * toFight.dps * stepSize; nodeVisiting.enemyhp [toFight] = 0; nodeVisiting.died = toFight; } } } else { // Nobody has seen me nodeVisiting.parent = nodeTheClosestTo; copy (nodeTheClosestTo, nodeVisiting); } try { tree.insert (nodeVisiting.GetArray (), nodeVisiting); } catch (KeyDuplicateException) { } nodeVisiting.visited = true; // Add the path to the death paths list if (nodeVisiting.playerhp <= 0) { Node playerDeath = nodeVisiting; while (playerDeath.parent.playerhp <= 0) playerDeath = playerDeath.parent; deathPaths.Add (ReturnPath (playerDeath, smooth)); } // Attemp to connect to the end node if (nodeVisiting.playerhp > 0) { // Compute minimum time to reach the end node p1 = nodeVisiting.GetVector3 (); p2 = end.GetVector3 (); p2.y = p1.y; float dist = Vector3.Distance (p1, p2); float t = dist * Mathf.Tan (angle); pd = p2; pd.y += t; if (pd.y <= nodeMatrix.GetLength (0)) { Node endNode = GetNode ((int)pd.y, (int)pd.x, (int)pd.z); // Try connecting seenList = new List<Cell[][][]> (); foreach (Enemy e in enemies) { if (nodeTheClosestTo.enemyhp [e] > 0) seenList.Add (e.seenCells); } hit = dda.Los3D (nodeMatrix, nodeVisiting, endNode, seenList.ToArray ()); // To simplify things, only connect if player isn't seen or collides with an obstacle if (hit == null) { endNode.parent = nodeVisiting; copy (endNode.parent, endNode); List<Node> done = ReturnPath (endNode, smooth); //UpdateNodeMatrix (done); return done; } } if (nodeVisiting.playerhp < playerMaxHp) // Health pack solving foreach (HealthPack pack in packs) { if (!nodeVisiting.picked.Contains(pack)) { // Compute minimum time to reach the pack p1 = nodeVisiting.GetVector3 (); p2 = new Vector3(pack.posX, p1.y, pack.posZ); dist = Vector3.Distance (p1, p2); t = dist * Mathf.Tan (angle); pd = p2; pd.y += t; if (pd.y <= nodeMatrix.GetLength (0)) { // TODO If the node is already on the Tree, things may break! // but we need to add it to the tree and retrieve from it to make it a possible path! Node packNode = GetNode ((int)pd.y, (int)pd.x, (int)pd.z); // Try connecting seenList = new List<Cell[][][]> (); foreach (Enemy e in enemies) { if (nodeVisiting.enemyhp [e] > 0) seenList.Add (e.seenCells); } hit = dda.Los3D (nodeMatrix, nodeVisiting, packNode, seenList.ToArray ()); // To simplify things, only connect if player isn't seen or collides with an obstacle if (hit == null) { packNode.parent = nodeVisiting; copy (packNode.parent, packNode); packNode.picked.Add(pack); packNode.playerhp = playerMaxHp; try { tree.insert(packNode.GetArray(), packNode); } catch (KeyDuplicateException) { } } } } } } //Might be adding the neighboor as a the goal if (nodeVisiting.x == end.x & nodeVisiting.y == end.y) { //Debug.Log ("Done2"); List<Node> done = ReturnPath (nodeVisiting, smooth); //UpdateNodeMatrix (done); return done; } } return new List<Node> (); }
public List<Node> Compute(int startX, int startY, int endX, int endY, int attemps, float speed, Cell[][][] matrix, bool smooth = false) { // Initialization tree = new KDTree (3); explored = new List<Node> (); nodeMatrix = matrix; //Start and ending node Node start = GetNode (0, startX, startY); start.visited = true; start.parent = null; // Prepare start and end node Node end = GetNode (0, endX, endY); tree.insert (start.GetArray (), start); explored.Add (start); // Prepare the variables Node nodeVisiting = null; Node nodeTheClosestTo = null; float tan = speed / 1; angle = 90f - Mathf.Atan (tan) * Mathf.Rad2Deg; List<Distribution.Pair> pairs = new List<Distribution.Pair> (); for (int x = 0; x < matrix[0].Length; x++) for (int y = 0; y < matrix[0].Length; y++) if (((Cell)matrix [0] [x] [y]).waypoint) pairs.Add (new Distribution.Pair (x, y)); pairs.Add (new Distribution.Pair (end.x, end.y)); //Distribution rd = new Distribution(matrix[0].Length, pairs.ToArray()); //RRT algo for (int i = 0; i <= attemps; i++) { //Get random point int rt = Random.Range (1, nodeMatrix.Length); //Distribution.Pair p = rd.NextRandom(); int rx = Random.Range (0, nodeMatrix [rt].Length); int ry = Random.Range (0, nodeMatrix [rt] [rx].Length); //int rx = p.x, ry = p.y; nodeVisiting = GetNode (rt, rx, ry); if (nodeVisiting.visited || nodeVisiting.cell.blocked) { i--; continue; } explored.Add (nodeVisiting); nodeTheClosestTo = (Node)tree.nearest (new double[] {rx, rt, ry}); // Skip downwards movement if (nodeTheClosestTo.t > nodeVisiting.t) continue; // Only add if we are going in ANGLE degrees or higher Vector3 p1 = nodeVisiting.GetVector3 (); Vector3 p2 = nodeTheClosestTo.GetVector3 (); Vector3 pd = p1 - p2; if (Vector3.Angle (pd, new Vector3 (pd.x, 0f, pd.z)) < angle) { continue; } // And we have line of sight if ((nodeVisiting.cell.seen && !nodeVisiting.cell.safe) || Extra.Collision.CheckCollision (nodeVisiting, nodeTheClosestTo, this, SpaceState.Editor, true)) continue; try { tree.insert (nodeVisiting.GetArray (), nodeVisiting); } catch (KeyDuplicateException) { } nodeVisiting.parent = nodeTheClosestTo; nodeVisiting.visited = true; // Attemp to connect to the end node if (Random.Range (0, 1000) > 0) { p1 = nodeVisiting.GetVector3 (); p2 = end.GetVector3 (); p2.y = p1.y; float dist = Vector3.Distance (p1, p2); float t = dist * Mathf.Tan (angle); pd = p2; pd.y += t; if (pd.y <= nodeMatrix.GetLength (0)) { Node endNode = GetNode ((int)pd.y, (int)pd.x, (int)pd.z); if (!Extra.Collision.CheckCollision (nodeVisiting, endNode, this, SpaceState.Editor, true)) { //Debug.Log ("Done3"); endNode.parent = nodeVisiting; return ReturnPath (endNode, smooth); } } } //Might be adding the neighboor as a the goal if (nodeVisiting.x == end.x & nodeVisiting.y == end.y) { //Debug.Log ("Done2"); return ReturnPath (nodeVisiting, smooth); } } return new List<Node> (); }
void OnGUI() { #region Pre-Init // Wait for the floor to be set and initialize the drawer and the mapper if (floor != null) { if (floor.collider == null) { Debug.LogWarning ("Floor has no valid collider, game object ignored."); floor = null; } else { drawer = floor.gameObject.GetComponent<MapperEditorDrawer> (); if (drawer == null) { drawer = floor.gameObject.AddComponent<MapperEditorDrawer> (); drawer.hideFlags = HideFlags.HideInInspector; } } if (mapper == null) { mapper = floor.GetComponent<Mapper> (); if (mapper == null) mapper = floor.AddComponent<Mapper> (); mapper.hideFlags = HideFlags.None; } } #endregion // ---------------------------------- scrollPos = EditorGUILayout.BeginScrollView (scrollPos); #region 1. Map EditorGUILayout.LabelField ("1. Map"); playerPrefab = (GameObject)EditorGUILayout.ObjectField ("Player Prefab", playerPrefab, typeof(GameObject), false); floor = (GameObject)EditorGUILayout.ObjectField ("Floor", floor, typeof(GameObject), true); gridSize = EditorGUILayout.IntSlider ("Grid size", gridSize, 10, 300); if (GUILayout.Button ((MapperEditor.editGrid ? "Finish Editing" : "Edit Grid"))) { if (floor != null) { MapperEditor.editGrid = !MapperEditor.editGrid; Selection.activeGameObject = mapper.gameObject; } } EditorGUILayout.LabelField (""); #endregion // ---------------------------------- #region 2. Units EditorGUILayout.LabelField ("2. Units"); playerDPS = EditorGUILayout.Slider("Player DPS", playerDPS, 0.1f, 100f); if (GUILayout.Button ("Store Positions")) { StorePositions (); } EditorGUILayout.LabelField (""); #endregion // ---------------------------------- #region 3. Map Computation EditorGUILayout.LabelField ("3. Map Computation"); timeSamples = EditorGUILayout.IntSlider ("Time samples", timeSamples, 1, 10000); stepSize = EditorGUILayout.Slider ("Step size", stepSize, 0.01f, 1f); stepInTicks = ((long)(stepSize * 10000000L)); ticksBehind = EditorGUILayout.IntSlider (new GUIContent ("Ticks behind", "Number of ticks that the FoV will remain seen after the enemy has no visibility on that cell (prevents noise/jitter like behaviours)"), ticksBehind, 0, 100); if (GUILayout.Button ("Precompute Maps")) { //Find this is the view if (playerPrefab == null) { playerPrefab = GameObject.Find ("Player"); } if (floor == null) { floor = (GameObject)GameObject.Find ("Floor"); if (mapper == null) { mapper = floor.GetComponent<Mapper> (); if (mapper == null) mapper = floor.AddComponent<Mapper> (); mapper.hideFlags = HideFlags.None; } drawer = floor.gameObject.GetComponent<MapperEditorDrawer> (); if (drawer == null) { drawer = floor.gameObject.AddComponent<MapperEditorDrawer> (); drawer.hideFlags = HideFlags.HideInInspector; } } if (!simulated) { StorePositions (); simulated = true; } Cell[][] baseMap = null; if (MapperEditor.grid != null) { Cell[][] obstacles = mapper.ComputeObstacles (); baseMap = new Cell[gridSize][]; for (int x = 0; x < gridSize; x++) { baseMap [x] = new Cell[gridSize]; for (int y = 0; y < gridSize; y++) { baseMap [x] [y] = MapperEditor.grid [x] [y] == null ? obstacles [x] [y] : MapperEditor.grid [x] [y]; } } } original = mapper.PrecomputeMaps (SpaceState.Editor, floor.collider.bounds.min, floor.collider.bounds.max, gridSize, gridSize, timeSamples, stepSize, ticksBehind, baseMap); drawer.fullMap = original; float maxSeenGrid; drawer.seenNeverSeen = Analyzer.ComputeSeenValuesGrid (original, out maxSeenGrid); drawer.seenNeverSeenMax = maxSeenGrid; drawer.tileSize = SpaceState.Editor.tileSize; drawer.zero.Set (floor.collider.bounds.min.x, floor.collider.bounds.min.z); ResetAI (); previous = DateTime.Now; } EditorGUILayout.LabelField (""); #endregion // ---------------------------------- #region 4. Path EditorGUILayout.LabelField ("4. Path"); start = (GameObject)EditorGUILayout.ObjectField ("Start", start, typeof(GameObject), true); end = (GameObject)EditorGUILayout.ObjectField ("End", end, typeof(GameObject), true); attemps = EditorGUILayout.IntSlider ("Attempts", attemps, 1000, 100000); iterations = EditorGUILayout.IntSlider ("Iterations", iterations, 1, 1500); randomSeed = EditorGUILayout.IntSlider("Random Seed", randomSeed, -1, 10000); smoothPath = EditorGUILayout.Toggle ("Smooth path", smoothPath); simulateCombat = EditorGUILayout.Toggle ("Simulate combat", simulateCombat); if (GUILayout.Button ("(WIP) Compute 3D A* Path")) { float playerSpeed = GameObject.FindGameObjectWithTag ("AI").GetComponent<Player> ().speed; //Check the start and the end and get them from the editor. if (start == null) { start = GameObject.Find ("Start"); } if (end == null) { end = GameObject.Find ("End"); } startX = (int)((start.transform.position.x - floor.collider.bounds.min.x) / SpaceState.Editor.tileSize.x); startY = (int)((start.transform.position.z - floor.collider.bounds.min.z) / SpaceState.Editor.tileSize.y); endX = (int)((end.transform.position.x - floor.collider.bounds.min.x) / SpaceState.Editor.tileSize.x); endY = (int)((end.transform.position.z - floor.collider.bounds.min.z) / SpaceState.Editor.tileSize.y); paths.Clear (); deaths.Clear (); ClearPathsRepresentation (); arrangedByCrazy = arrangedByDanger = arrangedByDanger3 = arrangedByDanger3Norm = arrangedByLength = arrangedByLoS = arrangedByLoS3 = arrangedByLoS3Norm = arrangedByTime = arrangedByVelocity = null; Exploration.DavAStar3d astar3d = new DavAStar3d(); List<Node> nodes = astar3d.Compute(startX, startY, endX, endY, original, playerSpeed); if (nodes.Count > 0) { paths.Add (new Path (nodes)); toggleStatus.Add (paths.Last (), true); paths.Last ().color = new Color (UnityEngine.Random.Range (0.0f, 1.0f), UnityEngine.Random.Range (0.0f, 1.0f), UnityEngine.Random.Range (0.0f, 1.0f)); } } if (GUILayout.Button ("Compute Path")) { float playerSpeed = GameObject.FindGameObjectWithTag ("AI").GetComponent<Player> ().speed; float playerMaxHp = GameObject.FindGameObjectWithTag ("AI").GetComponent<Player> ().maxHp; //Check the start and the end and get them from the editor. if (start == null) { start = GameObject.Find ("Start"); } if (end == null) { end = GameObject.Find ("End"); } paths.Clear (); deaths.Clear (); ClearPathsRepresentation (); arrangedByCrazy = arrangedByDanger = arrangedByDanger3 = arrangedByDanger3Norm = arrangedByLength = arrangedByLoS = arrangedByLoS3 = arrangedByLoS3Norm = arrangedByTime = arrangedByVelocity = null; // Prepare start and end position startX = (int)((start.transform.position.x - floor.collider.bounds.min.x) / SpaceState.Editor.tileSize.x); startY = (int)((start.transform.position.z - floor.collider.bounds.min.z) / SpaceState.Editor.tileSize.y); endX = (int)((end.transform.position.x - floor.collider.bounds.min.x) / SpaceState.Editor.tileSize.x); endY = (int)((end.transform.position.z - floor.collider.bounds.min.z) / SpaceState.Editor.tileSize.y); GameObject[] hps = GameObject.FindGameObjectsWithTag("HealthPack"); HealthPack[] packs = new HealthPack[hps.Length]; for (int i = 0; i < hps.Length; i++) { packs[i] = hps[i].GetComponent<HealthPack>(); packs[i].posX = (int)((packs[i].transform.position.x - floor.collider.bounds.min.x) / SpaceState.Editor.tileSize.x); packs[i].posZ = (int)((packs[i].transform.position.z - floor.collider.bounds.min.z) / SpaceState.Editor.tileSize.y); } // Update the parameters on the RRT class rrt.min = floor.collider.bounds.min; rrt.tileSizeX = SpaceState.Editor.tileSize.x; rrt.tileSizeZ = SpaceState.Editor.tileSize.y; rrt.enemies = SpaceState.Editor.enemies; rrt.packs = packs; rrt.simulateCombat = simulateCombat; int seed = randomSeed; if (randomSeed != -1) UnityEngine.Random.seed = randomSeed; else { DateTime now = DateTime.Now; seed = now.Millisecond + now.Second + now.Minute + now.Hour + now.Day + now.Month+ now.Year; UnityEngine.Random.seed = seed; } List<Node> nodes = null; for (int it = 0; it < iterations; it++) { // Make a copy of the original map fullMap = new Cell[original.Length][][]; for (int t = 0; t < original.Length; t++) { fullMap[t] = new Cell[original[0].Length][]; for (int x = 0; x < original[0].Length; x++) { fullMap[t][x] = new Cell[original[0][0].Length]; for (int y = 0; y < original[0][0].Length; y++) fullMap[t][x][y] = original[t][x][y].Copy(); } } // Use the copied map so the RRT can modify it foreach (Enemy e in SpaceState.Editor.enemies) { for (int t = 0; t < original.Length; t++) for (int x = 0; x < original[0].Length; x++) for (int y = 0; y < original[0][0].Length; y++) if (e.seenCells[t][x][y] != null) e.seenCells[t][x][y] = fullMap[t][x][y]; // TODO: Need to make a backup of the enemies positions, rotations and forwards } // We have this try/catch block here to account for the issue that we don't solve when we find a path when t is near the limit try { nodes = rrt.Compute (startX, startY, endX, endY, attemps, stepSize, playerMaxHp, playerSpeed, playerDPS, fullMap, smoothPath); // Did we found a path? if (nodes.Count > 0) { paths.Add (new Path (nodes)); toggleStatus.Add (paths.Last (), true); paths.Last ().color = new Color (UnityEngine.Random.Range (0.0f, 1.0f), UnityEngine.Random.Range (0.0f, 1.0f), UnityEngine.Random.Range (0.0f, 1.0f)); } // Grab the death list foreach (List<Node> deathNodes in rrt.deathPaths) { deaths.Add(new Path(deathNodes)); } } catch (Exception e) { Debug.LogWarning("Skip errored calculated path"); Debug.LogException(e); // This can happen in two different cases: // In line 376 by having a duplicate node being picked (coincidence picking the EndNode as visiting but the check is later on) // We also cant just bring the check earlier since there's data to be copied (really really rare cases) // The other case is yet unkown, but it's a conicidence by trying to insert a node in the tree that already exists (really rare cases) } } // Set the map to be drawn drawer.fullMap = fullMap; ComputeHeatMap (paths, deaths); // Compute the summary about the paths and print it String summary = "Summary:\n"; summary += "Seed used:" + seed; summary += "\nSuccessful paths found: " + paths.Count; summary += "\nDead paths: " + deaths.Count; // How many paths killed how many enemies Dictionary<int, int> map = new Dictionary<int, int>(); for (int i = 0; i <= SpaceState.Editor.enemies.Length; i++) map.Add(i, 0); foreach (Path p in paths) { int killed = 0; foreach (Node n in p.points) if (n.died != null) killed++; if (map.ContainsKey(killed)) map[killed]++; else map.Add(killed, 1); } foreach (int k in map.Keys) { summary += "\n" + map[k] + " paths killed " + k + " enemies"; } // Debug.Log(summary); } if (GUILayout.Button ("(DEBUG) Export Paths")) { List<Path> all = new List<Path>(); all.AddRange(paths); all.AddRange(deaths); PathBulk.SavePathsToFile ("pathtest.xml", all); } if (GUILayout.Button ("(DEBUG) Import Paths")) { paths.Clear (); ClearPathsRepresentation (); List<Path> pathsImported = PathBulk.LoadPathsFromFile ("pathtest.xml"); foreach (Path p in pathsImported) { if (p.points.Last().playerhp <= 0) { deaths.Add(p); } else { p.name = "Imported " + (++imported); p.color = new Color (UnityEngine.Random.Range (0.0f, 1.0f), UnityEngine.Random.Range (0.0f, 1.0f), UnityEngine.Random.Range (0.0f, 1.0f)); toggleStatus.Add (p, true); } } ComputeHeatMap (paths, deaths); SetupArrangedPaths (paths); } EditorGUILayout.LabelField (""); #endregion // ---------------------------------- #region 5. Visualization EditorGUILayout.LabelField ("5. Visualization"); timeSlice = EditorGUILayout.IntSlider ("Time", timeSlice, 0, timeSamples - 1); drawMap = EditorGUILayout.Toggle ("Draw map", drawMap); drawNeverSeen = EditorGUILayout.Toggle ("- Draw safe places", drawNeverSeen); drawFoVOnly = EditorGUILayout.Toggle ("- Draw only fields of view", drawFoVOnly); drawHeatMap = EditorGUILayout.Toggle ("- Draw heat map", drawHeatMap); drawCombatHeatMap = EditorGUILayout.Toggle ("-> Draw combat heat map", drawCombatHeatMap); drawHeatMap3d = EditorGUILayout.Toggle ("-> Draw heat map 3d", drawHeatMap3d); drawDeathHeatMap = EditorGUILayout.Toggle ("-> Draw death heat map", drawDeathHeatMap); drawDeathHeatMap3d = EditorGUILayout.Toggle ("--> Draw 3d death heat map", drawDeathHeatMap3d); drawPath = EditorGUILayout.Toggle ("Draw path", drawPath); drawCombatLines = EditorGUILayout.Toggle ("Draw combat lines", drawCombatLines); if (drawer != null) { drawer.heatMap = null; drawer.heatMap3d = null; drawer.deathHeatMap = null; drawer.deathHeatMap3d = null; drawer.combatHeatMap = null; if (drawHeatMap) { if (drawCombatHeatMap) drawer.combatHeatMap = combatHeatMap; else if (drawHeatMap3d) drawer.heatMap3d = heatMap3d; else if (drawDeathHeatMap) { if (drawDeathHeatMap3d) drawer.deathHeatMap3d = deathHeatMap3d; else drawer.deathHeatMap = deathHeatMap; } else drawer.heatMap = heatMap; } } EditorGUILayout.LabelField (""); if (GUILayout.Button (playing ? "Stop" : "Play")) { playing = !playing; } EditorGUILayout.LabelField (""); /*if (GUILayout.Button ("Batch computation")) { BatchComputing (); }*/ #endregion // ---------------------------------- #region 6. Paths EditorGUILayout.LabelField ("6. Paths"); EditorGUILayout.LabelField (""); crazySeconds = EditorGUILayout.Slider ("Crazy seconds window", crazySeconds, 0f, 10f); if (GUILayout.Button ("Analyze paths")) { ClearPathsRepresentation (); // Setup paths names int i = 1; foreach (Path path in paths) { path.name = "Path " + (i++); path.color = new Color (UnityEngine.Random.Range (0.0f, 1.0f), UnityEngine.Random.Range (0.0f, 1.0f), UnityEngine.Random.Range (0.0f, 1.0f)); toggleStatus.Add (path, true); path.ZeroValues (); } // Analyze paths Analyzer.PreparePaths (paths); //Analyzer.ComputePathsTimeValues (paths); //Analyzer.ComputePathsLengthValues (paths); //Analyzer.ComputePathsVelocityValues (paths); //Analyzer.ComputePathsLoSValues (paths, SpaceState.Editor.enemies, floor.collider.bounds.min, SpaceState.Editor.tileSize.x, SpaceState.Editor.tileSize.y, original, drawer.seenNeverSeen, drawer.seenNeverSeenMax); Analyzer.ComputePathsDangerValues (paths, SpaceState.Editor.enemies, floor.collider.bounds.min, SpaceState.Editor.tileSize.x, SpaceState.Editor.tileSize.y, original, drawer.seenNeverSeen, drawer.seenNeverSeenMax); //Analyzer.ComputeCrazyness (paths, original, Mathf.FloorToInt (crazySeconds / stepSize)); //Analyzer.ComputePathsVelocityValues (paths); SetupArrangedPaths (paths); } if (GUILayout.Button ("(DEBUG) Export Analysis")) { XmlSerializer ser = new XmlSerializer (typeof(MetricsRoot), new Type[] { typeof(PathResults), typeof(PathValue), typeof(Value) }); MetricsRoot root = new MetricsRoot (); foreach (Path path in paths) { root.everything.Add (new PathResults (path, Analyzer.pathMap [path])); } using (FileStream stream = new FileStream ("pathresults.xml", FileMode.Create)) { ser.Serialize (stream, root); stream.Flush (); stream.Close (); } } if (GUILayout.Button ("(DEBUG) Compute clusters")) { ComputeClusters (); } #region Paths values display seeByTime = EditorGUILayout.Foldout (seeByTime, "Paths by Time"); if (seeByTime && arrangedByTime != null) { for (int i = 0; i < arrangedByTime.Count; i++) { EditorGUILayout.BeginHorizontal (); EditorGUILayout.FloatField (arrangedByTime [i].name, arrangedByTime [i].time); toggleStatus [arrangedByTime [i]] = EditorGUILayout.Toggle ("", toggleStatus [arrangedByTime [i]], GUILayout.MaxWidth (20f)); EditorGUILayout.ColorField (arrangedByTime [i].color, GUILayout.MaxWidth (40f)); EditorGUILayout.EndHorizontal (); } } seeByLength = EditorGUILayout.Foldout (seeByLength, "Paths by Length"); if (seeByLength && arrangedByLength != null) { for (int i = 0; i < arrangedByLength.Count; i++) { EditorGUILayout.BeginHorizontal (); EditorGUILayout.FloatField (arrangedByLength [i].name, arrangedByLength [i].length2d); toggleStatus [arrangedByLength [i]] = EditorGUILayout.Toggle ("", toggleStatus [arrangedByLength [i]], GUILayout.MaxWidth (20f)); EditorGUILayout.ColorField (arrangedByLength [i].color, GUILayout.MaxWidth (40f)); EditorGUILayout.EndHorizontal (); } } seeByDanger = EditorGUILayout.Foldout (seeByDanger, "Paths by Danger (A*)"); if (seeByDanger && arrangedByDanger != null) { for (int i = 0; i < arrangedByDanger.Count; i++) { EditorGUILayout.BeginHorizontal (); EditorGUILayout.FloatField (arrangedByDanger [i].name, arrangedByDanger [i].danger); toggleStatus [arrangedByDanger [i]] = EditorGUILayout.Toggle ("", toggleStatus [arrangedByDanger [i]], GUILayout.MaxWidth (20f)); EditorGUILayout.ColorField (arrangedByDanger [i].color, GUILayout.MaxWidth (40f)); EditorGUILayout.EndHorizontal (); } } seeByDanger3 = EditorGUILayout.Foldout (seeByDanger3, "Paths by Danger 3 (A*)"); if (seeByDanger3 && arrangedByDanger3 != null) { for (int i = 0; i < arrangedByDanger3.Count; i++) { EditorGUILayout.BeginHorizontal (); EditorGUILayout.FloatField (arrangedByDanger3 [i].name, arrangedByDanger3 [i].danger3); toggleStatus [arrangedByDanger3 [i]] = EditorGUILayout.Toggle ("", toggleStatus [arrangedByDanger3 [i]], GUILayout.MaxWidth (20f)); EditorGUILayout.ColorField (arrangedByDanger3 [i].color, GUILayout.MaxWidth (40f)); EditorGUILayout.EndHorizontal (); } } seeByDanger3Norm = EditorGUILayout.Foldout (seeByDanger3Norm, "Paths by Danger 3 (A*) (normalized)"); if (seeByDanger3Norm && arrangedByDanger3Norm != null) { for (int i = 0; i < arrangedByDanger3Norm.Count; i++) { EditorGUILayout.BeginHorizontal (); EditorGUILayout.FloatField (arrangedByDanger3Norm [i].name, arrangedByDanger3Norm [i].danger3Norm); toggleStatus [arrangedByDanger3Norm [i]] = EditorGUILayout.Toggle ("", toggleStatus [arrangedByDanger3Norm [i]], GUILayout.MaxWidth (20f)); EditorGUILayout.ColorField (arrangedByDanger3Norm [i].color, GUILayout.MaxWidth (40f)); EditorGUILayout.EndHorizontal (); } } seeByLoS = EditorGUILayout.Foldout (seeByLoS, "Paths by Line of Sight (FoV)"); if (seeByLoS && arrangedByLoS != null) { for (int i = 0; i < arrangedByLoS.Count; i++) { EditorGUILayout.BeginHorizontal (); EditorGUILayout.FloatField (arrangedByLoS [i].name, arrangedByLoS [i].los); toggleStatus [arrangedByLoS [i]] = EditorGUILayout.Toggle ("", toggleStatus [arrangedByLoS [i]], GUILayout.MaxWidth (20f)); EditorGUILayout.ColorField (arrangedByLoS [i].color, GUILayout.MaxWidth (40f)); EditorGUILayout.EndHorizontal (); } } seeByLoS3 = EditorGUILayout.Foldout (seeByLoS3, "Paths by Line of Sight 3 (FoV)"); if (seeByLoS3 && arrangedByLoS3 != null) { for (int i = 0; i < arrangedByLoS3.Count; i++) { EditorGUILayout.BeginHorizontal (); EditorGUILayout.FloatField (arrangedByLoS3 [i].name, arrangedByLoS3 [i].los3); toggleStatus [arrangedByLoS3 [i]] = EditorGUILayout.Toggle ("", toggleStatus [arrangedByLoS3 [i]], GUILayout.MaxWidth (20f)); EditorGUILayout.ColorField (arrangedByLoS3 [i].color, GUILayout.MaxWidth (40f)); EditorGUILayout.EndHorizontal (); } } seeByLoS3Norm = EditorGUILayout.Foldout (seeByLoS3Norm, "Paths by Line of Sight 3 (FoV) (normalized)"); if (seeByLoS3Norm && arrangedByLoS3Norm != null) { for (int i = 0; i < arrangedByLoS3Norm.Count; i++) { EditorGUILayout.BeginHorizontal (); EditorGUILayout.FloatField (arrangedByLoS3Norm [i].name, arrangedByLoS3Norm [i].los3Norm); toggleStatus [arrangedByLoS3Norm [i]] = EditorGUILayout.Toggle ("", toggleStatus [arrangedByLoS3Norm [i]], GUILayout.MaxWidth (20f)); EditorGUILayout.ColorField (arrangedByLoS3Norm [i].color, GUILayout.MaxWidth (40f)); EditorGUILayout.EndHorizontal (); } } seeByCrazy = EditorGUILayout.Foldout (seeByCrazy, "Paths by Crazyness"); if (seeByCrazy && arrangedByCrazy != null) { for (int i = 0; i < arrangedByCrazy.Count; i++) { EditorGUILayout.BeginHorizontal (); EditorGUILayout.FloatField (arrangedByCrazy [i].name, arrangedByCrazy [i].crazy); toggleStatus [arrangedByCrazy [i]] = EditorGUILayout.Toggle ("", toggleStatus [arrangedByCrazy [i]], GUILayout.MaxWidth (20f)); EditorGUILayout.ColorField (arrangedByCrazy [i].color, GUILayout.MaxWidth (40f)); EditorGUILayout.EndHorizontal (); } } seeByVelocity = EditorGUILayout.Foldout (seeByVelocity, "Paths by Velocity Changes"); if (seeByVelocity && arrangedByVelocity != null) { for (int i = 0; i < arrangedByVelocity.Count; i++) { EditorGUILayout.BeginHorizontal (); EditorGUILayout.FloatField (arrangedByVelocity [i].name, arrangedByVelocity [i].velocity); toggleStatus [arrangedByVelocity [i]] = EditorGUILayout.Toggle ("", toggleStatus [arrangedByVelocity [i]], GUILayout.MaxWidth (20f)); EditorGUILayout.ColorField (arrangedByVelocity [i].color, GUILayout.MaxWidth (40f)); EditorGUILayout.EndHorizontal (); } } #endregion #endregion // ---------------------------------- #region Temp Player setup if (playerNode == null) { playerNode = GameObject.Find ("TempPlayerNode"); if (playerNode == null) { playerNode = new GameObject ("TempPlayerNode"); playerNode.hideFlags = HideFlags.HideAndDontSave; } } if (playerPrefab != null) { foreach (KeyValuePair<Path, bool> p in toggleStatus) { if (p.Value) { if (!players.ContainsKey (p.Key)) { GameObject player = GameObject.Instantiate (playerPrefab) as GameObject; player.transform.position.Set (p.Key.points [0].x, 0f, p.Key.points [0].y); player.transform.parent = playerNode.transform; players.Add (p.Key, player); Material m = new Material (player.renderer.sharedMaterial); m.color = p.Key.color; player.renderer.material = m; player.hideFlags = HideFlags.HideAndDontSave; } else { players [p.Key].SetActive (true); } } else { if (players.ContainsKey (p.Key)) { players [p.Key].SetActive (false); } } } } #endregion EditorGUILayout.EndScrollView (); // ---------------------------------- if (drawer != null) { drawer.timeSlice = timeSlice; drawer.drawHeatMap = drawHeatMap; drawer.drawMap = drawMap; drawer.drawFoVOnly = drawFoVOnly; drawer.drawNeverSeen = drawNeverSeen; drawer.drawPath = drawPath; drawer.drawCombatLines = drawCombatLines; drawer.paths = toggleStatus; drawer.textDraw = textDraw; } if (original != null && lastTime != timeSlice) { lastTime = timeSlice; UpdatePositions (timeSlice, mapper); } SceneView.RepaintAll (); }
public List<Node> Compute(int startX, int startY, int endX, int endY, Cell[][][] matrix, float playerSpeed) { this.speed = 1.0d / playerSpeed; try { Priority_Queue.IPriorityQueue<Node> heap2 = new Priority_Queue.HeapPriorityQueue<Node> (1000000); List<Node> closed = new List<Node> (); // Initialize our version of the matrix (can we skip this?) Node[][][] newMatrix = new Node[matrix.Length][][]; for (int t=0; t<matrix.Length; t++) { newMatrix [t] = new Node[matrix [t].Length][]; for (int x = 0; x < matrix [t].Length; x++) { newMatrix [t] [x] = new Node[matrix [t] [x].Length]; for (int y = 0; y < matrix [t] [x].Length; y++) { newMatrix [t] [x] [y] = new Node (); newMatrix [t] [x] [y].parent = null; newMatrix [t] [x] [y].cell = matrix [t] [x] [y]; newMatrix [t] [x] [y].x = x; newMatrix [t] [x] [y].y = y; newMatrix [t] [x] [y].t = t; } } } // Do the work for the first cell before firing the algorithm start = newMatrix [0] [startX] [startY]; end = newMatrix [0] [endX] [endY]; start.parent = null; start.visited = true; start.accSpeed = speed - Math.Floor(speed); foreach (Node n in getAdjacent(start, newMatrix)) { n.parent = start; float fVal = f (n); n.Priority = fVal; heap2.Enqueue (n, fVal); } while (heap2.Count != 0) { Node first = heap2.Dequeue (); if (first.x == end.x && first.y == end.y) { end = newMatrix [first.t] [end.x] [end.y]; break; } first.visited = true; foreach (Node m in getAdjacent(first, newMatrix)) { float currentG = g (first) + h (m, first); float gVal = g (m); if (m.visited) { if (gVal > currentG) { m.parent = first; acc(m); } } else { if (!heap2.Contains (m)) { m.parent = first; m.Priority = f (m); heap2.Enqueue (m, m.Priority); acc(m); } else { if (gVal > currentG) { m.parent = first; m.Priority = f (m); heap2.UpdatePriority (m, m.Priority); acc(m); } } } } } // Creates the result list Node e = end; List<Node> points = new List<Node> (); while (e != null) { points.Add (e); e = e.parent; } points.Reverse (); // If we didn't find a path if (points.Count == 1) points.Clear (); return points; } catch (System.Exception e) { Debug.Log (e.Message); Debug.Log (e.StackTrace); Debug.Log ("ERROR 2"); return null; } }
private static bool SetOrUpdateCellValue(SheetData sheetData, uint rowNumber, uint columnNumber, Type datatype, object value, DefaultCellStyle defaultCellStyle, uint customStyle = 0) { if (sheetData != null && value != null && datatype != null) { //创建cell. //0.不存在row,建立row,插入cell. //0.row存在1.删除cell.2.是否有比这个cell更大的cell,有插入大cell之前.否则直接附加在row后面. string cellRefrence = GetCellReference(rowNumber, columnNumber); IEnumerable <Row> equalOrbiggerRows = sheetData.Elements <Row>().Where(x => x.RowIndex >= rowNumber); Row equalRow = null, biggerRow = null; if (equalOrbiggerRows != null && equalOrbiggerRows.Count() > 0 && equalOrbiggerRows.First().RowIndex == rowNumber) { equalRow = equalOrbiggerRows.First(); } else if (equalOrbiggerRows != null && equalOrbiggerRows.Count() > 0 && equalOrbiggerRows.First().RowIndex > rowNumber) { biggerRow = equalOrbiggerRows.First(); } if (equalRow != null)//存在row. 1.是否存在cell,存在跟新,不存在建立新cell.2.是否有比这个cell更大的cell,有插入大cell之前.否则直接附加在Row后面. { IEnumerable <Cell> equalOrbiggerCells = equalRow.Elements <Cell>().Where(x => x.CellReference >= new StringValue(cellRefrence)); Cell equalCell = null; Cell biggerCell = null; if (equalOrbiggerCells != null && equalOrbiggerCells.Count() > 0 && equalOrbiggerCells.First().CellReference == cellRefrence) { equalCell = equalOrbiggerCells.First(); } else if (equalOrbiggerCells != null && equalOrbiggerCells.Count() > 0 && equalOrbiggerCells.First().CellReference > new StringValue(cellRefrence)) { biggerCell = equalOrbiggerCells.First(); } Cell newCell = createCell(cellRefrence, datatype, value, defaultCellStyle, customStyle); if (equalCell != null) { equalOrbiggerRows.First().ReplaceChild(newCell, equalCell); } else { if (biggerCell != null) { equalOrbiggerRows.First().InsertBefore(newCell, biggerCell); } else { equalOrbiggerRows.First().Append(newCell); } } } else//不存在.新建row and cell. { Row newrow = new Row(); newrow.RowIndex = rowNumber; Cell theCell = IncOpenExcel.createCell(cellRefrence, datatype, value, defaultCellStyle, customStyle); if (theCell != null) { newrow.Append(theCell); } if (biggerRow != null) { sheetData.InsertBefore(newrow, equalOrbiggerRows.First());//插入的行不是最大的,插到比它大的前面. } else { sheetData.Append(newrow);; //插入的行是最大的,直接附加到最后 } } } return(true); }
public void OnSceneGUI() { // Update drawer if (drawer != null) drawer.editGrid = editGrid; // Stop if needed if (!editGrid) { didUpdate = false; return; } // Create grid if (grid == null || grid.Length != MapperWindowEditor.gridSize) { grid = new Cell[MapperWindowEditor.gridSize][]; for (int i = 0; i < MapperWindowEditor.gridSize; i++) grid [i] = new Cell[MapperWindowEditor.gridSize]; } // Prepare holders if (mapper == null) { mapper = (Mapper)target; } if (drawer == null) { drawer = mapper.gameObject.GetComponent<MapperEditorDrawer> (); } drawer.editingGrid = grid; // Update Scene if (!didUpdate) { mapper.ComputeTileSize (SpaceState.Editor, mapper.collider.bounds.min, mapper.collider.bounds.max, MapperWindowEditor.gridSize, MapperWindowEditor.gridSize); drawer.tileSize.Set (SpaceState.Editor.tileSize.x, SpaceState.Editor.tileSize.y); drawer.zero.Set (SpaceState.Editor.floorMin.x, SpaceState.Editor.floorMin.z); didUpdate = true; } // Raycast Event current = Event.current; if (current != null && EventType.KeyDown == current.type) { Ray ray = HandleUtility.GUIPointToWorldRay (current.mousePosition); RaycastHit hit; if (Physics.Raycast (ray, out hit, Mathf.Infinity, 1 << LayerMask.NameToLayer ("Floor"))) { if (hit.transform.CompareTag ("Floor")) { Vector2 pos = new Vector2 ((hit.point.x - hit.collider.bounds.min.x) / SpaceState.Editor.tileSize.x, (hit.point.z - hit.collider.bounds.min.x) / SpaceState.Editor.tileSize.y); Cell c = grid [(int)pos.x] [(int)pos.y]; if (c == null) { c = new Cell (); grid [(int)pos.x] [(int)pos.y] = c; } switch (current.keyCode) { case KeyCode.Alpha0: grid [(int)pos.x] [(int)pos.y] = null; break; case KeyCode.Alpha1: c.safe = true; break; case KeyCode.Alpha2: c.blocked = true; break; case KeyCode.Alpha3: c.noisy = true; break; case KeyCode.Alpha4: c.waypoint = true; break; case KeyCode.U: c.cluster = 0; break; case KeyCode.Alpha6: c.cluster |= 1; break; case KeyCode.Alpha7: c.cluster |= 2; break; case KeyCode.Alpha8: c.cluster |= 4; break; case KeyCode.Alpha9: c.cluster |= 8; break; case KeyCode.Keypad4: c.cluster |= 8; break; case KeyCode.Keypad5: c.cluster |= 16; break; case KeyCode.Keypad6: c.cluster |= 32; break; case KeyCode.Keypad7: c.cluster |= 64; break; case KeyCode.Keypad8: c.cluster |= 128; break; case KeyCode.Keypad9: c.cluster |= 256; break; } SceneView.RepaintAll (); } } } }
public List<Node> Compute(int startX, int startY, int endX, int endY, Cell[][] matrix, bool improve) { List<Node> opened = new List<Node> (); Priority_Queue.IPriorityQueue<Node> heap2 = new Priority_Queue.HeapPriorityQueue<Node> (600); List<Node> closed = new List<Node> (); // Initialize our version of the matrix (can we skip this?) Node[][] newMatrix = new Node[matrix.Length][]; for (int x = 0; x < matrix.Length; x++) { newMatrix [x] = new Node[matrix [x].Length]; for (int y = 0; y < matrix[x].Length; y++) { newMatrix [x] [y] = new Node (); newMatrix [x] [y].parent = null; newMatrix [x] [y].cell = matrix [x] [y]; newMatrix [x] [y].x = x; newMatrix [x] [y].y = y; } } // Do the work for the first cell before firing the algorithm start = newMatrix [startX] [startY]; end = newMatrix [endX] [endY]; closed.Add (start); foreach (Node c in getAdjacent(start, newMatrix)) { c.parent = start; if (improve) heap2.Enqueue (c, f (c)); else opened.Add (c); } while ((improve && heap2.Count > 0) || (!improve && opened.Count > 0)) { // Pick the closest to the goal Node minF = null; if (improve) { minF = heap2.Dequeue (); } else { for (int i = 0; i < opened.Count; i++) { if (minF == null || f (minF) > f (opened [i])) minF = opened [i]; } opened.Remove (minF); } closed.Add (minF); // Found it if (minF == end) break; foreach (Node adj in getAdjacent(minF, newMatrix)) { float soFar = g (minF) + h (adj, minF); // Create the links between cells (picks the best path) if (closed.Contains (adj)) { if (g (adj) > soFar) { adj.parent = minF; } } else { if ((improve && heap2.Contains (adj)) || (!improve && opened.Contains (adj))) { if (g (adj) > soFar) { adj.parent = minF; } } else { adj.parent = minF; if (improve) heap2.Enqueue (adj, f (adj)); else opened.Add (adj); } } } } // Creates the result list Node n = end; List<Node> points = new List<Node> (); while (n != null) { points.Add (n); n = n.parent; } points.Reverse (); // If we didn't find a path if (points.Count == 1) points.Clear (); return points; }
public List<Node> Compute(int startX, int startY, int endX, int endY, Cell[][][] matrix, int time, bool prob) { try{ Priority_Queue.IPriorityQueue<Node> heap2 = new Priority_Queue.HeapPriorityQueue<Node>(600); // Initialize our version of the matrix (can we skip this?) Node[][] newMatrix = new Node[matrix[0].Length][]; for (int x = 0; x < matrix [0].Length; x++) { newMatrix [x] = new Node[matrix [0] [x].Length]; for (int y = 0; y < matrix [0] [x].Length; y++) { newMatrix [x] [y] = new Node (); newMatrix [x] [y].parent = null; newMatrix [x] [y].cell = matrix [0] [x] [y]; newMatrix [x] [y].x = x; newMatrix [x] [y].y = y; } } enemyPathProb(newMatrix); // Do the work for the first cell before firing the algorithm start = newMatrix [startX] [startY]; end = newMatrix [endX] [endY]; start.parent=null; start.visited=true; foreach (Node n in getAdjacent(start, newMatrix)) { n.t=time; n.parent = start; float fVal = f (n); n.Priority = fVal; heap2.Enqueue(n,fVal); } while(heap2.Count != 0){ Node first = heap2.Dequeue(); if(first == end) break; first.visited=true; double temprt = 1; List<Node> adjs = getAdjacent(first,newMatrix); foreach(Node m in adjs){ float currentG = (float)(g (first) + h (first,m, ref temprt)); if(m.visited){ if(g (m)>currentG){ m.parent=first; m.t = first.t+time; } } else{ if( !heap2.Contains(m)){ m.parent = first; m.t= first.t +time; m.Priority = (float)temprt*f(m); heap2.Enqueue(m, m.Priority); } else { float gVal = g (m); if(gVal>currentG){ m.parent= first; m.t = first.t+time; m.Priority= (float)temprt *f (m); heap2.UpdatePriority(m, m.Priority); } } } } } // Creates the result list Node l = end; List<Node> points = new List<Node> (); while (l != null) { points.Add (l); l = l.parent; } points.Reverse (); // If we didn't find a path if (points.Count == 1) points.Clear (); return points; }catch(System.Exception e){ Debug.Log (e.Message); Debug.Log (e.StackTrace); Debug.Log ("ERROR 2"); return null; } }
public bool HasLOS(Cell[][] im, Vector2 p1, Vector2 p2, Vector2 res, int x, int y) { // Perform the DDA line algorithm // Based on http://lodev.org/cgtutor/raycasting.html //which box of the map we're in int mapX = Mathf.FloorToInt (p2.x); int mapY = Mathf.FloorToInt (p2.y); //length of ray from current position to next x or y-side float sideDistX; float sideDistY; //length of ray from one x or y-side to next x or y-side float deltaDistX = Mathf.Sqrt (1 + (res.y * res.y) / (res.x * res.x)); float deltaDistY = Mathf.Sqrt (1 + (res.x * res.x) / (res.y * res.y)); //what direction to step in x or y-direction (either +1 or -1) int stepX; int stepY; //calculate step and initial sideDist if (res.x < 0) { stepX = -1; sideDistX = (p2.x - mapX) * deltaDistX; } else { stepX = 1; sideDistX = (mapX + tileSizeX - p2.x) * deltaDistX; } if (res.y < 0) { stepY = -1; sideDistY = (p2.y - mapY) * deltaDistY; } else { stepY = 1; sideDistY = (mapY + tileSizeZ - p2.y) * deltaDistY; } // Don't skip seen cells bool done = im [x] [y].blocked; bool seen = false; //perform DDA while (!done) { //jump to next map square, OR in x-direction, OR in y-direction if (sideDistX < sideDistY) { sideDistX += deltaDistX; mapX += stepX; } else { sideDistY += deltaDistY; mapY += stepY; } if (Vector2.Distance (p2, new Vector2 (mapX, mapY)) > Vector2.Distance (p1, p2)) { seen = true; done = true; } // Check map boundaries if (mapX < 0 || mapY < 0 || mapX >= cellsX || mapY >= cellsZ) { seen = true; done = true; } else { //Check if ray has hit a wall if (im [mapX] [mapY].blocked) { done = true; } // End the algorithm if (x == mapX && y == mapY) { seen = true; done = true; } } } return seen; }
public bool HasLOS(Cell[][] im, Vector2 p1, Vector2 p2, Vector2 res) { return HasLOS (im, p1, p2, res, Mathf.FloorToInt (p1.x), Mathf.FloorToInt (p1.y)); }
public bool HasLOS(Cell[][] im, Vector2 p1, Vector2 p2) { return HasLOS (im, p1, p2, (p2 - p1).normalized); }
public Node Los3D(Cell[][][] im, Node start, Node end, Cell[][][][] seenList = null) { Vector3 pos = new Vector3 (start.x, start.y, start.t); Vector3 p = new Vector3 (end.x, end.y, end.t); Vector3 res = (p - pos).normalized; if (seenList == null) seenList = new Cell[0][][][]; //which box of the map we're in int mapX = start.x; int mapY = start.y; int mapT = start.t; //length of ray from current position to next x or y-side float sideDistX; float sideDistY; float sideDistT; //length of ray from one x or y-side to next x or y-side float deltaDistX = 1 / Mathf.Abs (res.x); float deltaDistY = 1 / Mathf.Abs (res.y); float deltaDistT = 1 / Mathf.Abs (res.z); //what direction to step in x or y-direction (either +1 or -1) int stepX; int stepY; int stepT; //calculate step and initial sideDist if (res.x < 0) { stepX = -1; sideDistX = (pos.x - mapX) * deltaDistX; } else { stepX = 1; sideDistX = (mapX + 1 - pos.x) * deltaDistX; } if (res.y < 0) { stepY = -1; sideDistY = (pos.y - mapY) * deltaDistY; } else { stepY = 1; sideDistY = (mapY + 1 - pos.y) * deltaDistY; } if (res.z < 0) { stepT = -1; sideDistT = (pos.z - mapT) * deltaDistT; } else { stepT = 1; sideDistT = (mapT + 1 - pos.z) * deltaDistT; } bool done = false; Node result = null; //perform DDA while (!done) { //jump to next map square, OR in x-direction, OR in y-direction if (sideDistX <= sideDistY && sideDistX <= sideDistT) { sideDistX += deltaDistX; mapX += stepX; } else if (sideDistY <= sideDistT) { sideDistY += deltaDistY; mapY += stepY; } else { sideDistT += deltaDistT; mapT += stepT; } // Check map boundaries if (stepX == 1) { if (mapX > end.x) done = true; } else if (mapX < end.x) done = true; if (stepY == 1) { if (mapY > end.y) done = true; } else if (mapY < end.y) done = true; if (stepT == 1) { if (mapT > end.t) done = true; } else if (mapT < end.t) done = true; if (Vector3.Distance (p, new Vector3 (mapX, mapY, mapT)) > Vector3.Distance (p, pos)) { // Check for maximum distance done = true; } if (end.x == mapX && end.y == mapY) { // End the algorithm on reach done = true; } if (!done && !im[mapT][mapX][mapY].safe) { // Check for ending conditions: safespot, blocked or seen by enemy bool ignored = true; if (im[mapT][mapX][mapY].blocked) ignored = false; else foreach (Cell[][][] map in seenList) if (map[mapT][mapX][mapY] != null) ignored = false; if (!ignored) { result = new Node(); result.t = mapT; result.x = mapX; result.y = mapY; result.cell = im[mapT][mapX][mapY]; done = true; } } } return result; }