static bool CheckTrajectory(PathFindingGrid grid, PathFindingAgent agent, Node jumpStart, Node jumpLanding, int xDelta, int precision = 12) { float cellSize = grid.CellSize; Vector2 a = jumpStart.WorldPosition + new Vector2(-.5f, agent.Height - .5f) * cellSize; Vector2 b = a + Vector2.up * (agent.JumpStrength * cellSize); Vector2 c = b + Vector2.right * (xDelta * cellSize); Vector2 d = jumpLanding.WorldPosition + new Vector2(-.5f, agent.Height - .5f) * cellSize; var bezierCurve = new BezierCurve(a, b, c, d); bool isRight = xDelta > 0; Node lastNode = null; float offset = 1f / precision; float t = 0; for (int i = 0; i < precision - 1; i++) { t += offset; var curveValue = bezierCurve.GetValue(t); var node = grid.WorldPositionToNode(curveValue); if (node == lastNode) { continue; } if (!AllNodes(grid, node.Y, node.X, 1, agent.Width + 1, IsAir)) { return(false); } if (isRight) { if (!AllNodes(grid, node.Y - (agent.Height - 1), node.X + agent.Width, agent.Height + 1, 1, IsAir)) { return(false); } } else { if (!AllNodes(grid, node.Y - (agent.Height - 1), node.X - 1, agent.Height + 1, 1, IsAir)) { return(false); } } lastNode = node; } return(true); }
static bool AllInColumn(PathFindingGrid grid, int xStart, int yStart, int yCount, Func <Node, bool> checkFunc) { for (int y = 0; y < yCount; y++) { if (!checkFunc(grid.GetNode(xStart, yStart + y))) { return(false); } } return(true); }
static bool AllInRow(PathFindingGrid grid, int xStart, int yStart, int xCount, Func <Node, bool> checkFunc) { for (int x = 0; x < xCount; x++) { if (!checkFunc(grid.GetNode(xStart + x, yStart))) { return(false); } } return(true); }
public List <TransitionData> GetTransitions(PathFindingGrid grid, PathFindingAgent agent, Node node) { var neighbours = new List <TransitionData>(); bool isGrounded = AnyNode(grid, node.X, node.Y - 1, agent.Width, 1, IsGround); if (isGrounded) { if (AllInColumn(grid, node.X - 1, node.Y, agent.Height, IsAir)) { var neighbourNode = grid.GetNode(node.X - 1, node.Y); var neighbour = new TransitionData(neighbourNode, TransitionType.Walk, 1); neighbours.Add(neighbour); } if (AllInColumn(grid, node.X + agent.Width, node.Y, agent.Height, IsAir)) { var neighbourNode = grid.GetNode(node.X + 1, node.Y); var neighbour = new TransitionData(neighbourNode, TransitionType.Walk, 1); neighbours.Add(neighbour); } for (var dx = 2; dx <= agent.JumpStrength; dx++) { CheckJump(grid, agent, neighbours, node, dx); } for (var dx = -2; dx >= -agent.JumpStrength; --dx) { CheckJump(grid, agent, neighbours, node, dx); } } else { Node landing = GetFallOnGroundNode(grid, agent, node.X, node.Y); if (landing != null) { int fallHeight = node.Y - landing.Y; if (fallHeight <= agent.FallLimit) { const TransitionType fall = TransitionType.Fall; var neighbour = new TransitionData(landing, fall, GetCost(agent, node, landing, fall)); neighbours.Add(neighbour); } } } return(neighbours); }
static Node GetFallOnGroundNode(PathFindingGrid grid, PathFindingAgent agent, int x, int y) { if (!AllInRow(grid, x, y, agent.Width, node => node != null)) { return(null); } while (AllInRow(grid, x, y - 1, agent.Width, IsAir)) { --y; } return(grid.GetNode(x, y)); }
static bool AnyNode(PathFindingGrid grid, int xStart, int yStart, int xCount, int yCount, Func <Node, bool> checkFunc) { for (int x = 0; x < xCount; x++) { for (int y = 0; y < yCount; y++) { if (checkFunc(grid.GetNode(xStart + x, yStart + y))) { return(true); } } } return(false); }
static bool CheckTrajectory(PathFindingGrid grid, PathFindingAgent agent, Node jumpStart, Node jumpEnd) { int dx = jumpEnd.X - jumpStart.X, dy = jumpEnd.Y - jumpStart.Y; var offsets = agent.GetCheckNodes(dx, dy); foreach (var offset in offsets) { Node toCheck = grid.GetNode(jumpStart.X + offset.x, jumpStart.Y + offset.y); if (!IsAir(toCheck)) { return(false); } } return(true); }
static Node GetFallOnGroundNode(PathFindingGrid grid, int yStart, int xStart, int width) { // Make sure that it's not out of grid. for (int x = 0; x < width; x++) { if (grid.GetNode(yStart, xStart + x) == null) { return(null); } } while (!AnyNode(grid, yStart - 1, xStart, 1, width, IsGround)) { --yStart; } return(grid.GetNode(yStart, xStart)); }
void CheckJump(PathFindingGrid grid, PathFindingAgent agent, List <TransitionData> neighbours, Node node, int dx) { Node landing = GetFallOnGroundNode(grid, agent, node.X + dx, node.Y + agent.JumpStrength); if (landing == null) { return; } int fallHeight = node.Y + agent.JumpStrength - landing.Y; if (fallHeight > agent.FallLimit) { return; } if (CheckTrajectory(grid, agent, node, landing)) { const TransitionType jump = TransitionType.Jump; var neighbour = new TransitionData(landing, jump, GetCost(agent, node, landing, jump)); neighbours.Add(neighbour); } }
public AStarSearch(PathFindingGrid pathFindingGrid) { _pathFindingGrid = pathFindingGrid; _openSet = new Heap <Node>(pathFindingGrid.MaxSize); }
public Node[] GetNeighbours(PathFindingGrid grid, Node node, PathFindingAgent agent, out int count) { count = 0; bool isGrounded = AnyNode(grid, node.Y - 1, node.X, 1, agent.Width, IsGround); if (isGrounded) { Node neighbour; if (AllNodes(grid, node.Y, node.X - 1, agent.Height, 1, IsAir)) { neighbour = grid.GetNode(node.Y, node.X - 1); _neighbours[count++] = neighbour; } if (AllNodes(grid, node.Y, node.X + agent.Width, agent.Height, 1, IsAir)) { neighbour = grid.GetNode(node.Y, node.X + 1); _neighbours[count++] = neighbour; } // Jump to the Right for (var x = 2; x <= agent.JumpStrength; ++x) { neighbour = GetFallOnGroundNode(grid, node.Y + agent.JumpStrength, node.X + x, agent.Width); if (neighbour == null) { continue; } if (CheckTrajectory(grid, agent, node, neighbour, x)) { _neighbours[count++] = neighbour; } } // Jump to the Left for (var x = -2; x >= -agent.JumpStrength; --x) { neighbour = GetFallOnGroundNode(grid, node.Y + agent.JumpStrength, node.X + x, agent.Width); if (neighbour == null) { continue; } if (CheckTrajectory(grid, agent, node, neighbour, x)) { _neighbours[count++] = neighbour; } } } // Falling Down. This should only happen if spawned above the ground. else { _neighbours[count++] = grid.GetNode(node.Y - 1, node.X); } return(_neighbours); }
public void Init(PathFindingGrid pathFindingGrid) { _pathFindingGrid = pathFindingGrid; }