Делаем свой HUD
В этой статье мы рассмотрим как сделать 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 класс. Вывод из всего вышесказанного:
Если Вы еще не очень осознали, о чем идет речь - читайте дальше - будет разобран пример учебного HUD`a (глава "Рисуем!").
Замечание по сетевому HUD`у. HUD отображается на клиентской машине, поэтому Вы должны ставить слово simulated в Вашей функции PostRender, разумеется, если Ваш мод не мультиплеерный то simulated писать не надо.
Итак, теперь непосредственно рассмотрим класс Canvas и доступные в нем методы для рисования.
Основные свойства (переменные) класса Canvas
Canvas.DrawColor.r = 127; // красная составляющая цвета Canvas.DrawColor.g = 127; // зеленая составляющая Canvas.DrawColor.b = 127; // голубая составляющая |
Заметьте, что если при выводе текстур значение DrawColor не равно белому цвету (255,255,255) то все цвета текстуры претерпевают изменения.
Функции общего назначения.
SetPos(30,40) |
CurX=30; CurY=40; |
Font=Canvas.Default.Font; CurX=Canvas.Default.CurX ... |
Функции рисования.
Примечание: в данном случае текстура выводится с позиции (0,0), поэтому если, к примеру, рисовать в центре экрана, то, возможно, что левый верхний угол текстуры не совпадет с левым верхним углом области (смотрите скрин, и Вам все станет ясно)
Пример DrawPattern - рисование с центра экрана, видно, что верхние левые углы области и текстуры не совпадают:Специальные функции.
В данной статье эти функции не рассматриваются, чтобы не усложнять материал. Как только Вы разберетесь, как делать свой HUD, эти функции разберете сами без труда.
Теперь прервемся от пояснений и попытаемся чего-нибудь нарисовать. Создадим свой учебный HUD на котором и поэкспериментируем... : ) Как уже говорилось, рисовать мы должны в функции PostRender(Canvas Canvas) в качестве параметра которой передается ссылка на объект Canvas. Данная функция объявлена в классе HUD (Engine.HUD) и вызывается игроком PlayerPawn при каждой перерисовке HUD`a. Таким образом, нам необходимо создать свой класс который наследует от класса HUD (или любого другого потомка данного класса) и в нем объявить функцию PostRender, в которой и будем рисовать. Однако это еще не все, сделаем свой мод, т.к. в GameInfo есть свойство HUDType которое указывает на используемый HUD. Последовательность создания мода описана ниже, однако, Вы можете загрузить готовый проект.
class MyGame extends DeathMatchPlus; defaultproperties { GameName="SUPER PUPER" HUDType=Class'MyHUD' } |
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).
[Editor.EditorEngine] ... EditPackages=LearnHUD
[Public] Object=(Name=LearnHUD.MyGame,Class=Class,MetaClass=Botpack.TournamentGameInfo)
Поэкспериментируйте... а затем пойдем дальше.
Как уже было сказано, свойство font представляет шрифт, которым будет выводиться текст. Вы можете задавать любой шрифт по Вашему усмотрению, например, записав что-то типа:
Canvas.Font=Font(DynamicLoadObject("LadderFonts.UTLadder16", class'Font')); |
Однако в UnrealTournament размер HUD`a меняется в зависимости от разрешения экрана (в отличие от Unreal), поэтому лучше не указывать шрифт напрямую. В паке Botpack есть класс FontInfo в котором содержатся соответствующие функции, в классе ChallengeHUD определена переменная MyFonts типа FontInfo, так что Вам достаточно обращаться к данной переменной. Вот полный список функции, которыми Вы можете воспользоваться (в качестве параметра Width подставляется ClipX):
Какого размера шрифт возвращают функции я думаю понятно. Вот пример кода:
Canvas.Font=MyFonts.GetMediumFont(Canvas.ClipX); |
Чтение данного раздела относится к тем, кто собирается делать свой HUD наследуя от стандартного ChallengeHUD.
Как уже было упомянуто, в UnrealTournament размер HUD`a меняется в зависимости от текущего разрешения экрана. Однако это еще не все, игрок также может регулировать размеры отдельных элементов экрана, так что при разработке своего HUD`a Вы должны учитывать это. В классе ChallengeHUD определены следующие переменные:
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 |
Scale = (HUDScale * Canvas.ClipX)/1280.0;
В общем случае, Вам достаточно иметь дело с параметром Scale, т.е. рассчитывать масштаб и позицию выводимой текстуры как: YourScaleOrLocation*Scale. И еще, перед "рисованием" не забывайте проверять переменную bHideHUD (ее назначение я думаю понятно).
native(466) final function DrawTile( texture Tex, float XL, float YL, float U, float V, float UL, float VL ); |
// // XL = 128, UL = 128, U = 0 ("до"): // [op] // // XL = 128, UL = 128, U = 64 ("после"): // p][o //
Некоторые пояснения. XL,YL определяют область рисования вообще, промасштабировать текстуру можно при помощи UL,VL. А U,V определяют смещение в исходной текстуре при ее рисовании. Если непонятно попробуйте разобраться с этим скринами:
А еще лучше - испытайте сами, зря что ли мы учебный HUD сделали...
Будьте внимательны при указании параметра Tex. Если Вы укажете что-то типа:
Canvas.DrawTile(Texture'UTtech1.Deco.TESTred',256,64,0,0,256,64); |
...то UCC будет "ругаться" (Can`t find Texture...) т.к. текстурный пак UTtech1 не загружен при компиляции. Правильнее будет такой вариант:
Canvas.DrawTile(Texture(DynamicLoadObject("UTtech1.Deco.TESTred",class'Texture')),...); |
Данное замечание не относится к текстурам включенным в компилируемые классы (при помощи exec), к примеру, так Вы имеете полное право написать:
Canvas.DrawTile(Texture'Botpack.Icons.Use8ball',...); |
(Разумеется, имея в виду, что Botpack обрабатывается UCC до Вашего пака).
Здесь приведен пример использования Org и Clip переменных. Предположим, Вам понадобилось сделать что-то типа текстовой области, т.е. текст находится в определенных границах (вспомните транслятор в Unreal). При выводе строки UT автоматически переносит ее, если она не помещается в отведенной ей области. Примерно это выглядит так:
|long str| |ing | | |
То есть, при достижении строки значения ClipX движок выводит оставшуюся часть строки, начиная с позиции OrgX. Все что нам надо сделать - это поменять значения ClipX и OrgX. И... все. Только не забудьте потом восстановить первоначальные значения Clip и Org переменных.
На этом все, основные сведения у Вас есть. Для начала разберитесь с выполнением функций рисования на учебном HUD`е, затем уже можно делать свой HUD. Если у Вас есть какие-то вопросы по материалу этой статьи, либо у Вас что-то не получается - не ленитесь спрашивать.
Удачного Вам ХУДостроительства : ))
Автор статьи: Shadow
Mail: shadow_m777@mail.ru
Большая часть материала основана на туториале HUD Overview and Canvas functions c сайта CHiMERiC.
Автор: Eater
Mail: lsergey@home.com
Web: http://www.planetunreal.com/nalichronicles/