Не понимаю, с чего начать реализацию простого 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 шт):
Раз поле зрения в виде сектора круга, то нужно проверить две вещи:
- расстояние между точками
- угол между вектором, соединяющим две точки, и направлением взгляда
Как проверять расстояние, надеюсь, понятно. Подсказка - корень считать медленно, лучше сравнивать квадраты.
Про угол - есть несколько вариантов. Чтобы не считать каждый раз синусы/косинусы/корни, я бы сделал так:
Сделал две копии направления взгляда, и повернул их в разные стороны на половину угла обзора (умножением на матрицу поворота 2х2, в одну сторону просто, а в другую - на ту же матрицу, но транспонированную).
Взял векторные произведения между направлением на цель и этими двумя векторами. Раз векторное произведение всегда трехмерное, в исходных векторах считаем Z=0. У результата всегда будут X=0, Y=0, поэтому их не считаем, а считаем только Z.
Дальше смотрим на знаки двух получившихся чисел - если одно больше нуля, а второе меньше, то цель входит в угол обзора (методом тыка подбираете, какое из чисел должно быть положительное, а какое отрицательное).