示例#1
0
        public void ShouldFindPath_GraphWithDeadEnds()
        {
            var nodeCenter = new Node(new Position(10, 10));
            var nodeLeft   = new Node(new Position(0, 10));
            var nodeRight  = new Node(new Position(20, 10));
            var nodeAbove  = new Node(new Position(10, 0));
            var nodeBelow  = new Node(new Position(10, 20));

            nodeCenter.Connect(nodeLeft, Velocity.FromMetersPerSecond(1));
            nodeLeft.Connect(nodeCenter, Velocity.FromMetersPerSecond(1));

            nodeCenter.Connect(nodeRight, Velocity.FromMetersPerSecond(1));
            nodeRight.Connect(nodeCenter, Velocity.FromMetersPerSecond(1));

            nodeCenter.Connect(nodeAbove, Velocity.FromMetersPerSecond(1));
            nodeAbove.Connect(nodeCenter, Velocity.FromMetersPerSecond(1));

            nodeCenter.Connect(nodeBelow, Velocity.FromMetersPerSecond(1));
            nodeBelow.Connect(nodeCenter, Velocity.FromMetersPerSecond(1));

            var path = this.PathFinder.FindPath(nodeLeft, nodeBelow, Velocity.FromMetersPerSecond(1));

            Assert.That(path.Type, Is.EqualTo(PathType.Complete));
            Assert.That(path.Edges.Count, Is.EqualTo(2));
            Assert.That(path.Distance, Is.EqualTo(Distance.FromMeters(20)));
            Assert.That(path.Duration, Is.EqualTo(Duration.FromSeconds(20)));
        }
示例#2
0
 Grid GetMapGrid(int frame)
 {
     if (MapLastUpdate < frame)
     {
         var gridSize          = new GridSize(columns: MapData.MapWidth, rows: MapData.MapHeight);
         var cellSize          = new Size(Distance.FromMeters(1), Distance.FromMeters(1));
         var traversalVelocity = Velocity.FromMetersPerSecond(1);
         WalkGrid = Grid.CreateGridWithLateralAndDiagonalConnections(gridSize, cellSize, traversalVelocity);
         for (var x = 0; x < MapData.MapWidth; x++)
         {
             for (var y = 0; y < MapData.MapHeight; y++)
             {
                 if (!MapData.Map[x][y].Walkable)
                 {
                     WalkGrid.DisconnectNode(new GridPosition(x, y));
                     //DebugService.DrawSphere(new Point { X = x, Y = y, Z = MapData.Map[x][y].TerrainHeight + 1 }, 2, new Color { R = 0, G = 255, B = 0 });
                 }
                 else
                 {
                     //DebugService.DrawSphere(new Point { X = x, Y = y, Z = MapData.Map[x][y].TerrainHeight + 1 }, 2, new Color { R = 255, G = 0, B = 0 });
                 }
             }
         }
     }
     return(WalkGrid);
 }
示例#3
0
        Grid GetGroundGrid(int frame)
        {
            Node [,] nodes = new Node[MapData.MapWidth, MapData.MapHeight];
            if (GroundGridLastUpdate < frame)
            {
                for (var x = 0; x < MapData.MapWidth; x++)
                {
                    for (var y = 0; y < MapData.MapHeight; y++)
                    {
                        var node = new Node(new Position(x, y));
                        nodes[x, y] = node;
                    }
                }

                for (var x = 0; x < MapData.MapWidth; x++)
                {
                    for (var y = 0; y < MapData.MapHeight; y++)
                    {
                        if (MapData.Map[x][y].Walkable && !MapData.Map[x][y].PathBlocked)
                        {
                            var speed = BaseSpeed - MapData.Map[x][y].EnemyGroundDpsInRange + MapData.Map[x][y].SelfGroundDpsInRange;
                            if (MapData.Map[x][y].InSelfVision)
                            {
                                speed += FriendlyVisionSpeed;
                            }
                            if (MapData.Map[x][y].InEnemyVision)
                            {
                                speed += EnemyVisionSpeed;
                            }
                            //if (MapData.Map[x][y].SelfDetection) // TODO: Self detection
                            //{
                            //    speed += FriendlyDetectionSpeed;
                            //}
                            if (MapData.Map[x][y].InEnemyDetection)
                            {
                                speed += EnemyDetectionSpeed;
                            }
                            if (speed < MinimumSpeed)
                            {
                                speed = MinimumSpeed;
                            }
                            // TODO: low ground near high ground, add a high ground proximity to the MapCell
                            foreach (Node neighbor in GetNeighbors(x, y, 1, nodes))
                            {
                                if (MapData.Map[(int)neighbor.Position.X][(int)neighbor.Position.Y].Walkable && !MapData.Map[(int)neighbor.Position.X][(int)neighbor.Position.Y].PathBlocked)
                                {
                                    var node = nodes[x, y];
                                    node.Connect(neighbor, Velocity.FromMetersPerSecond(speed));
                                }
                            }
                        }
                    }
                }

                GroundGrid           = Grid.CreateGridFrom2DArrayOfNodes(nodes);
                GroundGridLastUpdate = frame;
            }
            return(GroundGrid);
        }
示例#4
0
        public void ShouldFindPath__StartNodeIsEndNode()
        {
            var node = new Node(Position.Zero);
            var path = this.PathFinder.FindPath(node, node, Velocity.FromMetersPerSecond(1));

            Assert.That(path.Type, Is.EqualTo(PathType.Complete));
            Assert.That(path.Edges.Count, Is.EqualTo(0));
            Assert.That(path.Distance, Is.EqualTo(Distance.FromMeters(0)));
            Assert.That(path.Duration, Is.EqualTo(Duration.Zero));
        }
示例#5
0
        Grid GetAirGrid(int frame)
        {
            Node[,] nodes = new Node[MapData.MapWidth, MapData.MapHeight];
            if (AirGridLastUpdate < frame)
            {
                for (var x = 0; x < MapData.MapWidth; x++)
                {
                    for (var y = 0; y < MapData.MapHeight; y++)
                    {
                        var node = new Node(new Position(x, y));
                        nodes[x, y] = node;
                    }
                }

                for (var x = 0; x < MapData.MapWidth; x++)
                {
                    for (var y = 0; y < MapData.MapHeight; y++)
                    {
                        var speed = BaseSpeed - MapData.Map[x][y].EnemyAirDpsInRange + MapData.Map[x][y].SelfAirDpsInRange;
                        if (MapData.Map[x][y].InSelfVision)
                        {
                            speed += FriendlyVisionSpeed;
                        }
                        if (MapData.Map[x][y].InEnemyVision)
                        {
                            speed += EnemyVisionSpeed;
                        }
                        //if (MapData.Map[x][y].SelfDetection) // TODO: Self detection
                        //{
                        //    speed += FriendlyDetectionSpeed;
                        //}
                        if (MapData.Map[x][y].InEnemyDetection)
                        {
                            speed += EnemyDetectionSpeed;
                        }
                        if (speed < MinimumSpeed)
                        {
                            speed = MinimumSpeed;
                        }

                        foreach (Node neighbor in GetNeighbors(x, y, 1, nodes))
                        {
                            var node = nodes[x, y];
                            node.Connect(neighbor, Velocity.FromMetersPerSecond(speed));
                        }
                    }
                }

                AirGrid           = Grid.CreateGridFrom2DArrayOfNodes(nodes);
                AirGridLastUpdate = frame;
            }
            return(AirGrid);
        }
示例#6
0
        public WorldGrid(int columns, int rows, float cellDimensions, float traversalVelocity, Vector3 offset)
        {
            var gridSize = new GridSize(columns, rows);

            this.CellSize        = new Size(Distance.FromMeters(cellDimensions), Distance.FromMeters(cellDimensions));
            this.MaximumVelocity = Velocity.FromMetersPerSecond(traversalVelocity);
            // TODO: if we create a grid with lateral and diagonal connections paths look a lot better
            // however we have to take into account 'crossing over' other cells when reserving.
            this.Grid         = Grid.CreateGridWithLateralConnections(gridSize, this.CellSize, this.MaximumVelocity);
            this.PathFinder   = new PathFinder();
            this.Reservations = new Entity[columns, rows];

            this.Offset     = offset;
            this.CellOffset = new Vector3(this.CellSize.Width.Meters * 0.5f, 0, this.CellSize.Height.Meters * 0.5f);
        }
        public static Grid MapToGrid(this AreaMap areaMap)
        {
            var rows    = areaMap.Map.GetLength(0);
            var columns = areaMap.Map[0].GetLength(0);
            var nodes   = new Node[columns, rows];

            for (var i = 0; i < columns; i++)
            {
                for (var j = 0; j < rows; j++)
                {
                    nodes[i, j] = new Node(new Position((float)i * DistanceBetweenCells, (float)j * DistanceBetweenCells));
                }
            }

            for (var i = 0; i < columns; i++)
            {
                for (var j = 0; j < rows; j++)
                {
                    if (!IsMovable(areaMap.Map[j][i]))
                    {
                        continue;
                    }

                    var fromNode = nodes[i, j];

                    var speed = GetVelocityWithAdjacency(areaMap, j, i, rows, columns);
                    if (i + 1 < columns && IsMovable(areaMap.Map[j][i + 1]))
                    {
                        var toNode   = nodes[i + 1, j];
                        var velocity = Velocity.FromMetersPerSecond(speed);
                        fromNode.Connect(toNode, velocity);
                        toNode.Connect(fromNode, velocity);
                    }

                    if (j + 1 < rows && IsMovable(areaMap.Map[j + 1][i]))
                    {
                        var toNode   = nodes[i, j + 1];
                        var velocity = Velocity.FromMetersPerSecond(speed);
                        fromNode.Connect(toNode, velocity);
                        toNode.Connect(fromNode, velocity);
                    }
                }
            }

            var grid = Grid.CreateGridFrom2DArrayOfNodes(nodes);

            return(grid);
        }
示例#8
0
        public void ShouldFindPath_AcyclicGraph()
        {
            var nodeA = new Node(new Position(0, 0));
            var nodeB = new Node(new Position(10, 0));
            var nodeC = new Node(new Position(20, 0));

            nodeA.Connect(nodeB, Velocity.FromMetersPerSecond(1));
            nodeB.Connect(nodeC, Velocity.FromMetersPerSecond(1));

            var path = this.PathFinder.FindPath(nodeA, nodeC, Velocity.FromMetersPerSecond(1));

            Assert.That(path.Type, Is.EqualTo(PathType.Complete));
            Assert.That(path.Edges.Count, Is.EqualTo(2));
            Assert.That(path.Distance, Is.EqualTo(Distance.FromMeters(20)));
            Assert.That(path.Duration, Is.EqualTo(Duration.FromSeconds(20)));
        }
示例#9
0
        public MainWindowViewModel()
        {
            this.PathFinder = new PathFinder();

            this.Models = new ObservableCollection <ReactiveObject>();

            this.Random  = new Random();
            this.outcome = string.Empty;

            this.ExitCommand = ReactiveCommand.Create(() =>
            {
                Application.Current.Shutdown();
            });

            this.OpenGitHubCommand = ReactiveCommand.Create(() =>
            {
                var psi = new ProcessStartInfo
                {
                    FileName        = "cmd",
                    WindowStyle     = ProcessWindowStyle.Hidden,
                    UseShellExecute = false,
                    CreateNoWindow  = true,
                    Arguments       = $"/c start http://github.com/roy-t/AStar"
                };
                Process.Start(psi);
            });

            this.ResetCommand     = ReactiveCommand.Create(() => this.CreateNodes(Connections.LateralAndDiagonal));
            this.LateralCommand   = ReactiveCommand.Create(() => this.CreateNodes(Connections.Lateral));
            this.DiagonalCommand  = ReactiveCommand.Create(() => this.CreateNodes(Connections.Diagonal));
            this.RandomizeCommand = ReactiveCommand.Create(() => this.SetSpeedLimits(() =>
            {
                var value = this.Random.Next((int)Settings.MinSpeed.MetersPerSecond, (int)Settings.MaxSpeed.MetersPerSecond + 1);
                return(Velocity.FromMetersPerSecond(value));
            }));

            this.MaxCommand = ReactiveCommand.Create(() => this.SetSpeedLimits(() => Settings.MaxSpeed));
            this.MinCommand = ReactiveCommand.Create(() => this.SetSpeedLimits(() => Settings.MinSpeed));

            this.SaveGridCommand = ReactiveCommand.Create(this.SaveGrid);
            this.OpenGridCommand = ReactiveCommand.Create(this.OpenGrid);

            this.CreateNodes(Connections.LateralAndDiagonal);
        }
示例#10
0
 Grid GetAirDamageGrid(int frame)
 {
     if (AirDamageLastUpdate < frame)
     {
         var gridSize          = new GridSize(columns: MapData.MapWidth, rows: MapData.MapHeight);
         var cellSize          = new Size(Distance.FromMeters(1), Distance.FromMeters(1));
         var traversalVelocity = Velocity.FromMetersPerSecond(1);
         AirDamageGrid = Grid.CreateGridWithLateralAndDiagonalConnections(gridSize, cellSize, traversalVelocity);
         for (var x = 0; x < MapData.MapWidth; x++)
         {
             for (var y = 0; y < MapData.MapHeight; y++)
             {
                 if (MapData.Map[x][y].EnemyAirDpsInRange > 0)
                 {
                     AirDamageGrid.DisconnectNode(new GridPosition(x, y));
                 }
             }
         }
         AirDamageLastUpdate = frame;
     }
     return(AirDamageGrid);
 }
示例#11
0
 Grid GetGroundDetectionGrid(int frame)
 {
     if (GroundDetectionLastUpdate < frame)
     {
         var gridSize          = new GridSize(columns: MapData.MapWidth, rows: MapData.MapHeight);
         var cellSize          = new Size(Distance.FromMeters(1), Distance.FromMeters(1));
         var traversalVelocity = Velocity.FromMetersPerSecond(1);
         GroundDetectionGrid = Grid.CreateGridWithLateralAndDiagonalConnections(gridSize, cellSize, traversalVelocity);
         for (var x = 0; x < MapData.MapWidth; x++)
         {
             for (var y = 0; y < MapData.MapHeight; y++)
             {
                 if (!MapData.Map[x][y].Walkable || MapData.Map[x][y].InEnemyDetection)
                 {
                     GroundDetectionGrid.DisconnectNode(new GridPosition(x, y));
                 }
             }
         }
         GroundDetectionLastUpdate = frame;
     }
     return(GroundDetectionGrid);
 }
示例#12
0
 private static Velocity FromDto(this VelocityDto velocity)
 {
     return(Velocity.FromMetersPerSecond(velocity.MetersPerSecond));
 }
示例#13
0
 void UpdateEnemyVisionGrid(IEnumerable <UnitCalculation> enemyUnits)
 {
     EnemyVisionGrid = Grid.CreateGridWithLateralAndDiagonalConnections(WalkGrid.GridSize, new Size(Distance.FromMeters(1), Distance.FromMeters(1)), Velocity.FromMetersPerSecond(1));
     foreach (var enemy in enemyUnits)
     {
         var nodes = GetNodesInRange(enemy.Unit.Pos, 11, EnemyVisionGrid.Columns, EnemyVisionGrid.Rows); // TODO: get sight range of every unit, // TODO: units on low ground can't see high ground
         foreach (var node in nodes)
         {
             EnemyVisionGrid.DisconnectNode(node);
         }
     }
 }