Monday, April 29, 2013

Делаем hud health status в udk

   Расскажу, как можно заменить стандартную иконку с жизнями на свою собственную, с помощью flash и с минимумом знаний обо всем этом. Основой служили вот эти уроки и скрипты (они также рекомендованы к просмотру),  к слову все дальнейшие манипуляции я делаю в September(2010) версии.


    Первым делом нам следует заготовить swf файл. (на примере работы с adobe flash cs). Создаем проект как Action Script 2.0(в новых версиях udk уже имеется поддержка as3.0), выставляем разрешение 1024x768(не обязательно такое).




Нюансы:
1)  В настройках импортируемых картинок нужно обязательно убирать расширение. Не выполнение этого условия приведет к аварийному завершению UDK. Также ставим галочки как на скриншоте.(Наводим на загруженную текстуру в библиотеке проекта > правой кнопкой мыши > свойства)




2)  Текущее значение жизни будем передавать как параметр типа string, назначаем ему соответствующее имя экземпляра, дабы потом правильно к нему обращаться через uscript.
Создаем textField, пишем там 100, еще создаем textField- пишем %.
Объект textField, где написано 100, присваиваем имя player_health. Оно нам пригодится (используется при обращении в скриптах).



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





    Для примера добавлен простой фон под 100%, дизайн же вывода текущих жизней ограничивается лишь вашей фантазией, все на ваше усмотрение, а в данном случае осталось только вставить немного кода в новом слое.
Итак выделяем новый слой, жмем F9 и вставляем такой код:

import gfx.motion.Tween;
_global.gfxExtensions = true;

    Первая строка добавляет библиотеку Tween(не думаю что это здесь обязательно, по крайней мере, пример очень простой и эту библиотеку вряд ли использует. Библиотека добавляет возможность анимации муверов, с контролем из uscript), вторая строка разрешает вести диалог между action script и unreal script, при помощи чего и будут передаваться параметр, вызываться функции. За хорошим примером, чего можно добиться этой связкой, далеко идти не надо - тоже меню в udk как раз эффективно показывает возможности взаимодействия scaleform и unreal script.

    После того, как опубликовали и создали все нужные файлы, загружаем их в UDK. Создадим простой тип игры для примера.

Прописываем в своем Test_InfoGame собственный контроллер и hud. Остальные настройки по умолчанию.
class Test_InfoGame extends  UTDeathmatch; 

DefaultProperties
{
    //Indentify your GameInfo
    Acronym="ST"

    PlayerControllerClass=class'FlashHealthGame.Test_PlayerController'
    HUDType=class'FlashHealthGame.THUD'
    //DefaultPawnClass=class'UTGame.UTPawn'
 
    //This variable was created by Epic Games to allow back compatability with UIScenes
    bUseClassicHUD=true

    bDelayedStart=false
    bRestartLevel=false
    Name="Test_GameInfo"
}

Просто балванка контроллера.
class Test_PlayerController extends UTPlayerController;

DefaultProperties
{
    bForceBehindView=false
    Name="Test_PlayerController"
}


    Этот класс отвечает за отработку hud элементов. В конкретном случае, просто рождаем класс, который ответственен за работу scaleform компонента.
class THUD extends UTHUDBase;

//Reference the actual SWF container (STGFxHUD created later)
var STGFXHUD HudMovie;

//Called when this is destroyed
singular event Destroyed()
{
    if (HudMovie != none) 
    {
        //Get rid of the memory usage of HudMovie
        HudMovie.Close(true);
        HudMovie = none;
    }

    super.Destroy();
}

//Called after game loaded - initialise things
simulated function PostBeginPlay() 
{
    super.PostBeginPlay();

    //Create a STGFxHUD for HudMovie
    HudMovie = new class'STGFXHUD';
 
    //Set the timing mode to TM_Real - otherwide things get paused in menus
    HudMovie.SetTimingMode(TM_Real);
 
    //Call HudMovie's Initialise function
    HudMovie.Init(class'Engine'.static.GetEngine().GamePlayers[HudMovie.LocalPlayerOwnerIndex]);
}

//Called every tick the HUD should be updated
event PostRender() {
    HudMovie.TickHUD();
}

DefaultProperties
{
}

Отвечает за общение с флешкой и передачи параметров.
class STGFXHUD extends GFxMoviePlayer;

//Create a Health Cache variable
var float LastHealthpc;

//Create variables to hold references to the Flash MovieClips and Text Fields that will be modified
var GFxObject HealthTF;


function Init(optional LocalPlayer player) 
{
    //Start and load the SWF Movie
    Start();
    Advance(0.f);

    //Set the cahce value so that it will get updated on the first Tick
    LastHealthpc = -1337;

    //Load the references with pointers to the movieClips and text fields in the .swf
    HealthTF = GetVariableObject("_root.player_health");
}

//Called every update Tick
function TickHUD()
{
    local UTPawn UTP;
    local PlayerController PC;
 
    PC = GetPC();
    //We need to talk to the Pawn, so create a reference and check the Pawn exists
    UTP = UTPawn(PC.Pawn);
 
    //If the cached value for Health percentage isn't equal to the current...
    if (LastHealthpc != UTP.Health)
    {
        // update the text field
        HealthTF.SetText(UTP.Health);
        //...Make it so...
        LastHealthpc = UTP.Health;
    }
    else if (LastHealthpc <= 0)
    {
        HealthTF.SetText(0);
        close();
    }
}


DefaultProperties
{
    //this is the HUD. If the HUD is off, then this should be off
    bDisplayWithHudOff=false
    //Местонахождение флешки
    MovieInfo=SwfMovie'Test_flash.Test.Test_flash'
}

    Не забудьте правильно прописать путь к флешке в DefaultProperties, которую загрузили в UDK. Создаем, компилируем, запускаем UDK, загружаем тестовый уровень, ставим нужный тип игры в настройках, радуемся.






 Исходники

Cсылки по теме:
http://noexp.wordpress.com/scaleform-hud-tutorial/
http://forecourse.com/unreal-tutorials/
http://www.youtube.com/user/scaleformpress#p/u/16/_nsOOSBBbdg

7 comments:

  1. А как можно получить ссылку на переменную из другого класса и изменить ее?

    ReplyDelete
    Replies
    1. Чтобы добраться до переменной из другого(не старшего) класса, необходимо получить ссылку на экземпляр этого класса.
      В функции TickHUD() класса STGFXHUD есть пример, как можно это сделать:
      local UTPawn UTP;
      local PlayerController PC;

      PC = GetPC(); /* получили ссылку на экземпляр класса PlayerController
      GetPC() - спец. функция из GFxMoviePlayer, теперь можно изменять все доступные переменные в PC находясь в экземпляре класса STGFXHUD. */
      UTP = UTPawn(PC.Pawn); /* получили ссылку на экземпляр класса UTPawn
      можем изменить параметр MaxHealth(и любой другой доступный) у этого экземпляра:*/
      UTP.MaxHealth = 100500;

      Delete
    2. просто я хочу сделать не отображение здоровья а переменной с другого класса типа int и мне как то надо получить ее значение пробивал через ForEach AllACtors(class'MyInventory',inv)
      {
      inv.wood+=100;
      //Ну я дальше хотя б через лог
      worldinfo,Game,braodcast(self,inv.wood);
      }
      и в итоге мне выдавало не 100 а 0 (Ну а вообще делал для вывода на худ но думал там что-то не правильно и сделал и выводом лога пока-что)

      Delete
    3. У класса Pawn есть переменная InvManager (ссылка на InventoryManager). Т.е. если был указан собственный инвентарь в defaultproperties, то можно изменить параметр так(находясь в Pawn классе):

      MyInventoryManager(InvManager).wood +=100;

      где MyInventoryManager - собственный класс инвентаря, в котором объявлена переменная wood.

      Суть проблемы и ситуация не очень ясны, поэтому что-то посоветовать определенно верное, особо шансов нет. Нужна конкретика :)

      Delete
    4. а вы немогли бы обьяснить , как путь к бару здоровья делать)

      Delete
    5. Непонятен вопрос, лучше сформулируйте более точно.

      Если имеется ввиду создание шкалы/полоски здоровья, то в флешку из us можно передавать некий параметр scaleX, который будет влиять на scale полоски-movieclip.(могу расписать подробнее если требуется)

      Delete
  2. An impressive share! I've just forwarded this onto a colleague who has been conducting a little research on this. And he in fact bought me lunch due to the fact that I discovered it for him... lol. So allow me to reword this.... Thanks for the meal!! But yeah, thanks for spending the time to discuss this topic here on your blog. aol.com email sign in

    ReplyDelete