04 октября 2005
Обновлено 17.05.2023

Игровое программирование. Уроки скриптописания, часть 3

Игровое программирование. Уроки скриптописания, часть 3 - изображение обложка

Замедление в духе “ Матрицы ” (slo-mo) впервые было использовано в Max Payne. После этого многие игроделы еще не раз пытались выехать за счет slo-mo, но, увы, большинство “замедленных” проектов провалились. Исключением должна стать грядущая F.E.A.R.. Пока еще не совсем понятно, как разработчикам удастся совместить вид от первого лица и замедление, но… мы попробуем сделать это раньше Monolith. Сегодня мы продолжим изучать принципы построения игровых скриптов на примере Unreal Tournament 2004 и создадим настоящий slo-mo-мод, превращающий игру в залихватскую “Матрицу” с лазерными пушками и… возможностью играть по сети.

Все упоминаемые в статье программы и файлы можно взять с нашего диска.

Концепция модификации

Что такое комбо в UT2004, знают, наверное, все. Но далеко не все знают, что разработчики оставили модмейкерам возможность подключать до 16 дополнительных комбо. Изначально же их в игре менее десятка. Для непосвященных поясним, в чем их суть: когда уровень адреналина равен 100 единицам (за счет отстрела вражин или подбора адреналиновых капсул), игрок может быстро нажать определенную комбинацию из четырех клавиш ( Вперед , Назад , Влево , Вправо ) и тем самым активировать соответствующее комбо (невидимость, скорость и некоторые другие). Длительность комбо ограничена из соображений игрового баланса, поэтому через несколько секунд сверхспособности пропадают.

Разберемся, какие у нас есть возможности для создания slo-mo-комбо. Во-первых, существует функция замедления скорости игры. Во-вторых, можно изменять характеристики движения самого игрока, в том числе скорость бега по земле и высоту прыжка. Что если объединить эти две возможности?

Однако мы хотим сделать полноценный сетевой мод, а не просто некое абстрактное slo-mo для зарубов с ботами. И тут могут возникнуть трудности. Что делать, когда, например, один игрок только начал комбо, а второй его уже окончил? Все эти моменты мы обязательно учтем.

Реализация

Подробно рассмотрим все аспекты программирования мода. Во-первых, создаем пустой проект под названием Matrixed и загружаем его в UDE (как это сделать, смотрите в первой части цикла “ Игровое программирование” ). В моде у нас будут присутствовать всего два класса. Первый будет отвечать за комбо, а второй — за мутатор, добавляющий его в игру.

Класс комбо

(ЛИСТИНГ 1)

Любое игровое комбо является наследником класса Combo и переопределяет ряд методов и свойств родительского класса. Итак, после заголовка класса MatrixCombo ( строка 1 ) объявляем пару дополнительных переменных ( строка 2 ) — LeftTrail и RightTrail , которые мы используем для создания эффекта трассирующего следа от ног игрока (как в комбо Speed ). Стоит отметить одну особенность: данные переменные объявляются после лексемы var , а не var() , потому что предназначены только для внутреннего использования объектом класса.

В строке 3 переопределяем метод StartEffect , который отвечает за начало действия комбо. Аргументом данного метода является объект класса xPawn — игрок, активировавший комбо.

Далее инициализируем так называемые эмиттеры ( строки 5 и 7 ). Этот термин наверняка знаком всем, кто работал с системами частиц, например в 3DS Max. Эмиттер — это источник испускаемых частиц, которые ведут себя по определенным законам. В нашем случае создаваемые объекты относятся к классу SpeedTrail , частицы такого эмиттера образуют трассирующий след, чем-то напоминающий световой меч из Star Wars. Эти объекты мы закрепляем на ногах игрока ( строки 6 и 8 ) командами AttachToBone(X,Y) , где X — имя прикрепляемого объекта, а Y — название кости скелета персонажа, к которой присоединяется X. В качестве костей скелета мы используем rfoot (правая ступня) и lfoot (левая ступня). Теперь у игрока в режиме slo-mo появится визуальный элемент “огонь из-под копыт”!

Следующий шаг — улучшение физических характеристик игрока. В строках 9-13 модифицируем скорость перемещения игрока по земле, в воздухе, под водой, высоту прыжка и управление в воздухе. При изменении свойств используется операция *X = Y (увеличить значение X в Y раз), хорошо известная каждому, кто программировал на C++.

Обращаясь к объекту Level.Game , мы разрешаем изменение скорости в мультиплеере ( строка 14 ) и замедляем скорость игры до 30% ( строка 15 ). Теперь новое комбо будет отвечать всем нашим требованиям.

Однако комбо должно быть завершено через какое-то время, поэтому мы должны также переопределить метод StopEffect ( строка 17 ). В строках 20-21 уничтожаем ранее созданные эмиттеры. Затем нужно выяснить, можно ли возвращать прежнюю скорость игры (возможно, какой-то игрок еще выполняет комбо в этот момент). Для этого используем новый тип цикла — foreach ( строка 22 ), с помощью которого можно перебрать все имеющиеся объекты требуемого класса (текущий элемент цикла — переменная X ). Проверяем три условия ( строки 24-25 ), обозначающих, что кроме нас кто-то еще выполняет комбо. Если условия выполнены, сбрасываем значения характеристик игрока на значения по умолчанию и выходим командой return ( строки 27-28 ). Если цикл завершился, но ни одной “коллизии” не обнаружено, мы можем сбрасывать не только значения для игрока, но и скорость игры на уровне (никаких последствий это не вызовет).

Нельзя обойтись и без важнейшей стадии создания комбо — задания параметров по умолчанию ( строки 34-42 ). Тут мы определяем: сообщение, появляющееся на экране в момент выполнения комбо, длительность комбо в секундах и четыре клавиши, быстрое последовательное нажатие на которые запускает комбо. В качестве цифровых значений можно использовать следующие: 1 — Вперед, 2 — Назад, 4 — Влево, 8 — Вправо. Разумеется, при этом учитывается раскладка клавиатуры игрока.

Рассмотренный класс теперь нужно использовать в связке с мутатором, который добавит новое комбо в игру.

Класс мутатора

(ЛИСТИНГ 2)

Принцип работы мутаторов мы уже рассматривали в предыдущих статьях данного цикла, поэтому остановимся на отдельных деталях, отличающих этот модификатор от созданных ранее (в двух предыдущих статьях). Итак, главные отличия — появление массива ссылок NotifyPlayer ( строка 2 ) и функции Timer ( строка 3 ). Первый служит для учета новых игроков (по сути — обычная очередь). Таймер же с заданной периодичностью отслеживает, кому нужно “дать” комбо.

В строках 13-39 представлена уже знакомая нам функция IsRelevant , отвечающая за применимость мутатора, а заодно выполняющая почти всю полезную работу по модифицированию геймплея. Объектами изменения являются сами игроки, поэтому прежде чем добавлять им новое комбо ( строка 24 ), следует убедиться, что данный объект — игрок ( строка 16 ). После проверки в цикле перебираются элементы списка имеющихся комбо-приемов, на первое свободное место записывается название нашего slo-mo-комбо.

Мало просто добавить новый элемент в список, надо еще создать объект класса MatrixCombo. Поэтому в строках 28-35 явным образом сохраняем ссылку на игрока, которому мы хотим добавить новую возможность. Тут нам поможет массив NotifyPlayer — в его первый найденный (в цикле) пустой элемент нужно сохранить ссылку. После этого запускаем таймер и указываем, что он должен однократно (значение false в качестве второго аргумента) сработать через полсекунды.

Таймер ( строки 2-12 ) функционирует предельно просто: один раз просматривается весь массив NotifyPlayer , как только обнаруживается непустой элемент (объект класса xPlayer ), ему добавляется новое комбо функцией ClientRecieveCombo , после чего ссылка из массива удаляется.

Поскольку наш мутатор может быть далеко не единственным, мы должны проверить совместимость с остальными модификациями. Такая проверка у нас осуществляется в строках 36-38 и является стандартной.

Наконец, мы задаем у мутатора параметры по умолчанию ( строки 40-44 ) — текстовые описания. После компиляции мутатор можно использовать в игре.

Исходный код модификатора

* * *

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

Цикл завершен, но тема далеко не закрыта, потому как в будущем мы еще не раз обратимся к игровому программированию при создании собственных модификаций.

Комментарии
Чтобы оставить комментарий,Войдите или Зарегистрируйтесь