Программирование игр для Windows. Советы профессионала

Удачный угол зрения на спрайты


Эта тема наиболее сложная из всех, которые мы до сих пор рассматривали. При перемещении трехмерных спрайтов по экрану, с точки зрения наблюдателя все должно выглядеть так, словно объекты и в самом деле имеют три измерения. Наблюдатель в нашем случае — это игрок, и его позиция фиксирована. Обычно она имеет координаты (0,0,0) или слегка сдвинута по оси Z. В любом случае, когда спрайт, к примеру, делает поворот, и мы хотим, чтобы он выглядел как настоящий трехмерный объект, нам следует менять кадры этого спрайта на экране в последовательности, соответствующей реальной смене ракурсов «живого» объекта. (Такую фразу и не выговоришь на одном дыхании!)

Полное и элегантное решение этой проблемы слишком... масштабно для нас. Нам всего лишь требуется, чтобы наши программы, модели и алгоритмы. давали реалистичные результаты. Поэтому, алгоритм, который мы обсудим в этом разделе, едва ли решит поставленную задачу в полном объеме, и в будущем, вы наверняка внесете в него свои дополнения. Однако он является хорошей стартовой площадкой, а я всегда предпочитаю иметь хороший фундамент для последующего строительства, а не слабое его подобие, на котором после ничего и не соорудишь.

Как и при написании любой программы для любого компьютера, мы должны вначале четко определить задачу, а затем обдумать возможные пути ее решения. • Итак, проблема: как выбрать кадр для изображения объекта на основании угла между лучом зрения игрока и направлением «взгляда» самого объекта.

Замечание

В общем случае объект может передвигаться и не в том направлении, куда обращена его лицевая сторона, Мы не будем сейчас заострять внимание на этом варианте движения, чтобы чрезмерно не усложнять нашу задачу. Пока будем считать, что объект всегда движется в ту сторону, куда он обращен лицом. Это предположение вполне обосновано, так как в программе, которую мы впоследствии напишем, будут участвовать космические корабли с кормовыми дюзами. Точно так же и в играх типа Wolfenstein или DOOM игровые персонажи обычно движутся в том направлении, куда они смотрят (или в обратном, если они пятятся).




Попытаемся вначале проанализировать проблему. Нам необходимо определить вид объекта, который зависит от направления взгляда игрока и траектории объекта или направления его движения. Как мы уже говорили, луч зрения игрока можно зафиксировать и считать, что он всегда перпендикулярен экрану. Тогда нам нужно будет побеспокоиться только о векторе траектории объекта, выводимого на экран. На рисунке 8.7 изображена взаимосвязь между вектором направления взгляда игрока и некоторой траекторией передвижения объекта.



Теперь мы должны сделать вот что: возьмем игрушечную машинку или что-нибудь подобное и будем передвигать ее перед собой (шум мотора имитировать при этом не обязательно, можно все делать тихо). Проделав это, вы быстро придете к выводу, что рисуемое на экране изображение космического корабля, движущегося прямолинейно, практически одинаково для всех параллельных траекторий независимо от местоположения объекта. Конечно, это справедливо только частично, зато мы получили хорошую отправную точку для нашего первого алгоритма выбора правильного кадра.

Что же мы должны сделать:

§          Вычислить угол между траекторией движения объекта и лучом зрения игрока (который всегда направлен прямо в экран);



§          Разделить полученный угол на квадранты. Затем на основании полученного индекса выбрать наиболее подходящее изображение среди предварительно подготовленных оцифровкой фотографий модели или нарисованных в графическом редакторе. (Более подробно это обсуждается в разделе «Оцифровка объектов и моделирование».)

§          Вывести на экран подходящий кадр, используя аксонометрическую проекцию и масштабируя объект до необходимого размера.

 В результате на экране получается реалистичная картина.

Каким же образом находится угол между траекторией объекта и лучом зрения наблюдателя? Ответ может быть получен с помощью скалярного произведения векторов.



Мы знаем, что угол между двумя векторами можно найти с помощью скалярного произведения векторов, как это показано на рисунке 8.8.



Формула 8.4. Вычисление угла между наблюдателем и объектом.

Если мы зададим вектор направления взгляда, как V, а вектор скорости, как О, тогда угол между ними можно будет найти по следующей формуле:

Пусть V = (vx,vy,vz) и О = (ox,oy,oz), тогда



Если бы мы хотели сформулировать это действие словами, то могли бы сказать так: «Угол между V и О равен арккосинусу скалярного произведения этих векторов, разделенного на произведение длин векторов».

Угол между V и О, рассчитанный по этой формуле, имеет одну особенность: он всегда внутренний, то есть больше 0, но меньше 180 градусов. Следовательно, один и тот же результат, полученный по этой формуле, может соответствовать двум разным углам. Это происходит потому, что скалярное произведение не дает информации о направлении вектора (или о направлении, в котором вы отсчитываете положительный угол). Другими словами, эта формула всегда выдает наименьший из углов между двумя векторами. Если вы будете помнить об этом, то такое поведение данной формулы не будет большой проблемой. (Это напоминает бутерброд, который всегда падает маслом вниз. Если вы не знаете об этом, то такой результат может свести вас с ума. А кто предупрежден, тот вооружен.)

Рисунок 8.9 иллюстрирует указанную проблему графически. На этом рисунке показан вектор направления взгляда, три возможных положения вектора траектории и полученный в результате расчетов по формуле 8.4 угол.



Кстати, формулу 8.4 можно значительно упростить, вспомнив, что нас интересует только плоскость X-Z, так как луч зрения всегда перпендикулярен плоскости просмотра.

Но как же, в конце концов, определить действительный угол? Конечно, вы Могли бы воспользоваться еще и векторным произведением, чтобы решить, корректен ли угол, полученный в результате расчетов по формуле 8.4 или необходимо увеличить его еще на 180 градусов. Однако я слишком не люблю математику (возможно, именно поэтому я и доктор математических наук) и предпочитаю вместо грубой силы использовать тонкую интуицию.



Если мы сообразим, что вектор траектории объекта имеет ту же исходную точку, что и вектор направления взгляда, а затем проверим, в какой из полуплоскостей относительно луча зрения расположен Х-компонент вектора траектории, то мы сможем определить, больше или меньше 180° искомый угол. Это наглядно изображено на рисунке 8.10.



Применяя метод проверки Х-компонента, мы можем написать простую функцию, которая вначале рассчитывает угол, используя скалярное произведение, а затем проверяет, находится ли координата Х справа (положительная) или слева (отрицательная) от вектора направления взгляда. Если координата Х положительная, мы вычитаем угол, полученный с помощью формулы 8.4 из 360 градусов (это все равно, что прибавить 180). Затем мы можем взять рассчитанный угол и разбить его на 12 квадрантов (либо взять его модуль по основанию 12). Полученное число затем можно использовать как индекс для нахождения кадров спрайта. (Конечно, кадры должны быть расположены в правильном порядке, то есть кадрам, полученным при вращении объекта против часовой стрелки с шагом в 30 градусов, должны соответствовать индексы от 0 до 11. При этом нулевой индекс должен указывать на кадр объекта, повернутого тыльной стороной к наблюдателю.)

Если значение координаты Х отрицательное, происходит то же самое за исключением того, что будет использован другой банк изображений, и оперировать потребуется с абсолютным значением X.

Кадры, которые я создал для демонстрации этого алгоритма, расположены в файле VRYENTXT.PCX. Они расположены слева направо и сверху вниз. Каждая картинка содержит изображение, повернутое на 30° против часовой стрелки, а в исходной позиции нос корабля направлен прямо в экран (или, с точки зрения игрока, корабль обращен к нему тыльной стороной). Этот же файл мы использовали и в предыдущем примере.

Демонстрационная программа будет использовать рассчитываемые углы для выбора кадров. Но мы же не можем поместить корабль просто в пустоту. Это будет скучно! Нам надо добавить что-нибудь для оживления картинки.Я предлагаю создать трехмерное звездное небо. Под трехмерностью я здесь понимаю то, что звезды будут перемещаться к вам или от вас, а не влево или вправо, как это мы делали раньше, Надо отметить, что космический корабль, летящий в звездном пространстве, выглядит превосходно. Однако следует еще поговорить о том, как же создается такое трехмерное звездное небо.


Содержание раздела