public NodePathFinderPlatformer getEdge(NodePathFinderPlatformer node) { float r = Random.value; if (r < 0.3f) { // right while (node.right != null) { node = node.right; } return(node); } else if (r < 0.3f) { // left while (node.left != null) { node = node.left; } return(node); } else { if (node.left != null) { return(node.left); } else if (node.right != null) { return(node.right); } return(node); } }
public NodePathFinderPlatformer bfs(NodePathFinderPlatformer node, NodePathFinderPlatformer target) { // return last node before reaching target if (node == target) { return(target); } List <NodePathFinderPlatformer> level = new List <NodePathFinderPlatformer>(); HashSet <NodePathFinderPlatformer> vis = new HashSet <NodePathFinderPlatformer>(); Queue <NodePathFinderPlatformer> q = new Queue <NodePathFinderPlatformer>(); q.Enqueue(node); vis.Add(node); while (q.Count > 0) { NodePathFinderPlatformer u = q.Peek(); q.Dequeue(); List <NodePathFinderPlatformer> adj = u.getAdjNodes(); foreach (NodePathFinderPlatformer v in adj) { if (v == target) { return(u); } if (!vis.Contains(v)) { vis.Add(v); q.Enqueue(v); } } } return(null); }
public bool isOnSamePlatform(NodePathFinderPlatformer a, NodePathFinderPlatformer b) { Queue <NodePathFinderPlatformer> q = new Queue <NodePathFinderPlatformer>(); HashSet <NodePathFinderPlatformer> vis = new HashSet <NodePathFinderPlatformer>(); q.Enqueue(a); while (q.Count > 0) { NodePathFinderPlatformer u = q.Peek(); q.Dequeue(); vis.Add(u); if (u == b) { return(true); } if (u.left != null && !vis.Contains(u.left)) { q.Enqueue(u.left); } if (u.right != null && !vis.Contains(u.right)) { q.Enqueue(u.right); } } return(false); }
public NodePathFinderPlatformer findClosest(Vector3 pos) { NodePathFinderPlatformer closest = null; float minDiff = 99999999f; float targetY = pos.y; int idx = xToCol(pos.x); // Debug.Log($"find closest {idx}"); if (idx < 0 || idx > nodes.Count) { return(null); } foreach (NodePathFinderPlatformer node in nodes[idx]) { // Debug.Log(node.transform.position.y); // if (node.transform.position.y <= pos.y) return node; float nodey = node.transform.position.y; if (nodey > pos.y) { continue; } if (Mathf.Abs(nodey - targetY) < minDiff) { closest = node; minDiff = Mathf.Abs(nodey - targetY); } } if (closest != null) { return(closest); } return(closest); }
public void GetOptimalPath(Enemy enemy, Transform target) { int idx = xToCol(transform.position.x); NodePathFinderPlatformer dst = findClosest(target.position); NodePathFinderPlatformer src = findClosest(enemy.transform.position); if (dst == null || src == null) { enemy.BeIdle(); return; } // Debug.Log(dst.transform.position); // Debug.Log(src.transform.position); // find path if (isOnSamePlatform(src, dst)) { // Debug.Log("is on same platform"); if (target.position.x - enemy.transform.position.x > 0) { enemy.MoveRight(); } else { enemy.MoveLeft(); } return; } // NodePathFinderPlatformer jumpTarget = getEdge(dst); // Vector2 jumpTerm = new Vector2(jumpTarget.transform.position.x, jumpTarget.transform.position.y); // enemy.StartJumpThrough(jumpTerm + Vector2.up * 0.8f); enemy.StartJumpThrough(target.position + Vector3.up * 1.0f + Vector3.right * (-0.5f + Random.value) * 3f); // NodePathFinderPlatformer next = bfs(src, dst); // // Debug.Log("next"); // // Debug.Log(next.transform.position); // if (next == null) { // enemy.BeIdle(); // } else if (next == src.jumpLeft) { // enemy.Jump(); // enemy.MoveLeft(); // } else if (next == src.jumpRight) { // enemy.Jump(); // enemy.MoveRight(); // } else if (next == src.left || next == src.fallLeft) { // enemy.MoveLeft(); // } else if (next == src.right || next == src.fallRight) { // enemy.MoveRight(); // } }
public void AddFallNeighbors(NodePathFinderPlatformer node, int col_idx) { // Debug.Log("add fall neighbors"); if (col_idx > 0) { // left if (node.left == null) { float y = node.transform.position.y; float maxSmallerY = -9999999f; NodePathFinderPlatformer found = null; foreach (NodePathFinderPlatformer left in nodes[col_idx - 1]) { if (maxSmallerY < left.pos.y && left.pos.y < y) { maxSmallerY = left.pos.y; found = left; } } node.fallLeft = found; } } if (col_idx < nodes.Count - 1) { // right if (node.right == null) { float y = node.transform.position.y; float maxSmallerY = -9999999f; NodePathFinderPlatformer found = null; foreach (NodePathFinderPlatformer right in nodes[col_idx + 1]) { if (maxSmallerY < right.pos.y && right.pos.y < y) { maxSmallerY = right.pos.y; found = right; } } node.fallRight = found; } } }
public void AddJumpNeighbors() { Debug.Log("add jump neighbors"); for (int i = 0; i < nodes.Count; ++i) { foreach (NodePathFinderPlatformer node in nodes[i]) { float dt = tileSize / moveSpeed; int cnt = 0; float t = dt; float x0 = node.transform.position.x; float y0 = node.transform.position.y; float vy = jumpInitVerSpeed; float vx = moveSpeed; float y = y0; // Debug.Log($"{dt} {x0} {y0} {vy} {vx} {y}"); while (y > bottomLeft.position.y - 100f) { if (cnt + i >= nodes.Count && cnt - i < 0) { break; } float lasty = y; y = y0 + vy * t + 0.5f * gravity * t * t; // Debug.Log($"{y - lasty} {y - y0}, t = {t}, {vx * t}, cnt = {cnt}, i = {i}"); if (y - lasty < 0) // falling downwards { if (node.jumpRight == null && i + cnt < nodes.Count) { // Debug.Log("jump right"); // jump right float maxSmallerY = y; NodePathFinderPlatformer foundRight = null; foreach (NodePathFinderPlatformer leftNode in nodes[i + cnt]) { float lefty = leftNode.transform.position.y; // Debug.Log($"lefty = {lefty}"); // Debug.Log($"smallery = {maxSmallerY}, lasty = {lasty}, lefty = {lefty}"); if (maxSmallerY < lefty && lefty < lasty) { maxSmallerY = lefty; foundRight = leftNode; } } node.jumpRight = foundRight; } // jump left (symmetric) if (node.jumpLeft == null && i - cnt >= 0) { // Debug.Log("jump left"); float maxSmallerY = y; foreach (NodePathFinderPlatformer rightNode in nodes[i - cnt]) { float righty = rightNode.transform.position.y; // Debug.Log($"righty = {righty}"); // Debug.Log($"smallery = {maxSmallerY}, lasty = {lasty}, righty = {righty}"); if (maxSmallerY < righty && righty < lasty) { maxSmallerY = righty; node.jumpLeft = rightNode; } } } } t += dt; ++cnt; } } } }
public void GenerateGraph() { Debug.Log("generate graph"); float xlo = bottomLeft.position.x + tileSize / 2f; float xhi = topRight.position.x; float ylo = bottomLeft.position.y; float yhi = topRight.position.y; Debug.Log($"{xlo}, {xhi}, {ylo}, {yhi}"); bool isLastGround = false; for (float x = xlo; x < xhi; x += tileSize) { List <NodePathFinderPlatformer> curCol = new List <NodePathFinderPlatformer>(); for (float y = ylo; y < yhi; y += minObstacleSize) { Vector2 pos = new Vector2(x, y); if (!IsPosGround(pos)) { if (isLastGround) { isLastGround = false; float gndY = GetGroundY(x, y - minObstacleSize, y); NodePathFinderPlatformer newNode = Instantiate(pfNode, transform); newNode.transform.position = new Vector2(x, gndY); if (nodes.Count > 0) // if not the first column // check for neighbors on column to the left // Debug.Log("check for neighbors"); { List <NodePathFinderPlatformer> lastCol = nodes[nodes.Count - 1]; foreach (NodePathFinderPlatformer node in lastCol) { float diffy = Mathf.Abs(node.transform.position.y - newNode.transform.position.y); // Debug.Log(diffy); if (diffy < tileSize * 0.8f) { newNode.left = node; node.right = newNode; break; } } } curCol.Add(newNode); } } else { isLastGround = true; } } nodes.Add(curCol); } // add fall edge for (int i = 0; i < nodes.Count; ++i) { foreach (NodePathFinderPlatformer node in nodes[i]) { AddFallNeighbors(node, i); } } // add jump edge // AddJumpNeighbors(); }