//Generate the flow field showing how far to the closest obstacle from each cell
        private void GenerateObstacleFlowField()
        {
            FlowField flowField = new FlowField();

            int mapLength = PathfindingController.mapLength;
            int mapWidth  = PathfindingController.mapWidth;

            //The flow field will be stored in this array
            FlowFieldNode[,] gridArray = new FlowFieldNode[mapLength, mapWidth];

            for (int x = 0; x < mapLength; x++)
            {
                for (int z = 0; z < mapWidth; z++)
                {
                    bool isWalkable = true;

                    FlowFieldNode node = new FlowFieldNode(isWalkable);

                    node.cellPos = new IntVector2(x, z);

                    gridArray[x, z] = node;
                }
            }

            //A flow field can have several start nodes
            List <FlowFieldNode> startNodes = new List <FlowFieldNode>();

            for (int x = 0; x < mapLength; x++)
            {
                for (int z = 0; z < mapWidth; z++)
                {
                    //If this is an obstacle
                    if (isObstacleInCell[x, z])
                    {
                        startNodes.Add(gridArray[x, z]);
                    }
                }
            }

            //Generate the flow field
            flowField.FindPath(startNodes, gridArray);


            //Add the values to the other array
            for (int x = 0; x < mapLength; x++)
            {
                for (int z = 0; z < mapWidth; z++)
                {
                    distanceToClosestObstacle[x, z] = gridArray[x, z].totalCostFlowField;
                }
            }
        }
        //Calculate the shortest path with obstacles from each square
        //Is called Dynamic Programming in "Programming self-driving car" but is the same as a flow map
        //Is called holonomic-with-obstacles in the reports
        public void DynamicProgramming(IntVector2 targetPos)
        {
            FlowField flowField = new FlowField();

            int mapLength = PathfindingController.mapLength;
            int mapWidth  = PathfindingController.mapWidth;

            //The final flow field will be stored here, so init it
            FlowFieldNode[,] gridArray = new FlowFieldNode[mapLength, mapWidth];

            for (int x = 0; x < mapLength; x++)
            {
                for (int z = 0; z < mapWidth; z++)
                {
                    //bool isWalkable = ObstaclesController.isObstacleInCell[x, z] ? false : true;      (MATT)
                    bool isWalkable = true;

                    FlowFieldNode node = new FlowFieldNode(isWalkable);

                    node.cellPos = new IntVector2(x, z);

                    gridArray[x, z] = node;
                }
            }

            //A flow field can have several start nodes
            List <FlowFieldNode> startNodes = new List <FlowFieldNode>();

            startNodes.Add(gridArray[targetPos.x, targetPos.z]);

            flowField.FindPath(startNodes, gridArray);


            //Add the values to the other array
            for (int x = 0; x < mapLength; x++)
            {
                for (int z = 0; z < mapWidth; z++)
                {
                    flowFieldHeuristics[x, z] = gridArray[x, z].totalCostFlowField;
                }
            }
        }