Найти в Дзене
ZDG

Параллакс в играх. Часть 1: Движение сквозь звёзды

Другие материалы: симуляция огня, симуляция воды

Рассмотрим простую, но очень важную технику, которая широко применяется в 2D-играх: параллакс. Это греческое слово обозначает разницу положений объекта, когда мы смотрим на него с разных позиций. Если мы смотрим на 2 дерева: одно вблизи, а другое вдали, то шагнув на пару метров вправо или влево, мы увидим, что ближнее к нам дерево сместилось сильнее, чем дальнее. Наш мозг натренирован так, чтобы по параллаксному смещению определять расстояние до объекта.

Давайте посмотрим на эту схему:

У глаза есть угол зрения. И как можно видеть, в угол зрения помещается разное количество объектов на разных расстояниях. Вблизи мы можем увидеть только одно дерево целиком. Дальше можно увидеть сразу три дерева. И ещё дальше можно увидеть 5 деревьев. Как так получается? Оптическая система глаза устроена таким образом, что чем дальше объект – тем он меньше, несмотря на то, что его физический размер остаётся постоянным. Своими глазами мы видим примерно такую картину:

-2

И если мы сдвинемся влево или вправо на одно дерево, то в каждом ряду произойдет одинаковый сдвиг на одно дерево. Но только в ближнем ряду этот сдвиг будет равен 167 пикселов, в среднем 85 пикселов, а в дальнем 50 пикселов. Вот и получается, что хоть каждый ряд сдвинулся ровно на 1 дерево, но сам сдвиг чем дальше, тем меньше.

Таким образом, 2D-сцены, в которых присутствует параллакс, воспринимаются нами как имеющие глубину. Чем сильнее смещается объект относительно других объектов – там ближе он к нам. В играх параллакс используется для создания разных эффектов, и давайте начнём с движения в космосе сквозь звёзды. Звёзды изображаются точками на экране, и если бы они не двигались, мы не могли бы сказать, какая из них находится дальше, а какая ближе:

-3

Но как только они начинают двигаться с разными скоростями, создаётся иллюзия, что те звёзды, которые движутся быстрее – находятся ближе (см. работающую в браузере программу по ссылке).

Однако это фальшивка. Я просто генерирую звёзды со случайными скоростями, которые движутся в направлении из центра экрана к его краям. Это создаёт иллюзию параллакса, но не подкреплено реальной математикой. Получится ли более убедительная глубина, если применить реальный параллакс?

Первое, что нужно сделать – это получить зависимость смещения объекта от расстояния. Посмотрим на схему с одной звездой:

-4

Если нижняя полоска это плоскость экрана, то положение звезды на ней пропорционально положению звезды в своей плоскости (верхняя полоска). То есть положение звезды на плоскости экрана относится к положению звезды в своей плоскости так же, как расстояние до экрана относится к расстоянию до плоскости звезды.

экранная_x_звезды = x_звезды * расстояние_до_экрана / расстояние_до_плоскости_звезды

Если что, мы получили формулу перспективной проекции.

Теперь я сделаю следующее:

  1. Звёзды будут иметь координаты x, y, z, где z – это расстояние от наблюдателя
  2. Установлю самое далёкое расстояние, с которым можно работать (это подберу экспериментально)
  3. Сгенерирую массив звёзд, имеющих случайные координаты x, y и случайное расстояние z между плоскостью экрана и самым далёким расстоянием
  4. Все сгенерированные звёзды будут в каждом кадре приближаться, сокращая расстояние z
  5. Все сгенерированные звёзды будут отображаться на плоскость экрана по вышеуказанной формуле.
  6. Все звёзды, которые достигли плоскости экрана, или чья проекция на экран выходит за пределы экрана, будут отправляться на переработку – координаты x, y будут генерироваться заново, а расстояние будет задано максимальное, то есть вдали будет появляться новая звезда вместо старой. Я пускаю звёзды в переработку, чтобы не связываться с операциями удаления и добавления в массиве.

И вот что получилось: (см. работающую в браузере программу по ссылке)

Мне кажется, теперь звёзды движутся гораздо более убедительно. Хотя и первый вариант был по-своему интересен. Как вы думаете?

В следующих выпусках рассмотрим другие применения параллакса: дождь, снег и параллакс-скроллинг.