private static void ExpandNode(Node current, NVector2 to, ref PriorityQueue <Node> openlist, ref HashSet <Node> closedlist, int heurFactor = 1) { for (int i = 0; i < NeighborOffset.Length; ++i) { var offset = NeighborOffset[i]; var child = new Node(current.point + offset); child.parent = current; // check if point available if (!GridUtil.IsPassable(child.point)) { continue; } if (closedlist.Contains(child)) { continue; } child.distance = current.distance + 1; var heur = heurFactor * (int)currentHeuristicFunc(child.point, to); if (openlist.Contains(child, heur)) { continue; } openlist.Enqueue(child, heur); } }
public static List <NVector2> Area(NVector2 from, int max_depth, bool includeStart = false) { Queue <Node> openlist = new Queue <Node>(); HashSet <Node> closedlist = new HashSet <Node>(); openlist.Enqueue(new Node(from)); do { var current = openlist.Dequeue(); closedlist.Add(current); if (current.distance >= max_depth) { closedlist.Remove(current); break; } ExpandNode(current, ref openlist, ref closedlist); } while (openlist.Count > 0); var outlist = closedlist.Select(n => n.point).ToList(); outlist.Remove(from); return(outlist); }
public static List <NVector2> Path(NVector2 from, NVector2 to, int max_depth = 10, int distance = 0, int heurFactor = 1) { PriorityQueue <Node> openlist = new PriorityQueue <Node>(); HashSet <Node> closedlist = new HashSet <Node>(); openlist.Enqueue(new Node(from)); distance = GridUtil.IsPassable(to) ? 0 : distance; do { var current = openlist.Dequeue(); if (current.point == to || currentHeuristicFunc(current.point, to) <= distance) { List <NVector2> outlist = new List <NVector2>(); outlist.Add(current.point); while (current.parent != null) { current = current.parent; outlist.Insert(0, current.point); } return(outlist); } closedlist.Add(current); if (current.distance >= max_depth) { break; } ExpandNode(current, to, ref openlist, ref closedlist, heurFactor: heurFactor); } while (!openlist.Empty); return(new List <NVector2>()); }
void OnTriggerEnter(Collider other) { MonoBehaviour c = other.GetComponent <EnemyActor>(); if (c != null) { roomEnemies.Add((EnemyActor)c); positions.Add(c.transform.position); Physics.IgnoreCollision(this.GetComponent <Collider>(), c.GetComponent <Collider>()); if (GameTickManager.Instance.ActiveRoom == this) { c.gameObject.SetActive(false); } return; } c = other.GetComponent <PlayerActor>(); if (c != null) { GameTickManager.Instance.ActiveRoom = this; playerEnterTile = ((PlayerActor)c).GridPosition; return; } }
private void OnSceneGUI() { var up_quat = Quaternion.Euler(90, 0, 0); var points = serializedObject.FindProperty("waypoints").FindPropertyRelative("points"); Vector3 p1 = Vector3.zero, p2 = Vector3.zero; Handles.color = Color.red; for (int i = 0; i < points.arraySize; ++i) { var point = points.GetArrayElementAtIndex(i); var x = point.FindPropertyRelative("x").intValue; var y = point.FindPropertyRelative("y").intValue; p2 = GridUtil.GridToWorld(new Vector2(x, y)); if (i != 0) { Handles.DrawLine(p1, p2); } p1 = p2; Handles.RectangleHandleCap(i, p1, up_quat, 0.2f, EventType.Repaint); } // -------------- if (!visualmode) { return; } var plane = new Plane(Vector3.up, Vector3.zero); float enter; var ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); plane.Raycast(ray, out enter); var hitpoint = ray.GetPoint(enter); var tile = GridUtil.WorldToGrid(hitpoint); Handles.color = new Color(1f, 0.45f, 0f); Handles.DrawDottedLine(p1, GridUtil.GridToWorld(tile), 5); if (Handles.Button(GridUtil.GridToWorld(tile) + Vector3.up * 0.1f, up_quat, 0.5f, 0.5f, Handles.RectangleHandleCap)) { //active.Tiles[tile_y*active.TileMapWidth + tile_x] = selectedTile; //active.OnValidate(); var selected_point = new NVector2(tile); var pat = (target as PatrouilleBehaviour); if (pat.waypoints.points.Contains(selected_point)) { pat.waypoints.points.Remove(selected_point); } else { pat.waypoints.points.Add(selected_point); } SceneView.RepaintAll(); EditorUtility.SetDirty(target); } }
/// <returns>An A* Path to the Target, from the AI position, considering the Speed Attribute</returns> private List <NVector2> ClampedPathToTarget(NVector2 target) { var path = Astar.Path(actor.GridPosition, target, distance: 1); if (path.Count > actor.stats.currentStats.speed) { path = path.GetRange(0, actor.stats.currentStats.speed); } return(path); }
// public Vector2 currentWaypoint{ get { return waypoints.points[current]; } } void OnValidate() { var own_grid_pos = new NVector2(GridUtil.WorldToGrid(this.transform.position)); if (waypoints.points.Count < 1) { waypoints.points.Add(own_grid_pos); } else { if (waypoints.points[0] != own_grid_pos) { waypoints.points.Insert(0, own_grid_pos); } } }
public bool IsPlayerVisible() { if (visibleArea == null) { return(false); } var forward = new NVector2(this.transform.forward.To2DXZ()); var right = new NVector2(forward.y, -forward.x); var pgrid_pos = PlayerActor.Instance.GridPosition - enemyActor.GridPosition; var dx = right.x * pgrid_pos.x + right.y * pgrid_pos.y + visibleArea.GetLength(0) / 2; var dy = forward.x * pgrid_pos.x + forward.y * pgrid_pos.y; return(visibleArea.GetLength(0) > dx && dx >= 0 && visibleArea.GetLength(1) > dy && dy >= 0 && visibleArea[dx, dy]); }
public override void Update(ActionSelectorSM self) { var mesh = self.selectionCircleMesh; var enemiesInRange = GameTickManager.Instance.activeEnemies.Where( e => Astar.CalculateHeuristic(e.GridPosition, PlayerActor.Instance.GridPosition) < PlayerActor.Instance.stats.currentStats.awareness).ToList(); var ray = Camera.main.ScreenPointToRay(Input.mousePosition); float enter; if (!plane.Raycast(ray, out enter)) { return; } var field = new NVector2(GridUtil.WorldToGrid(ray.GetPoint(enter))); int?is_valid = null; for (var i = 0; i < enemiesInRange.Count; ++i) { if (enemiesInRange[i].GridPosition == field) { is_valid = i; Graphics.DrawMesh(mesh, Matrix4x4.Translate(enemiesInRange[i].transform.position), self.selectionCircleMaterial, 0, Camera.current, 0, activeCircle); } else { Graphics.DrawMesh(mesh, Matrix4x4.Translate(enemiesInRange[i].transform.position), self.selectionCircleMaterial, 0, Camera.current, 0); } } if (Input.GetMouseButtonDown(0) && is_valid != null) { var enemy = enemiesInRange[(int)is_valid]; var selectedAction = new AttackAction(PlayerActor.Instance.gameObject, enemy.gameObject, enemy.attackPrefab, 1); onActionSelectedObservable.OnNext(selectedAction); } }
public override void Update(ActionSelectorSM self) { if (mesh == null || meshMaterial == null) { return; } Graphics.DrawMesh(mesh, Matrix4x4.Translate(self.transform.position), meshMaterial, 0, Camera.current, 0, new MaterialPropertyBlock(), ShadowCastingMode.Off, receiveShadows: false); /* replace by input provider: */ var ray = Camera.main.ScreenPointToRay(Input.mousePosition); float enter; if (plane.Raycast(ray, out enter)) { var field = new NVector2(GridUtil.WorldToGrid(ray.GetPoint(enter))); fieldSelector.transform.position = Vector3.MoveTowards(fieldSelector.transform.position, GridUtil.GridToWorld(field), 32 * Time.deltaTime); var sel = new NVector2(GridUtil.WorldToGrid(fieldSelector.transform.position)); if (Math.Abs(sel.x - field.x + sel.y - field.y) > 0) { return; } var is_valid = walkableTiles.Contains(sel); fieldSelector.SetActive(is_valid); if (Input.GetMouseButtonDown(0) && is_valid) { var path = Astar.Path(PlayerActor.Instance.GridPosition, sel, heurFactor: 2); selectedAction = new MoveAction(PlayerActor.Instance.gameObject, path); onActionSelectedObservable.OnNext(selectedAction); } } }
private bool dirty = true; // quick hack private void Update() { NVector2 gridpos = new NVector2(GridUtil.WorldToGrid(this.transform.position)); Vector3 desiredWorldPos = GridUtil.GridToWorld(desiredPosition); animator.SetBool("walking", false); if (desiredWorldPos.Approx(transform.position, MOVEMENT_DEADZONE_SQR)) { // reached field this.transform.position = GridUtil.GridToWorld(desiredPosition); if (dirty) { onTileEnterAsObservable.OnNext(true); } dirty = false; if (nextPosition == null) { return; } if (nextPosition == desiredPosition) { onTileEnterAsObservable.OnNext(false); return; } desiredPosition = (NVector2)nextPosition; nextPosition = null; dirty = true; dir = (desiredPosition - gridpos); var mg = (dir.x * dir.x + dir.y * dir.y); if (mg != 1) { if (mg == 0) { return; // standing still !? } throw new ArgumentException(this.name + ": Unknown direction: " + dir); } } // rotate towards dir: var desiredRotation = Quaternion.LookRotation(((Vector2)dir).To3DXZ(), Vector3.up); var desiredAngle = Quaternion.Angle(transform.rotation, desiredRotation); if (desiredAngle > 5) { var rot = Quaternion.RotateTowards(transform.rotation, desiredRotation, 90 * rotationSpeedFactor * Time.deltaTime); transform.rotation = rot; rotationSpeedFactor += 16 * Time.deltaTime; } else { animator.SetBool("walking", true); transform.rotation = desiredRotation; rotationSpeedFactor = 1; //transform.position = transform.position + (((Vector2)dir) * Time.deltaTime * speed).To3DXZ(); transform.position = Vector3.MoveTowards(transform.position, desiredWorldPos, Time.deltaTime * speed); } }
public void ResetDesiredPosition() { desiredPosition = new NVector2(GridUtil.WorldToGrid(this.transform.position)); }
public static bool[,] CalculateVisibleArea(NVector2 position, int range, NVector2 forward, float viewAngle = 0) { var right = new NVector2(forward.y, -forward.x); // step 1: get opaque tiles in region bool[,] opaques = new bool[(range + 1) * 2 + 1, 1 + (range + 1) + 1]; // pos_tile = [range+1, 1] for (int dx = -(range + 1); dx <= (range + 1); ++dx) { for (int dy = -1; dy <= (range + 1); ++dy) { var pos = position + forward * dy + right * dx; var b = GridUtil.IsStaticObstacle(pos); // Debug.Log(dx + ", " + dy + ": " + b); opaques[(range + 1) + dx, dy + 1] = b; } } // step 2: get tile corners: // a corner is true if any of the 4 tiles that the corner belongs to are true // a corner is true if you cant look through it var range2 = range * range; bool[,] corners = new bool[opaques.GetLength(0) - 1, opaques.GetLength(1) - 1]; for (int x = 0; x < corners.GetLength(0); ++x) { for (int y = 0; y < corners.GetLength(1); ++y) { corners[x, y] = opaques[x, y] | opaques[x + 1, y] | opaques[x, y + 1] | opaques[x + 1, y + 1]; corners[x, y] |= (range2 <= sqrt_vector_length(x - 0.5f - range, y - 0.5f)); // corners[x, y] |= Math.Abs((new Vector2(x - 0.5f - range, y - 0.5f).normalized).y) <= viewAngle; } } /* GameTickManager.Instance.Gizmos += () => { * * * for (int x = 0; x < corners.GetLength(0); ++x) { * for (int y = 0; y < corners.GetLength(1); ++y) { * var wpos = GridUtil.GridToWorld((position + forward*y + right*(x-range))); * Gizmos.color = corners[x,y] ? Color.magenta : Color.cyan; * * if(corners[x,y] && (range2 <= sqrt_vector_length(x - 0.5f - range, y - 0.5f) )) * Gizmos.color = Color.red; * Gizmos.DrawCube(wpos + new Vector3(0.5f, 0, 0.5f), Vector3.one * 0.15f); * } * } * * * Debug.Break(); * };*/ // step 3: visible tiles: bool[,] visibles = new bool[range * 2 + 1, range + 1]; NVector2 pos_tile = new NVector2(range, 0); for (int x = 0; x < visibles.GetLength(0); ++x) { for (int y = 0; y < visibles.GetLength(1); ++y) { if (opaques[x + 1, y + 1]) { visibles[x, y] = false; continue; } if ((new Vector2(x - range, y).normalized).y <= viewAngle) { visibles[x, y] = false; continue; } if (CornersOfTile(x, y).All((xy) => corners[xy.x, xy.y])) { visibles[x, y] = false; continue; } var b = LineOfSight(pos_tile.x, pos_tile.y, x, y, ref corners); visibles[x, y] = b; } } /* * GameTickManager.Instance.Gizmos += () => { * * for (int x = 0; x < visibles.GetLength(0); ++x) { * for (int y = 0; y < visibles.GetLength(1); ++y) { * var wpos = GridUtil.GridToWorld((position + forward*y + right*(x-range))); * * if (opaques[x + 1, y + 1]) { * Gizmos.color = Color.black; * Gizmos.DrawWireCube(wpos , Vector3.one * 0.15f); * continue; * } * if (!visibles[x, y]) { * Gizmos.color = Color.red; * Gizmos.DrawWireCube(wpos , Vector3.one * 0.15f); * continue; * } * Gizmos.color = Color.cyan; * Gizmos.DrawWireCube(wpos , Vector3.one * 0.15f); * continue; * * } * } * * Debug.Break(); * }; */ return(visibles); }
public static float CalculateHeuristic(NVector2 from, NVector2 to) { //float schnellerAberUngenauer = 1f; //return Mathf.Abs(schnellerAberUngenauer * ((to.x - from.x) + (to.y - from.y))); return(Mathf.Abs(to.x - from.x) + Mathf.Abs(to.y - from.y)); }
public Node(NVector2 point, int dis = 0) { this.point = point; this.distance = dis; }
// Update is called once per frame void Update() { var activeEnemies = GameTickManager.Instance.activeEnemies; var ray = Camera.main.ScreenPointToRay(Input.mousePosition); float enter; if (plane.Raycast(ray, out enter)) { var field = new NVector2(GridUtil.WorldToGrid(ray.GetPoint(enter))); var b = false; foreach (var enemy in activeEnemies) { if (field != enemy.GridPosition) { continue; } var s = enemy.stats.currentStats; stats.text = $@"<color=white>HP{"\t"}<color=red>{new string('/', s.hp)} <color=white>Dmg{"\t"}<color=red>{new string('/', s.atk)} <color=white>SPD{"\t"}<color=red>{new string('/', s.speed)} "; ((RectTransform)stats.transform.parent).position = Camera.main.WorldToScreenPoint(enemy.transform.position); ((RectTransform)stats.transform.parent).position += Vector3.up * 50; b = true; break; } stats.transform.parent.gameObject.SetActive(b); } foreach (var key in indicators.Keys.Where(k => !activeEnemies.Contains(k))) { indicators[key].gameObject.SetActive(false); } foreach (var enemy in activeEnemies) { if (!indicators.ContainsKey(enemy)) { var go = GameObject.Instantiate(prefab, parent: this.transform); indicators.Add(enemy, go.GetComponent <Image>()); } if (enemy.State == AIState.Alterted) { int i = enemy.visibleArea.IsPlayerVisible() ? 2 : 1; indicators[enemy].gameObject.SetActive(true); indicators[enemy].sprite = AlertStates[i]; } else { indicators[enemy].gameObject.SetActive(false); } var sp = Camera.main.WorldToScreenPoint(enemy.transform.position + Vector3.up * 2.5f); indicators[enemy].transform.position = sp; } }
public bool Equals(NVector2 other) { return(x == other.x && y == other.y); }