В этой статье мы рассмотрим как сделать HUD (Heads-Up Display) к Вашему моду. Разбирается все довольно-таки детально, так что материал ориентирован на новичка, хотя некоторые знания не помешают (например что такое UCC :)). Скромно надеюсь, что данная статья Вам поможет в нелегком деле модостроительства (или ХУДостроительства :)).
Общие сведения
Все "рисование" на HUD`е (т.е. на экране игрока) осуществляется специальным объектом Canvas (Engine.Canvas), в нем же и содержатся все необходимые функции по рисованию. Если Вы уже изучали Java то возможно понятие Canvas`a (канвы) Вам уже знакомо. Сразу замечу, что по сути дела все рисование сводится к алгоритму:
Установить стиль (атрибуты) рисования (например цвет или прозрачность).
Указать начальную позицию рисуемого объекта на экране.
Нарисовать выбранную текстуру (буквы текстовой строки - это тоже текстуры).
Если Вы не знаете как располагаются координатные оси, вот Вам скрин:
HUD - это отдельный класс (Engine.HUD), в нем определена функция PostRender:
simulated event PostRender( canvas Canvas );
Именно в этой функции и осуществляется все рисование (в качестве параметра передается ссылка на Canvas - экран игрока). Эта функция вызывается игроком PlayerPawn при каждой перерисовке экрана. Возможно, у Вас возник вопрос "Если я сделаю свой класс наследующий от класса Engine.HUD, каким образом движок будет определять что надо вызывать именно PostRender в моем классе, а не в родительском?" Все просто - в классе GameInfo (собственно это и есть Ваш мод) определена переменная HUDType, значением которой и является ссылка на соответствующий HUD класс. Вывод из всего вышесказанного:
Нам надо сделать класс (например, MyHUD) наследующий от Engine.HUD (или от любого другого его потомка), в котором объявить функцию PostRender.
В функции PostRender при помощи методов Canvas рисовать то, что нам надо (об этом ниже).
Объявить новый класс наследующий от GameInfo и в defaultproperties которого написать строчку типа: HUDType=Class'MyHUD'
Если Вы еще не очень осознали, о чем идет речь - читайте дальше - будет разобран пример учебного HUD`a (глава "Рисуем!").
Замечание по сетевому HUD`у. HUD отображается на клиентской машине, поэтому Вы должны ставить слово simulated в Вашей функции PostRender, разумеется, если Ваш мод не мультиплеерный то simulated писать не надо.
Итак, теперь непосредственно рассмотрим класс Canvas и доступные в нем методы для рисования.
Объект Canvas
Основные свойства (переменные) класса Canvas
font Font - шрифт, которым будет отображаться текст, значение переменной Font - название текстуры шрифта. Например: "LadderFonts.UTLadder20".
float OrgX, OrgY - координаты точки (0,0), по умолчанию значения переменных OrgX, OrgY естественно равны 0.
float ClipX, ClipY - координаты крайне правого нижнего угла экрана. Значения этих переменных меняются в зависимости от текущего разрешения экрана, например, при разрешении 640x480, значение ClipX=640, ClipY=480.
float CurX, CurY - текущие координаты для рисования (например, для рисования текстуры с позиции (60,80) значения должны быть CurX=60, CurY=80).
byte Style - стиль рисуемого объекта (например эффект прозрачности), возможные значения:
(0) STY_None - невидимый объект, заметьте, что объект на самом деле "рисуется", но он не видим на экране.
(1) STY_Normal - "обычный" стиль
(2) STY_Masked - нулевой цвет (черный) рисуемой текстуры не отображается (для masked текстур).
(3) STY_Translucent - эффект прозрачности (за текстурой виден фон).
(4) STY_Modulated - каждый пиксель текстуры принимает значение цвета соответствующего пикселя фона.
color DrawColor - цвет рисуемого объекта, по умолчанию DrawColor=(127,127,127) (серый цвет). Значения цвета задаются через RGB значения, например:
Заметьте, что если при выводе текстур значение DrawColor не равно белому цвету (255,255,255) то все цвета текстуры претерпевают изменения.
Функции общего назначения.
function SetPos( float X, float Y ) - присваивает CurX=X, CurY=Y. Естественно, что
SetPos(30,40)
и
CurX=30;
CurY=40;
аналогичны по действию, просто первый вариант записывается быстрее : )
function SetOrigin( float X, float Y ) - присваивает OrgX=X, OrgY=Y.
function SetClip( float X, float Y ) - присваивает ClipX=X, ClipY=Y.
event Reset - установка начальных значений (default) всех переменных Canvas (Font,CurX,CurY и т.д.). Полезно когда надо восстановить первоначальные значения переменных одной строкой, вместо того чтобы писать утомительное:
function StrLen( coerce string String, out float XL, out float YL ) - возвращает размеры строки String (XL и YL) в зависимости от текущего шрифта.
Функции рисования.
function DrawText( coerce string Text, optional bool CR) - выводит строку Text в позицию (CurX,CurY) шрифтом Font и цветом DrawColor.
function DrawIcon ( texture Tex, float Scale ) - рисует текстуру Tex в позицию (CurX,CurY) с масштабом Scale.
function DrawRectangle ( texture Tex, float RectX, float RectY ) - аналогично DrawIcon, только масштаб по осям X и Y можно указывать различный.
function DrawPattern ( texture Tex, float XL, float YL, float Scale ) - рисует повторяющийся "узор" (паттерн) Tex в прямоугольной области, координаты верхнего левого угла этой области (CurX,CurY), а правого нижнего угла (XL,YL). Scale - масштаб самой текстуры Tex, причем в данном случае он реверсивен, т.е. при Scale=2 - текстура в два раза уменьшается, при Scale=0.5 в два раза увеличивается.
Примечание: в данном случае текстура выводится с позиции (0,0), поэтому если, к примеру, рисовать в центре экрана, то, возможно, что левый верхний угол текстуры не совпадет с левым верхним углом области (смотрите скрин, и Вам все станет ясно)
Пример DrawPattern - рисование с центра экрана, видно, что верхние левые углы области и текстуры не совпадают:
function DrawTile( texture Tex, float XL, float YL, float U, float V, float UL, float VL) - собственно это и есть функция на которой основываются DrawIcon,DrawRectangle,DrawPattern. Пояснению параметров отведена отдельная глава.
Специальные функции.
В данной статье эти функции не рассматриваются, чтобы не усложнять материал. Как только Вы разберетесь, как делать свой HUD, эти функции разберете сами без труда.
Рисуем!
Теперь прервемся от пояснений и попытаемся чего-нибудь нарисовать. Создадим свой учебный HUD на котором и поэкспериментируем... : ) Как уже говорилось, рисовать мы должны в функции PostRender(Canvas Canvas) в качестве параметра которой передается ссылка на объект Canvas. Данная функция объявлена в классе HUD (Engine.HUD) и вызывается игроком PlayerPawn при каждой перерисовке HUD`a. Таким образом, нам необходимо создать свой класс который наследует от класса HUD (или любого другого потомка данного класса) и в нем объявить функцию PostRender, в которой и будем рисовать. Однако это еще не все, сделаем свой мод, т.к. в GameInfo есть свойство HUDType которое указывает на используемый HUD. Последовательность создания мода описана ниже, однако, Вы можете загрузить готовый проект.
В каталоге с UT создайте каталог LearnHUD, а в нем каталог Classes
Создайте файл MyGame.uc - это будет наш мод, туда "забейте" следующие строки:
class MyGame extends DeathMatchPlus;
defaultproperties
{
GameName="SUPER PUPER"
HUDType=Class'MyHUD'
}
Теперь создадим наш HUD
class MyHUD extends ChallengeHUD;
// Константа для цвета
var color LightGreen;
// Все рисование производим в этой функции
// т.к. пример НЕ для сетевой игры, поэтому
// я не ставлю модификатор simulated
function PostRender(Canvas C) {
local float XL, YL;
// Шрифт
C.Font = MyFonts.GetBigFont(C.ClipX);
// Цвет
C.DrawColor = LightGreen;
// Стиль
C.Style = ERenderStyle.STY_NORMAL;
// Центрируем текст по оси X
C.bCenter = True;
// Находим высоту текста чтобы вывести текст по центру оси Y
C.StrLen("WM",XL,YL);
// Т.к. bCenter = true, то значение первого
// параметра SetPos - любое
C.SetPos(0,(C.ClipY - YL)/2);
// Собственно рисование текста
C.DrawText("Hello world!");
}
defaultproperties
{
LightGreen=(R=64,G=255,B=127)
}
Замечания: стиль вывода и шрифт задается в HUDSetup, наш HUD полностью "глушит" наследуемый ChallengeHUD. Чтобы выводились элементы стандартного HUD`a просто добавьте строку Super.PostRender(C).
Добавьте в UnrealTournament.ini строку:
[Editor.EditorEngine]
...
EditPackages=LearnHUD
Запустите "ucc make".
Создайте LearnHUD.int, в котором должны быть следующие строчки:
Теперь собственно все. Запускайте УТ, наш мод и любуйтесь : ) Должно быть что-то типа этого:
Поэкспериментируйте... а затем пойдем дальше.
Шрифты
Как уже было сказано, свойство font представляет шрифт, которым будет выводиться текст. Вы можете задавать любой шрифт по Вашему усмотрению, например, записав что-то типа:
Однако в UnrealTournament размер HUD`a меняется в зависимости от разрешения экрана (в отличие от Unreal), поэтому лучше не указывать шрифт напрямую. В паке Botpack есть класс FontInfo в котором содержатся соответствующие функции, в классе ChallengeHUD определена переменная MyFonts типа FontInfo, так что Вам достаточно обращаться к данной переменной. Вот полный список функции, которыми Вы можете воспользоваться (в качестве параметра Width подставляется ClipX):
function font GetHugeFont (float Width)
function font GetBigFont (float Width)
function font GetMediumFont (float Width)
function font GetSmallFont (float Width)
function font GetSmallestFont (float Width)
function font GetAReallySmallFont (float Width)
function font GetACompletelyUnreadableFont (float Width)
Какого размера шрифт возвращают функции я думаю понятно. Вот пример кода:
Canvas.Font=MyFonts.GetMediumFont(Canvas.ClipX);
Масштабирование
Чтение данного раздела относится к тем, кто собирается делать свой HUD наследуя от стандартного ChallengeHUD.
Как уже было упомянуто, в UnrealTournament размер HUD`a меняется в зависимости от текущего разрешения экрана. Однако это еще не все, игрок также может регулировать размеры отдельных элементов экрана, так что при разработке своего HUD`a Вы должны учитывать это. В классе ChallengeHUD определены следующие переменные:
float HUDScale - общий масштаб каждого отдельного элемента HUD`a. Устанавливается непосредственно игроком, по умолчанию HUDScale=1.
float StatusScale - размер иконки игрока в правом верхнем углу экрана.
float WeaponScale - размер панели иконок оружия в нижней части экрана. Если непонятно, смотрите на скрины:
HUDScale=1 StatusScale=1 WeaponScale=1
HUDScale=0.5 StatusScale=1 WeaponScale=1
HUDScale=1 StatusScale=1 WeaponScale=0.5
HUDScale=1 StatusScale=0.5 WeaponScale=1
float Scale - общий масштаб, высчитывается в HUDSetup по формуле:
Scale = (HUDScale * Canvas.ClipX)/1280.0;
В общем случае, Вам достаточно иметь дело с параметром Scale, т.е. рассчитывать масштаб и позицию выводимой текстуры как: YourScaleOrLocation*Scale. И еще, перед "рисованием" не забывайте проверять переменную bHideHUD (ее назначение я думаю понятно).
Описание функции DrawTile
native(466) final function DrawTile( texture Tex, float XL, float YL, float U, float V, float UL, float VL );
Tex - рисуемая текстура.
XL - размер по горизонтали выводимого изображения (в пикселях).
YL - размер по вертикали выводимого изображения (в пикселях).
U - смещение по горизонтали (в пикселях) выводимой текстуры. Вот пример:
//
// XL = 128, UL = 128, U = 0 ("до"):
// [op]
//
// XL = 128, UL = 128, U = 64 ("после"):
// p][o
//
V - смещение по вертикали (в пикселях) выводимой текстуры. Аналогично действию параметра U но по вертикали.
UL - какую часть текстуры рисовать (по длине). К примеру, если длина текстуры 128 и UL указать равным 64, то нарисуется только половина текстуры.
VL - аналогично UL, только по высоте (вертикали).
Некоторые пояснения. XL,YL определяют область рисования вообще, промасштабировать текстуру можно при помощи UL,VL. А U,V определяют смещение в исходной текстуре при ее рисовании. Если непонятно попробуйте разобраться с этим скринами:
А еще лучше - испытайте сами, зря что ли мы учебный HUD сделали...
Будьте внимательны при указании параметра Tex. Если Вы укажете что-то типа:
(Разумеется, имея в виду, что Botpack обрабатывается UCC до Вашего пака).
Хинт
Здесь приведен пример использования Org и Clip переменных. Предположим, Вам понадобилось сделать что-то типа текстовой области, т.е. текст находится в определенных границах (вспомните транслятор в Unreal). При выводе строки UT автоматически переносит ее, если она не помещается в отведенной ей области. Примерно это выглядит так:
|long str|
|ing |
| |
То есть, при достижении строки значения ClipX движок выводит оставшуюся часть строки, начиная с позиции OrgX. Все что нам надо сделать - это поменять значения ClipX и OrgX. И... все. Только не забудьте потом восстановить первоначальные значения Clip и Org переменных.
Заключение
На этом все, основные сведения у Вас есть. Для начала разберитесь с выполнением функций рисования на учебном HUD`е, затем уже можно делать свой HUD. Если у Вас есть какие-то вопросы по материалу этой статьи, либо у Вас что-то не получается - не ленитесь спрашивать.