Игра в материале
Unreal Tournament 2004
?Рейтинг
Игромании
9Рейтинг
игроков
PC
Жанр: Боевик, Боевик от первого лица
Серия: Unreal Tournament
Мультиплеер:  Интернет, локальная сеть (32)
Разработчик: Epic Games, Digital Extremes
Издатель: Atari
Дата выхода: 16 марта 2004
Игровое программирование. Уроки скриптописания

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

Самопал — Игровое программирование. Уроки скриптописания
материал открывает серию статей, в которы
Игроманияhttps://www.igromania.ru/
Самопал
Игровое программирование. Уроки скриптописания

Для многих начинающих игростроевцев, которые уже собирают свою команду, чтобы слепить на коленке очередной шедевр, программирование часто видится жутким монстром, с которым непонятно как бороться. Вроде и в 3D уже рисовать умеют, и в Photoshop кисточкой сноровисто работают, и другие полезные программы неплохо знают... Но как только дело доходит до кода, начинается паника и неразбериха: “Кто спрограммирует? Кто напишет заветные строчки? А если и напишет, то как в них потом разобраться?!”.

Данный материал открывает серию статей, в которых мы на простых примерах научим вас читать с листа и писать несложный программный код. Суперкрутыми программистами вы, разумеется, не станете (для этого надо учиться значительно дольше), но иероглифы кода перестанут быть для вас чем-то непонятным, от чего нужно держаться подальше.

Сегодня мы расскажем вам, как создать игровой мутатор оружия, превращающий заурядную шестистволку UT2004 в смертоносный плазмаган “Мегакиллер”. Пример, с одной стороны, несложный: разберутся даже самые начинающие. С другой стороны — ощутимый результат будет достигнут уже по факту прочтения вами статьи (и отработки ее на практике). Вы сами напишете мутатор для UT и опробуете его в игре.

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

Установка среды разработки

В UT2004 встроен собственный компилятор UCC для игровых скриптов. Но, к сожалению, он является консольным приложением и компиляция в нем — весьма трудоемкий процесс. Поэтому компания Epic Games выпустила программный пакет Unreal Developer Environment (далее — UDE), который может заметно упростить процесс написания игровых скриптов и их компиляцию. UDE распространяется в виде ut4mod-файла, то есть инсталлируемого игрового модуля.

При запуске установки модуля никаких особых манипуляций совершать не нужно — модуль сам определит наличие игры на вашем винчестере (через реестр) и путь к ней. Просто кликните кнопку Next. После установки на рабочем столе появится ярлык для UDE.

Классы игры и иерархия

Вся логическая составляющая UT представляет собой совокупность классов объектов, которые объединены в строгую иерархическую схему — так называемое дерево наследования. О наследовании и объектно-ориентированном программировании читайте на отдельном текстовом блоке.

Распаковка игровых скриптов

Изначально uc-файлы, содержащие классы объектов, упакованы в u-файлы. Но для работы с UDE нам придется их распаковать. Для этого в папке UT2004\System создаем bat-файл (или cmd) со следующим содержимым: @for /f "tokens=*" %%a in ('dir /b *.u') do ( ucc batchexport %%a class uc ..\%%~na\Classes ). Затем стартуем этот файл, и через 2—3 минуты все требуемые скрипты будут распакованы.

Запускаем UDE, появится окно мастера настройки среды разработки (в дальнейшем это конфигурирование можно повторить по команде File/Wizards/The UDE Setup Wizard внутри программы). Настроек несколько, и все их можно использовать со значениями по умолчанию. Также необходимо проверить, чтобы пункт Create Class/Package Trees (рис. 1.) был активным (он будет выведен на шаге 3 — Step 3: Class/Package Tree). Наконец, жмем Finish и ждем около минуты, пока среда разработки просканирует игровую папку на наличие файлов скриптов и объединит все найденные классы в дерево классов.

Настройка среды разработки

Перед нами среда разработки. Для организации рабочего пространства перемещаем открытые окна влево основного экрана с помощью соответствующей кнопки в правом верхнем углу каждого открытого окна. Теперь окна будут выезжать при наведении курсора на соответствующие значки панели слева. Для нас важны два окна: Classes (рис. 3.) и Packages (рис. 4.). В первом окне представлено иерархическое дерево всех игровых классов. Во втором — файлы скриптов в соответствии с их принадлежностью игровым архивам (u-файлам).

Двойной клик на любом пункте этих окон автоматически открывает соответствующий uc-файл/класс. Заголовок текстового окна с кодом вынесен влево, что весьма необычно, поэтому для закрытия окна нужно кликнуть на крестик в левом верхнем углу (а не в правом, как это обычно делается в Windows).

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

Принципы объектно-ориентированного программирования

В ООП существуют три основных принципа, на которых строятся практически все логические манипуляции с объектами.

Инкапсуляция — объединение внутри объекта данных с методами для их обработки. Например, если рассматривается класс “Лампочка”, то у него должны быть методы “включить свет” и “выключить свет”.

Наследование — создание класса объектов на основе уже существующего класса. При этом создаваемый класс будет не только содержать все данные и методы базового класса, но и обладать своими собственными. Методы базового класса могут быть переопределены. Примеры наследования и переопределения: если класс “Пегас” наследуется от класса “Лошадь”, то у первого появляется новое свойство — “крылья” и соответствующий метод “махать крыльями”. Все остальное у этих двух классов одинаковое. Если мы рассмотрим класс “Русалка”, основанный на классе “Человек”, то в данном случае будет иметь место переопределение свойства “ноги” на “рыбий хвост”, а метод “двигаться” будет вместо движения ног отвечать за перемещение хвоста.

Полиморфизм — что это такое, проще всего рассмотреть на конкретном примере. Рассмотрим два класса объектов — “Пегас” и “Лошадь”. Полиморфизм заключается в том, что мы можем рассматривать любого пегаса как лошадь и, например, у обоих объектов выполнять метод “кушать траву” или “бежать галопом”.

Многие начинающие программисты не различают понятия “класс” и “объект”. Но при этом эти два понятия различаются примерно так же, как и, скажем, чертеж устройства и готовое устройство в магазине. В жизни их спутать трудно.

Создание проекта

К сожалению, в UDE кнопка “Создать новый проект” отсутствует. Поэтому создаем в корневой папке UT2004 файл CreateNewClass.bat с командами:

set pkg=Megakiller

md %pkg%

md %pkg%\Classes

echo class %pkg% extends //base class>> %pkg%\Classes\%pkg%.uc

Значение переменной pkg — это имя нашего проекта (в данном случае — Megakiller). Остальные строки генерируют “пустой” скрипт.

После запуска пакетного файла в среде разработки выполняем команду UT2004 / Refresh Package/Class Tree. Теперь в списке архивов появился новый пункт Megakiller, а в нем скрипт Megakiller.uc. Этап подготовки завершен, переходим к программированию.

Идея модификации

Идея мутатора заключается в следующем: когда игрок стреляет в альтернативном режиме из “Мегакиллера”, стволы вместо пуль выпускают энергетические лучи, как у шокового ружья. При соприкосновении луча с любым препятствием происходит взрыв плазмы, который наносит здоровью противника заметный урон. При последовательном попадании нескольких лучей в одного и того же противника враг начинает гореть, а та часть тела, куда попал заряд, ампутируется.

Перед изучением нижеследующей информации настоятельно рекомендуется изучить текстовый блок “Анатомия Unreal-класса”.

Внимание! Читая нижеследующие абзацы, смотрите соответствующие строки в листинге кода, приведенном на отдельной странице (номера строк указаны слева от кода).

Класс оружия

Наше оружие будет объектом нового игрового класса Megakiller, основанном на уже существующем классе Minigun (строка 1). “Мегакиллер” переопределяет некоторые свойства (строка 2) родительского класса (строки 2-7): альтернативную стрельбу (FireModeClass), событие при получении оружия (PickupClass), а также описание оружия (Description). Стоит заметить, что основным режимом стрельбы является FireModeClass(0), а альтернативным — FireModeClass(1).

35 Kb

Рис. 1. Диалог создания дерева классов и архивов.

Класс альтернативной стрельбы

Класс альтернативной стрельбы для “Мегакиллера” представляет собой переработанный базовый класс MinigunAltFire. Для создания этого класса кликаем правой кнопкой мыши на нашем проекте Megakiller в окне Packages и в контекстном меню выбираем Create Sub Class. В открывшемся диалоговом окне (рис. 3.) в поле Parent Class вводим имя базового класса (MinigunAltFire), а в New Class Name —имя нашего нового класса (MegakillerAltFire). Обязательно ставим галочку в самом низу окна и жмем Оk. После этого в нашем проекте появляется новый файл MegakillerAltFire.uc.

27 Kb

Рис. 2. Окна с деревом классов и списком архивов.

В начале файла объявляем несколько новых свойств для объектов класса (строки 2-5): визуальный тип взрыва (ExplosionClass), визуальный тип следа от взрыва, например на стенах (ExplosionDecalClass). Тип луча при альтернативной стрельбе (BeamEffectClass) и радиус поражения при взрыве (DamageRadius).

Методы должны объявляться в порядке, обратном порядку обращения к ним. То есть если метод X вызывает метод Y, то Y должен быть объявлен перед X. С учетом этого добавляем два новых метода Explode и BlowUp и переопределяем имеющийся SpawnBeamEffect. О последнем стоит упомянуть отдельно. Дело в том, что все оружие делится на две категории: оружие непосредственного поражения (пули, лучи) и оружие, поражающее посредством снарядов (ракет, осколков). В первом случае противник, на которого нацелено оружие, получает повреждение моментально, во втором случае решение о повреждении принимается после взрыва снаряда с учетом множества факторов (например, попал ли противник в радиус поражения). Рассмотрим эти методы детально.

Метод SpawnBeamEffect (строки 23-30) имеет стандартный интерфейс, обеспечивающий успешный расчет попадания. Объявляем локальную переменную ShockBeamEffect (ключевое слово "local"), значение которой задаем с помощью специальной функции Spawn с аргументами: какой эффект луча мы хотим получить, в каком направлении и откуда луч испускается. Наконец, в точке соприкосновения луча устраиваем взрыв, вызвав метод Explode.

В методе Explode (строки 11-22) используется объект Instigator для уточнения, кто именно осуществил выстрел. После проверки, что взрыв возможен (луч не ушел в небо, например), воспроизводится звук взрыва и создаются спрайтовые визуальные эффекты для имитации взрывной волны и следа от взрыва на стенах. Затем проверяется, попадает ли игрок в зону поражения (строка 19). Если попадает, ему наносится повреждение в размере DamageMin (строка 41).

Для вычисления расстояния от игрока до центра взрыва используется функция VSize (длина вектора). В конце вызывается метод физического взрыва для противников — BlowUp (строки 6-10). Этот метод задействует всего две функции объекта Instigator — HurtRadius и MakeNoise. Первая функция создает сферу поражения требуемых силы и радиуса в нужной точке пространства, вторая — информирует ИИ игры о том, что мы только что пошумели.

Свойства, задаваемые в соответствующем блоке (строки 31-43): спецэффекты взрыва (ExplosionClass) и следы от него (ExplosionDecalClass), тип луча (BeamEffectClass), огонь из ствола при выстреле (FlashEmitterClass), радиус (DamageRadius) и некоторые параметры поражения при взрыве (DamageMin, DamageMax, bSplashDamage и bRecommendedSplashDamage). Плюс тип повреждений при взрыве (DamageType).

18 Kb

Рис. 3. Диалог создания подкласса.

Классы повреждения

По уже известной нам схеме добавляем еще два игровых класса. Класс наносимых оружием повреждений при взрыве MegaBeamDamage наследуется от базового класса DamTypeShockCombo. В новом классе переопределяются значения параметров: горит ли тело убитого врага(bFlaming), наносится ли урон дружественным игрокам (bSuperWeapon), наносятся ли повреждения при прямом попадании мгновенно (bInstantHit) и предохраняет ли броня от травм (bArmorStops).

Класс MegakillerPickup базируется на MinigunPickup и служит для одной цели: как только игроку в руки попадает “Мегакиллер”, ему выдается уведомление об этом, что проиллюстрировано в строках 4-5 листинга 4.

35 Kb

Рис. 4. Окно компиляции.

Класс игрового мутатора

Игровой класс MegakillerWeaponMod создаем на основе стандартного класса модов Mutator с параметром config(user). В классе переопределяется одна-единственная функция — CheckReplacement (строки 2-33), задача которой состоит в подмене всех имеющихся экземпляров минигана “Мегакиллерами”. А располагаться оружие может в одном из трех мест:

— в специальных точках карты (строка 7). Объект класса xWeaponBase позволяет узнать тип оружия с помощью обращения к полю WeaponType и при необходимости произвести замену (строка 11).

— просто лежать на карте (строка 15). Тут нам помогает класс WeaponPickup (строка 15). Подмена осуществляется функцией ReplaceWith (строка 19).

— оружие, которое есть у игрока в боекомплекте. Используемый класс объекта WeaponLocker дает возможность в цикле (строка 26) по очереди перебрать все имеющиеся единицы оружия и заменить “миниган”, если таковой имеется (строки 28-29).

В конце кода задаются значения параметров мутатора (строки 34-40): тип оружия по умолчанию (DefaultWeapon) и описания мутатора (GroupName, FriendlyName, Description).

13 Kb

Рис. 5. Сообщение об ошибке и справка.

Исходный код модификатора
17 Kb
51 Kb
15 Kb
16 Kb
41 Kb
35 Kb 27 Kb

Дуэли на "Мегакиллерах" иногда превращают обычный бой в феерическое зрелище.

Чернокожий стрелок пытается безуспешно подстрелить "античную" мадам.

25 Kb 39 Kb

Местные леди способны просто-таки заряжать вас энергией!

Каждый Чебурашка мечтает о большой пушке!

Компиляция и тестирование

Когда все скрипты готовы, остается только откомпилировать проект командой UT2004/Quick Compile Active Document (должен быть открыт любой скрипт проекта). Появится сообщение, что проект Megakiller не прописан внутри файла UT2004.ini (а это необходимо для компиляции). Поэтому кликаем Yes, а затем в следующем окне Ok.

Если все нормально, то через 10—20 секунд проект будет откомпилирован (редактор UnrealEd не должен быть запущен), а кнопка Ok в левом нижнем углу окна компиляции станет активной (рис. 4.). Если же надпись сменилась на Error, значит, во время компиляции произошла ошибка. Если кликнуть на этой кнопке, внизу экрана на вкладке Compile Results будет выведено, что именно вызвало ошибку, а в правом нижнем углу окна UDE появится небольшая справка о возможных способах устранения ошибки (Рис. 5).

Если все прошло успешно, то запускаем игру, выбираем Instant Action в меню, ставим режим Deathmatch и на вкладке мутаторов добавляем мутатор Megakiller, после чего кликаем Play. Когда мод протестирован в деле, его можно выложить, например, в интернет. Дистрибутивными файлами являются Megakiller.u и Megakiller.ucl (автоматически генерируется при компиляции) из папки UT2004\System.

Для того чтобы вы сразу могли оценить действие мутатора и поиграть в него, мы выкладываем полную версию “Мегакиллера” на наш диск.

Анатомия Unreal-класса

Класс игры имеет унифицированную архитектуру. Структура файла следующая.

 — Заголовок, содержащий объявление класса:

class ClassName extends BaseClass config(user); где ClassName — название нашего класса, BaseClass — базовый класс, на основе которого создается новый класс, config(user) — пример параметра в объявлении класса — указывает, что используются конфигурационные параметры из файла User.ini. Все игровые классы имеют в качестве родительского класс Object или любой из его классов-потомков. Лексемы class и extends являются зарезервированными обязательными атрибутами объявления игрового класса. Важно запомнить, что корректным является только тот uc-файл, имя которого совпадает с названием объявленного в нем класса. И в одном uc-файле должен быть описан только один класс.

 — Объявления новых переменных (свойств класса) в следующем формате:

var() class<PropertyClass> PropertyName; или var() SimpleType PropertyName; где PropertyClass — название класса создаваемого свойства, SimpleType — элементарный тип, такой как byte (байтовое значение от 0 до 255), int (знаковый целый тип), bool (логический тип), float (знаковый вещественный тип), string (символьная строка) и т.д. (полный список элементарных типов можно посмотреть в справке UDE), PropertyName — имя нового свойства.

— Объявления новых методов или переопределение унаследованных от базового класса имеют следующий вид:

simulated function FunctionName( VariableType VariableName, ... ) { ... } где FunctionName — имя нового метода (или переопределяемого), содержимое круглых скобок — аргументы метода — может отсутствовать, состоять из одного или нескольких значений. В этом случае VariableType  — тип (класс) аргумента, VariableName — имя аргумента. Обратите внимание, что в случае переопределения метода родительского класса, заголовок (интерфейс) метода (строка, стоящая перед фигурными скобками) не должен модифицироваться! Лексема simulated — один из возможных параметров метода — говорит о том, что метод будет выполняться только на клиентской машине. Фигурные скобки обособляют в коде тело метода.

 — Задание параметров (свойств) по умолчанию класса:

defaultproperties { Variable1Name=Class'Package.ClassName'; Variable2Name=Variable2Value; ... } где defaultproperties  — лексема, указывающая начало блока свойств, Variable1Name — название свойства, представляющего собой некоторый другой объект класса ClassName, содержащегося в u-файле с именем Package. Параметр Variable2Name имеет элементарный тип, поэтому и присваиваемое значение Variable2Value должно иметь тот же тип. Символ "=" означает операцию присвоения значения справа переменной слева. Фигурные скобки обособляют в коде блок присвоений.

* * *

Вот и подошел к концу наш первый экскурс в мир игрового программирования. Мы не только сделали интересный мутатор, но и научились читать несложный программный код. В одном из ближайших номеров “Мании” мы продолжим разбираться в азах программирования и, изучив более продвинутые строки кода, создадим более сложный мутатор.

Комментарии
Загрузка комментариев