Аналитическая геометрия - прекрасная вещь, особенно для использования в играх. Но вот незадача - почему использование обычных общепринятых определений и теорем при работе с осями и углами на плоскости работают не так, как следовало бы работать?
Дело в том, что стандартная ось и ось GTA SA хоть и схожы, но имеют различие. 0 градусов не 0, и 180 тоже не 180. Почему же?
Как видно, углы смещены путём поворота осей на 90 градусов против часовой стрелки.
Из этого следует, что уже X не связан с cos, а Y не связан с sin. X уже будет связан с sin, а Y будет уже связан с cos.
Как пример, попробуем понять, почему именно так.
Создадим два рисунка с осями без названий. Один рисунок - для Y, второй - для X.
Узнаем, как должны изменяться координаты относительно поворота.
А теперь повернем эти рисунки на 90 градусов по часовой стрелке.
Как мы видим, Y связан с cos, а X связан с -sin. В итоге, получаем, что если мы хотим создать какой-либо элемент впереди игрока, то:
PHP код:
new Float:p[4];
new Float:dist = 5.0; //дистанция, на котором будет создан объект
GetPlayerPos(playerid,p[0],p[1],p[2]);
GetPlayerFacingAngle(playerid,p[3]);
CreateObject(modelid,p[0]+dist*-floatsin(p[3],degrees),p[1]+dist*floatcos(p[3],degrees),p[2],0.0,0.0,0.0,300.0);
Хотите создать элемент где-то сбоку игрока, или даже сзади? Просто добавьте к текущей ротации игрока требуемый угол.
PHP код:
new Float:p[4];
new Float:dist = 5.0; //дистанция, на которой будет создан объект
GetPlayerPos(playerid,p[0],p[1],p[2]);
GetPlayerFacingAngle(playerid,p[3]);
p[3] = p[3] + 45.0; //прибавление угла; можно и отнимать
CreateObject(modelid,p[0]+dist*-floatsin(p[3],degrees),p[1]+dist*floatcos(p[3],degrees),p[2],0.0,0.0,0.0,300.0);
Задается вопрос: А зачем все эти синусы и косинусы? Нет другого способа? Ответ: нет, нету. Синус и косинус позволяют нам делать создание элемента именно с наиточнейшим расстоянием от игрока.
Все эти отрезки (L1,...,L8) равны между собой, т.к. являются радиусами. Таким образом, синус и косинус помогают вычислить нам расстояния, которые нужно изменить по X и Y, чтобы получить такой радиус.
А теперь перейдем к трехмерному пространству, особенно к функции GetPlayerCameraFrontVector.
Как ни странно, эта функция ведет себя, как в стандартном пространстве и с учетом игрового одновременно. Но она уже возвращает данные, преобразованные косинусом и синусом, то есть уже использовать угол поворота игрока, в принципе, не совсем нужно. Ан нет, он всё равно потребуется в каком-нибудь случае, так как обновление данных о камере идет куда не так часто, как обновление ротации игрока по Z.
Таким образом, красная зона отвечает за значения по Y и X, а синяя зона - за значение по Z.
А каков же угол по Z у камеры? Z связан с sin, поэтому достаточно легко понять, что для узнавания угла наклона нужно использовать asin:
PHP код:
new Float:p[3],Float:ang;
GetPlayerCameraFrontVector(playerid,p[0],p[1],p[2]);
ang = asin(p[2]);
Изменение угла - от -90 до 90.
Как пример, сделаем так, чтобы создавался объект именно там, куда смотрит игрок.
PHP код:
new Float:p[3],Float:pp[3];
new Float:dist = 5.0;
GetPlayerCameraFrontVector(playerid,p[0],p[1],p[2]);
GetPlayerCameraPos(playerid,pp[0],pp[1],pp[2]);
CreateObject(3798,pp[0]+dist*p[0],pp[1]+dist*p[1],pp[2]+dist*p[2],0,0,0);
Напомню, что здесь мы не используем sin и cos, так как GetPlayerCameraFrontVector уже высчитала нам различие.
Использовать позицию игрока будет неверным способом, так как камера смотрит не точно на позицию игрока.
Автор темы и рисунков: Quantra