Не понимаю, с чего начать реализацию простого FOV

Вот есть задача. Есть Юниты, у них задана координата x,y У юнитов есть так же угол зрения = 60 градусов и направление взгляда, задано вектором, например (1,0) или (0.7, 0.7), дистанция взгляда равна 2(клеткам).Результатом работы программы должно быть: Что видит каждый юнит. Просто не понимаю, куда копать и как реализовывать.

Что на данный момент имею:

std::array<std::array<char, 30>, 30> map{};

Карта, где:

constexpr char empty_cell == 'e'// - пустая клетка 
constexpr char unit_cell == '*' //-  такая кледка говорит о том, что тут  находится 
наш юнит
template<typename T>
struct TransformComponent
{
    TransformComponent(T x, T y):x(x), y(y){};
    T x;
    T y;
};


class Unit
{
    public:
        Unit(TransformComponent<int> position, TransformComponent<float> direction, 
                                               std::string unit_title):position(position), 
                                               direction(direction),
                                               unit_title(unit_title){};
        TransformComponent<int> position;
        TransformComponent<float> direction;
        float vision_angle = 60;
        int distance_of_view = 2;
        std::string unit_title;

};

Как реализовать такую задачку в консоли? Подскажите ресурсы, информацию, что гуглить, пожалуйста. Как я хочу решить задачу и с какими проблемами сталкиваюсь: Сначала:

for(auto unit : units)
    { 
    //Бежим по всем существующим юнитам
    for (int i = 0; i<unit.vision_angle; i++) {
    //Бежим от 0 до нашего угла зрения
    /*Вот вопрос: Как преобразовать направление взгляда(1,0) в угол обзора?*/
    int nx = round(cos(deg)*unit.distance_of_view);
    int ny = round(sin(deg)*unit.distance_of_view);
    /*получаю точку на заданной дистанции с каждого угла*/
    if(map[ny][nx] == '*')
    {
        std::cout << unit.unit_title << "  See something\n";
    }

Ответы (1 шт):

Автор решения: HolyBlackCat

Раз поле зрения в виде сектора круга, то нужно проверить две вещи:

  • расстояние между точками
  • угол между вектором, соединяющим две точки, и направлением взгляда

Как проверять расстояние, надеюсь, понятно. Подсказка - корень считать медленно, лучше сравнивать квадраты.

Про угол - есть несколько вариантов. Чтобы не считать каждый раз синусы/косинусы/корни, я бы сделал так:

  • Сделал две копии направления взгляда, и повернул их в разные стороны на половину угла обзора (умножением на матрицу поворота 2х2, в одну сторону просто, а в другую - на ту же матрицу, но транспонированную).

  • Взял векторные произведения между направлением на цель и этими двумя векторами. Раз векторное произведение всегда трехмерное, в исходных векторах считаем Z=0. У результата всегда будут X=0, Y=0, поэтому их не считаем, а считаем только Z.

    Дальше смотрим на знаки двух получившихся чисел - если одно больше нуля, а второе меньше, то цель входит в угол обзора (методом тыка подбираете, какое из чисел должно быть положительное, а какое отрицательное).

→ Ссылка