예제 #1
0
        private BlockType IsBlocked(int x, int y, PathfindaxCollisionCategory collisionCategory, Point2 fromCoordinates)
        {
            if (x >= _definitionNodeGrid.DefinitionNodeArray.Width || y >= _definitionNodeGrid.DefinitionNodeArray.Height)
            {
                return(BlockType.Current);
            }
            var definitionNode = _definitionNodeGrid.DefinitionNodeArray[x, y];
            var blockType      = BlockType.None;

            foreach (var nodeConnection in definitionNode.Connections)
            {
                if ((nodeConnection.CollisionCategory & collisionCategory) != 0)
                {
                    var toNode        = _definitionNodeGrid.DefinitionNodeArray[nodeConnection.To.Index];
                    var toCoordinates = new Point2((int)toNode.Position.X, (int)toNode.Position.Y);
                    if (toCoordinates.X >= fromCoordinates.X && toCoordinates.Y >= fromCoordinates.Y)
                    {
                        if (toCoordinates.X >= x || toCoordinates.Y >= y)
                        {
                            blockType = BlockType.Next;
                        }
                        else
                        {
                            return(BlockType.Current);
                        }
                    }
                }
            }
            return(blockType);
        }
예제 #2
0
 public void Generate(AstarNode[] pathfindingNetwork, PathfindaxCollisionCategory collisionCategory)
 {
     for (var i = 0; i < _definitionNodeGrid.DefinitionNodeArray.Array.Length; i++)
     {
         ref var definitionNode = ref _definitionNodeGrid.DefinitionNodeArray.Array[i];
         var     clearance      = CalculateClearance(ref definitionNode, collisionCategory, _maxClearance);
         pathfindingNetwork[i].Clearance = clearance;
     }
예제 #3
0
 void ICmpInitializable.OnInit(InitContext context)
 {
     if (context == InitContext.Activate && DualityApp.ExecContext == DualityApp.ExecutionContext.Game)
     {
         _rigidBody                   = GameObj.GetComponent <RigidBody>();
         _collisionCategory           = (PathfindaxCollisionCategory)_rigidBody.CollisionCategory;
         DualityApp.Mouse.ButtonDown += Mouse_ButtonDown;
     }
 }
 void ICmpInitializable.OnInit(InitContext context)
 {
     if (context == InitContext.Activate && DualityApp.ExecContext == DualityApp.ExecutionContext.Game)
     {
         DynamicPotentialFieldComponent.PotentialField.AddPotentialFunction(this,
                                                                            new QuadraticPotentialFunction(() => CurrentPosition, (float)AgentSize / 2 + 1.0f, 1.2f * AgentSize));
         _rigidBody                   = GameObj.GetComponent <RigidBody>();
         _collisionCategory           = (PathfindaxCollisionCategory)_rigidBody.CollisionCategory;
         DualityApp.Mouse.ButtonDown += Mouse_ButtonDown;
     }
 }
예제 #5
0
        public DijkstraNode[] GetCollisionLayerNetwork(PathfindaxCollisionCategory collisionCategory)
        {
            if (!_nodeNetworks.TryGetValue(collisionCategory, out var pathfindingNetwork))
            {
                var watch = Stopwatch.StartNew();
                pathfindingNetwork = GenerateNodeNetwork(collisionCategory);

                Debug.WriteLine($"Generated pathfind nodenetwork in {watch.ElapsedMilliseconds} ms");
                _nodeNetworks.Add(collisionCategory, pathfindingNetwork);
            }
            return(pathfindingNetwork);
        }
예제 #6
0
        public void Start(AstarNode[] pathfindingNetwork, DefinitionNode[] definitionNodes, int startNodeIndex, int targetNodeIndex, float neededClearance, PathfindaxCollisionCategory collisionCategory)
        {
            StartNodeIndex      = startNodeIndex;
            TargetNodeIndex     = targetNodeIndex;
            _neededClearance    = neededClearance;
            _collisionCategory  = collisionCategory;
            _pathfindingNetwork = pathfindingNetwork;
            _definitionNodes    = definitionNodes;

            _openSet.AssignArray(pathfindingNetwork);
            _closedSet.Clear();
            _openSet.Add(startNodeIndex);
        }
예제 #7
0
        private DijkstraNode[] GenerateNodeNetwork(PathfindaxCollisionCategory collisionCategory)
        {
            var gridClearanceGenerator = new BrushfireClearanceGenerator(DefinitionNodeGrid, _maxClearance);
            var nodeNetwork            = new DijkstraNode[DefinitionNodeGrid.NodeCount];

            for (var i = 0; i < DefinitionNodeGrid.NodeGrid.Array.Length; i++)
            {
                ref var definitionNode = ref DefinitionNodeGrid.NodeGrid.Array[i];
                nodeNetwork[i] = new DijkstraNode
                {
                    Clearance = _maxClearance == -1 ? int.MaxValue : gridClearanceGenerator.CalculateClearance(ref definitionNode, collisionCategory, _maxClearance)
                };
            }
예제 #8
0
        /// <summary>
        /// Calculates the clearances up to a maximum <paramref name="maxClearance"/>
        /// </summary>
        /// <param name="definitionNode"></param>
        /// <param name="collisionCategory"></param>
        /// <param name="maxClearance"></param>
        /// <returns></returns>
        public float CalculateGridNodeClearances(DefinitionNode definitionNode, PathfindaxCollisionCategory collisionCategory, int maxClearance)
        {
            var fromCoordinates = new Point2((int)definitionNode.Position.X, (int)definitionNode.Position.Y);

            for (var checkClearance = 0; checkClearance < maxClearance; checkClearance++)
            {
                var nextClearanceIsBlocked = false;
                for (var x = 0; x < checkClearance + 1; x++)
                {
                    switch (IsBlocked(x + fromCoordinates.X, checkClearance + fromCoordinates.Y, collisionCategory, fromCoordinates))
                    {
                    case BlockType.Current:
                        return(checkClearance);

                    case BlockType.Next:
                        nextClearanceIsBlocked = true;
                        break;
                    }
                }

                for (var y = 0; y < checkClearance; y++)
                {
                    switch (IsBlocked(checkClearance + fromCoordinates.X, y + fromCoordinates.Y, collisionCategory, fromCoordinates))
                    {
                    case BlockType.Current:
                        return(checkClearance);

                    case BlockType.Next:
                        nextClearanceIsBlocked = true;
                        break;
                    }
                }

                if (nextClearanceIsBlocked)
                {
                    var isBlocked = true;
                    for (var i = 0; i < definitionNode.Connections.Count; i++)
                    {
                        if ((definitionNode.Connections[i].CollisionCategory & collisionCategory) == 0)
                        {
                            isBlocked = false;
                        }
                    }

                    return(isBlocked ? checkClearance : checkClearance + 1);
                }
            }
            return(maxClearance);
        }
예제 #9
0
 public AstarNode[] GetCollisionLayerNetwork(PathfindaxCollisionCategory collisionCategory)
 {
     if (!_nodeNetworks.TryGetValue(collisionCategory, out var pathfindingNetwork))
     {
         var watch = Stopwatch.StartNew();
         pathfindingNetwork = GenerateNodeNetwork(DefinitionNodeNetwork);
         foreach (var pathfindNodeGenerator in _pathfindNodeGenerators)
         {
             pathfindNodeGenerator.Generate(pathfindingNetwork, collisionCategory);
         }
         Debug.WriteLine($"Generated pathfind nodenetwork in {watch.ElapsedMilliseconds} ms");
         _nodeNetworks.Add(collisionCategory, pathfindingNetwork);
     }
     return(pathfindingNetwork);
 }
예제 #10
0
        private DijkstraNode[] GenerateNodeNetwork(PathfindaxCollisionCategory collisionCategory)
        {
            var gridClearanceGenerator = new GridClearanceGenerator(DefinitionNodeGrid, _maxClearance);
            var nodeNetwork            = new DijkstraNode[DefinitionNodeGrid.NodeCount];

            for (var y = 0; y < DefinitionNodeGrid.NodeGrid.Height; y++)
            {
                for (var x = 0; x < DefinitionNodeGrid.NodeGrid.Width; x++)
                {
                    var definitionNode = DefinitionNodeGrid.NodeGrid[x, y];
                    nodeNetwork[definitionNode.Index.Index] = new DijkstraNode(definitionNode)
                    {
                        Clearance = _maxClearance == -1 ? int.MaxValue : gridClearanceGenerator.CalculateGridNodeClearances(definitionNode, collisionCategory, _maxClearance)
                    };
                }
            }
            return(nodeNetwork);
        }
예제 #11
0
 public void Generate(AstarNode[] pathfindingNetwork, PathfindaxCollisionCategory collisionCategory)
 {
     if (_maxClearance < 0)
     {
         for (var i = 0; i < pathfindingNetwork.Length; i++)
         {
             pathfindingNetwork[i].Clearance = int.MaxValue;
         }
     }
     else
     {
         for (int y = 0; y < _definitionNodeGrid.DefinitionNodeArray.Height; y++)
         {
             for (int x = 0; x < _definitionNodeGrid.DefinitionNodeArray.Width; x++)
             {
                 var definitionNode = _definitionNodeGrid.DefinitionNodeArray[x, y];
                 var clearance      = CalculateGridNodeClearances(definitionNode, collisionCategory, _maxClearance);
                 pathfindingNetwork[definitionNode.Index.Index].Clearance = clearance;
             }
         }
     }
 }
예제 #12
0
 public void SetConnectionCollision(int index, PathfindaxCollisionCategory collisionCategory)
 {
     Connections[index] = new NodeConnection(Connections[index].To, collisionCategory);
 }
예제 #13
0
 public static PathRequest <TPath> Create <TPath>(int start, int end, PathfindaxCollisionCategory collisionCategory = PathfindaxCollisionCategory.None, byte agentSize = 1)
     where TPath : IPath
 {
     return(new PathRequest <TPath>(start, end, collisionCategory, agentSize));
 }
예제 #14
0
        public static PathRequest <TPath> Create <TPath>(IPathfinder <TPath> pathfinder, int start, int end, PathfindaxCollisionCategory collisionCategory = PathfindaxCollisionCategory.None, byte agentSize = 1)
            where TPath : IPath
        {
            var request = new PathRequest <TPath>(start, end, collisionCategory, agentSize);

            pathfinder.RequestPath(request);
            return(request);
        }
예제 #15
0
 public PathRequest <TPath> RequestPath(DefinitionNode start, DefinitionNode end, PathfindaxCollisionCategory collisionLayer = PathfindaxCollisionCategory.None, byte agentSize = 1)
 {
     return(PathRequest.Create(this, start, end, collisionLayer, agentSize));
 }
예제 #16
0
 public PathRequest <TPath> RequestPath(float x1, float y1, float x2, float y2, PathfindaxCollisionCategory collisionLayer = PathfindaxCollisionCategory.None, byte agentSize = 1)
 {
     return(PathFindAlgorithm.CreatePathRequest(this, DefinitionNodeNetwork, x1, y1, x2, y2, collisionLayer, agentSize));
 }
예제 #17
0
        private bool ConnectionIsBlocked(Array2D <DefinitionNode> nodeGrid, int from, int to, PathfindaxCollisionCategory collisionCategory = PathfindaxCollisionCategory.Cat1)
        {
            if (from == -1 || to == -1)
            {
                return(true);
            }
            var connection = nodeGrid.Array[from].Connections.FirstOrDefault(x => x.To == to);

            return((connection.CollisionCategory & collisionCategory) != 0);
        }
예제 #18
0
 private void GetCollisionCategory(NodeGridCollisionMask nodeGridCollisionLayers, int x, int y, CollisionDirection tileCollisionShapeSelf, int toX, int toY, CollisionDirection tileCollisionShapeOther, ref PathfindaxCollisionCategory collisionCategory)
 {
     foreach (var nodeGridCollisionLayer in nodeGridCollisionLayers.Layers)
     {
         if ((collisionCategory | nodeGridCollisionLayer.CollisionCategory) == collisionCategory)
         {
             continue;
         }
         if (DoesCollide(nodeGridCollisionLayer, x, y, tileCollisionShapeSelf) || DoesCollide(nodeGridCollisionLayer, toX, toY, tileCollisionShapeOther))
         {
             collisionCategory |= nodeGridCollisionLayer.CollisionCategory;
         }
     }
 }
예제 #19
0
        public PathRequest <NodePath> CreatePathRequest(IPathfinder <NodePath> pathfinder, IDefinitionNodeNetwork definitionNodes, float x1, float y1, float x2, float y2, PathfindaxCollisionCategory collisionLayer = PathfindaxCollisionCategory.None, byte agentSize = 1)
        {
            DefinitionNode startNode;
            DefinitionNode endNode;

            switch (definitionNodes)
            {
            case IDefinitionNodeGrid definitionNodeGrid:
                var offset = -GridClearanceHelper.GridNodeOffset(agentSize, definitionNodeGrid.Transformer.Scale);
                startNode = definitionNodeGrid.GetNode(x1 + offset.X, y1 + offset.Y);
                endNode   = definitionNodeGrid.GetNode(x2 + offset.X, y2 + offset.Y);
                return(PathRequest.Create(pathfinder, startNode, endNode, collisionLayer, agentSize));

            case IDefinitionNodeNetwork definitionNodeNetwork:
                startNode = definitionNodeNetwork.GetNode(x1, y1);
                endNode   = definitionNodeNetwork.GetNode(x2, y2);
                return(PathRequest.Create(pathfinder, startNode, endNode, collisionLayer, agentSize));

            default:
                throw new NotSupportedException($"{definitionNodes.GetType()} is not supported");
            }
        }
예제 #20
0
 public PathRequest <TPath> RequestPath(int start, int end, PathfindaxCollisionCategory collisionLayer = PathfindaxCollisionCategory.None, byte agentSize = 1)
 {
     return(PathRequest.Create(this, 0, 0, PathfindaxCollisionCategory.None, 0));
 }
예제 #21
0
 public PathRequest <TPath> RequestPath(float x1, float y1, float x2, float y2, PathfindaxCollisionCategory collisionLayer = PathfindaxCollisionCategory.None, byte agentSize = 1)
 {
     return(RequestPath(0, 0, collisionLayer, agentSize));
 }
예제 #22
0
 private void DrawNodeConnections(IRenderer renderer, Transformer transformer, Vector2 nodeWorldPosition, NodeConnection[] nodeConnections, DefinitionNode[] definitionNodes, PathfindaxCollisionCategory collisionCategory)
 {
     foreach (var connection in nodeConnections)
     {
         if ((connection.CollisionCategory & collisionCategory) != 0)
         {
             continue;
         }
         ref var toNode = ref definitionNodes[connection.To];
         var     vector = (transformer.ToWorld(toNode.Position) - nodeWorldPosition) * 0.5f;             //Times 0.5f so we can see the connections in both directions.
         renderer.DrawLine(nodeWorldPosition, nodeWorldPosition + vector);
     }
예제 #23
0
 public void AddConnection(int to, PathfindaxCollisionCategory collisionCategory = PathfindaxCollisionCategory.None)
 {
     Connections = Connections.Append(new NodeConnection(to, collisionCategory));
 }
예제 #24
0
 void ICmpInitializable.OnActivate()
 {
     _rigidBody                   = GameObj.GetComponent <RigidBody>();
     _collisionCategory           = (PathfindaxCollisionCategory)_rigidBody.CollisionCategory;
     DualityApp.Mouse.ButtonDown += Mouse_ButtonDown;
 }
예제 #25
0
 public void AddConnection(DefinitionNode to, PathfindaxCollisionCategory collisionCategory = PathfindaxCollisionCategory.None)
 {
     Connections.Add(new NodeConnection(to.Index, collisionCategory));
 }
예제 #26
0
        private static List <DefinitionNode> FindPath(AstarNode[] pathfindingNetwork, AstarNode startNode, AstarNode targetNode, float neededClearance, PathfindaxCollisionCategory collisionCategory)
        {
            try
            {
                var sw = new Stopwatch();
                sw.Start();

                var pathSucces = false;
                if (startNode == targetNode)
                {
                    return(new List <DefinitionNode> {
                        targetNode.DefinitionNode
                    });
                }
                if (startNode.Clearance >= neededClearance && targetNode.Clearance >= neededClearance)
                {
                    var openSet          = new MaxHeap <AstarNode>(pathfindingNetwork.Length);
                    var closedSet        = new HashSet <AstarNode>();
                    var itterations      = 0;
                    var neighbourUpdates = 0;
                    openSet.Add(startNode);
                    while (openSet.Count > 0)
                    {
                        itterations++;
                        var currentNode = openSet.RemoveFirst();
                        closedSet.Add(currentNode);

                        if (currentNode == targetNode)
                        {
                            sw.Stop();
                            Debug.WriteLine($"NodePath found in {sw.ElapsedMilliseconds} ms. Itterations: {itterations} Neighbourupdates: {neighbourUpdates}");
                            pathSucces = true;
                            break;
                        }

                        foreach (var connection in currentNode.DefinitionNode.Connections)
                        {
                            var toNode = NodePointer.Dereference(connection.To, pathfindingNetwork);
                            if ((connection.CollisionCategory & collisionCategory) != 0 || closedSet.Contains(toNode))
                            {
                                continue;
                            }

                            if (toNode.Clearance >= neededClearance)
                            {
                                var newMovementCostToNeighbour = currentNode.GCost + GetDistance(currentNode.DefinitionNode, toNode.DefinitionNode) * currentNode.DefinitionNode.MovementCostModifier;
                                if (newMovementCostToNeighbour < toNode.GCost || !openSet.Contains(toNode))
                                {
                                    toNode.GCost  = newMovementCostToNeighbour;
                                    toNode.HCost  = GetDistance(toNode.DefinitionNode, targetNode.DefinitionNode);
                                    toNode.Parent = currentNode.DefinitionNode.Index;
                                    neighbourUpdates++;
                                    if (!openSet.Contains(toNode))
                                    {
                                        openSet.Add(toNode);
                                    }
                                }
                            }
                        }
                    }
                }
                if (pathSucces)
                {
                    return(RetracePath(pathfindingNetwork, startNode, targetNode));
                }
                Debug.WriteLine("Did not find a path :(");
                return(null);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
                Debugger.Break();
                return(null);
            }
        }
예제 #27
0
 /// <summary>
 /// Creates a new <see cref="NodeConnection"/>.
 /// </summary>
 /// <param name="to">Where this connection is going to</param>
 /// <param name="collisionCategory">The <see cref="PathfindaxCollisionCategory"/> of this <see cref="NodeConnection"/></param>
 public NodeConnection(NodePointer to, PathfindaxCollisionCategory collisionCategory = PathfindaxCollisionCategory.None)
 {
     To = to;
     CollisionCategory = collisionCategory;
 }
예제 #28
0
 public PathRequest <TPath> RequestPath(Vector2 start, Vector2 end, PathfindaxCollisionCategory collisionLayer = PathfindaxCollisionCategory.None, byte agentSize = 1)
 {
     return(RequestPath(start.X, start.Y, end.X, end.Y, collisionLayer, agentSize));
 }
예제 #29
0
 object IPathfindNodeNetwork.GetCollisionLayerNetwork(PathfindaxCollisionCategory collisionCategory) => GetCollisionLayerNetwork(collisionCategory);
예제 #30
0
 /// <summary>
 /// Creates a new instance of the <see cref="TilemapCollider"/> and adds the <see cref="RigidBody"/> thats on the same <see cref="GameObject"/>
 /// </summary>
 /// <param name="tilemapCollider"></param>
 public TilemapColliderWithBody(TilemapCollider tilemapCollider)
 {
     CollisionCategory       = (PathfindaxCollisionCategory)tilemapCollider.GameObj.GetComponent <RigidBody>().CollisionCategory;
     TilemapCollisionSources = tilemapCollider.CollisionSource.ToArray();
 }