Описания и обьяснения ниже,
Вид от третьего лица
Несмотря на мои ожидания, я заметил что у многих людей есть явные проблемы с пониманием и написанием кода этой части. В частности для вращаемой камеры.Конечно, вращение камеры вокруг двух осей может показаться тяжелым, но по-сути реализуется довольно просто: На картинке выше можно увидеть представление векторов для пары углов (обозначающих "горизонтальный" и "вертикальный" поворот камеры).
На левой части показано, что происходит в плоскости XY. Скорее всего вы уже знаете, о чем это (если пытаетесь сделать трехмерную игру) - компоненты вектора единичной длины вычисляются с помощью функций cos и sin соответственно.
Правая часть немного сложнее - тут показано (сбоку) что происходит при добавлении третьей оси и второго угла. Бывший XY вектор теперь плоский (потому что мы смотрим на него сбоку), и обозначен пурпурным цветом. Вращение вектора по вертикали уменьшает его длину в плоскости XY, и добавляет значение оси Z. Код для этого получается следующий:
vx = cos(pan) * cos(tilt); vy = sin(pan) * cos(tilt); vz = sin(tilt);Или, если вы больше любите функции lengthdir_ (и/или градусы),
vx = lengthdir_x(lengthdir_x(1, pan), tilt) vy = lengthdir_x(lengthdir_y(1, pan), tilt) vz = lengthdir_y(1, pan)После формирования вектора, настройка положения камеры проходит крайне просто:
d3d_set_projection( target.x + vx * distance, target.y + vy * distance, target.z + vz * distance, target.x, target.y, target.z, 0, 0, 1)(тут, distance - переменная, обозначающая расстояние между камерой и объектом)
Cel shading
На момент написания этой записи, GameMaker все еще не поддерживает шейдеры. Тем более в версии 8.0, для которой я предоставляю примеры (ради совместимости). Но, если в вашей игре не так уж и много полигонов, то есть один старый фокус для cel shading'а:- Включаем скрытие обратных сторон полигонов (backface culling)
- Рисуем модель как обычно
- Рисуем немного большего размера, черный вариант модели с нормалями (полигонами) смотрящими в обратно направлении.
Конечно, это не очень хорошая стратегия для больших моделей (поскольку количество операций рисования удваивается), но для низко-полигональных моделей это не заметно.
Тени
Это еще одна вещь, которую не стоит делать, если у вас высоко-полигональные модели, и что применимо тут в связи с отсутствием таковых (и простотой реализации).Используемый тут "фокус" заключается в том, что с помощью 3d трансформаций (d3d_transform_) можно "расплюснуть" модель (в данном случае сделать ее размер по оси Z нулевым), и нарисовать ее черным цветом, что будет выглядеть как тень. Опять таки, это удваивает количество рисуемых полигонов, поэтому для более сложных моделей лучше отрисовывать модель в поверхность, и потом рисовать оную.
Простая трехмерная физика
Несмотря на типичные представления об этом, реализация трехмерного движения лишь немного сложнее реализации двухмерного. С различием в нужде добавления лишней переменной (обычно z), которая будет меняться и использоваться при рисовании. В этом примере прыжки и столкновения между персонажем и полом занимают всего лишь 6 строк:// Z movement: if (z > 0) zspeed -= 0.5 // accelerate downwards if in air z += zspeed if (z < 0) { // hit ground z = 0 zspeed = 0 } if ((z <= 0) && keyboard_check(vk_space)) zspeed = 5 // jumpingЯ постараюсь сделать отдельную запись по поводу трехмерных столкновений позже.