UDN
Search public documentation:

GFxVolumeStatusBarCH
English Translation
日本語訳
한국어

Interested in the Unreal Engine?
Visit the Unreal Technology site.

Looking for jobs and company info?
Check out the Epic games site.

Questions about support via UDN?
Contact the UDN Staff

UE3 主页 > 用户界面 & HUD > Scaleform GFx > 如何添加带有状态栏的控制体积

如何添加带有状态栏的控制体积


概述


该教程包括了添加一个基础的带有工作状态栏的控制体积的方法。 针对该教程有三个版本。 在您可以选择添加版本2或版本3之前,必须已经完成版本1.

  • 状态栏会在屏幕上,位于HUD中央。
  • 该状态栏显示为在控制体积中央的浮动栏。 它本身实际位于游戏世界中并总是面向玩家。
  • 该栏会再次在HUD上出现,这次使用Canvas.Project使它出现在控制体积的相对位置处;玩家移动,该状态栏也围绕HUD移动,它总是位于控制体积的相关位置。

没有提供另一个玩家或团队占领一个已经被占领的体积的代码,也没有提供针对多个玩家联合占领的代码。 您必须自己做出这个效果。

当完成时,您就可以将一个体积添加到编辑器中的关卡了,菜单路径如下: Brush->Add Volume->SFControlVolume

Flash设置


  • 创建一个新的AS.2文档
  • 将该文档尺寸设置成512x256
  • ALERT! 重点: :将该文档的背景设成黑色。
  • 在文档的中央创建一个蓝色的矩形。
  • 将它转换成视Movie Clip(视频剪辑)。
  • 赋予它一个实例名BlueStatusBar。
  • 将SWF保存并发布到位于/UDKGame/Flash/UDKSFTutorial/CVStatusBar.SWF的UDK安装路径下。
  • 将SWF导入UDK。

Scaleform_Tutorial_01.jpg

状态栏在HUD上居中


创建一个您可以在地图中随处放置的可放置控制体积。

SFControlVolume.uc
  class SFControlVolume extends Volume
    placeable;
  
  var bool bControlled;
  var int ElapsedTime;
  var int PercentCaptured;
  
  // Editable Properties
  var(TimeToControl) int TimeToControl;
  var(TimeToControl) float UpdateRate;
  var() SwfMovie Movie;
  
  var Info ControlTimer;
  var SFControlVolumeMovie CVMovie;
  
  event PostBeginPlay()
  {
    Super.PostBeginPlay();
    ControlTimer = Spawn(class'SFVolumeControlTimer', self);
  }
  
  event Touch(Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal)
  {
    Super.Touch(Other,OtherComp,HitLocation,HitNormal);
  
    if(!bControlled)
    {
      // Turn on the timer, and have it tick every X seconds, where X = UpdateRate.
      ControlTimer.SetTimer(UpdateRate,true);
    }
  
    // Only display the status bar when the player has touched/is in the volume.
    CreateControlVolumeMovie();
    UpdateStatusBar();
  }
  
  event UnTouch(Actor Other)
  {
    Super.UnTouch(Other);
  
    // Reset capture timer.
    ControlTimer.ClearTimer();
  
    // Close the status bar when the player leaves the volume.
    CVMovie.Close(true);
    CVMovie = none;
  
    if(!bControlled)
    {
      ElapsedTime = 0;
    }
  }
  
  function StartControlling(SFVolumeControlTimer VC)
  {
    local int PercentCaptured;
  
    if (VC == ControlTimer)
    {
      ElapsedTime++;
      `log("Time to capture: " @ TimeToControl - ElapsedTime);
  
      UpdateStatusBar();
  
      // Once we reach the total time to control, capture the volume and clear the timer.
      if(ElapsedTime >= TimeToControl)
      {
        `log("Captured!");
        bControlled = true;
        ControlTimer.ClearTimer();
      }
    }
  }
  
  function UpdateStatusBar()
  {
    PercentCaptured = (100 * float(ElapsedTime)) / float(TimeToControl);
    CVMovie.UpdateStatusBar(self, PercentCaptured);
  }
  
  function CreateControlVolumeMovie()
  {
    CVMovie = new class'SFControlVolumeMovie';
    CVMovie.MovieInfo = Movie;
    CVMovie.SetTimingMode(TM_Real);
    CVMovie.Start();
  }
  
  defaultproperties
  {
    TimeToControl=100
    UpdateRate=0.1
  }
  

现在创建计时器类。 这个类只在每次更新时执行SFControlVolume::StartControlling()函数。

SFVolumeControlTimer.uc
  class SFVolumeControlTimer extends Info;
  
  var SFControlVolume CV;
  
  event PostBeginPlay()
  {
    Super.PostBeginPlay();
    CV = SFControlVolume(Owner);
  }
  
  event Timer()
  {
    CV.StartControlling(self);
  }
  
  defaultproperties
  {
    TickGroup=TG_PreAsyncWork
    bStatic=false
    RemoteRole=ROLE_None
  }
  

最后,为状态栏创建Movie Player(视频剪辑)类。

SFControlVolumeMovie.uc
  class SFControlVolumeMovie extends GFxMoviePlayer;
  
  var GFxObject StatusBarMC;
  
  function bool Start(optional bool StartPaused = false)
  {
    Super.Start();
    Advance(0);
  
    StatusBarMC = GetVariableObject("_root.BlueStatusBar");
  
    return true;
  }
  
  function UpdateStatusBar(SFControlVolume CV, int PercentCaptured)
  {
    local GFxObject.ASDisplayInfo DI;
  
    DI.hasXScale = true;
    DI.hasAlpha = true;
  
    DI.XScale = PercentCaptured;
    DI.Alpha = 100;
  
    if (DI.XScale >= 100)
    {
      DI.XScale = 101;
    }
    else if (DI.XScale == 0)
    {
      DI.XScale = 1;
      DI.Alpha = 0;
    }
  
    StatusBarMC.SetDisplayInfo(DI);
  }
  
  defaultproperties
  {
      bDisplayWithHudOff = false
  }
  

  • 现在使用一个BSP构建画刷为您的关卡创建控制体积。
  • 进入体积的属性(按下F4)。
  • 设置Time To Control(控制时间)。 (捕捉的最大更新数)
  • 设置Update Rate(更新速率) (您希望状态栏几秒更新一次;值越低意味着更新越快 )
  • 将Movie(短片)域设置为您先前导入的SWF。
  • 保存关卡并测试!

在游戏世界中浮动的状态栏


真正地出现在游戏世界中,并位于体积的中央,,首先要修改SFControlVolume类。

ALERT! 注意: 您可以在您的关卡中添加多个控制体积,但您必须为每个体积创建唯一的Material(材质)和TextureRenderTarget2D。

针对SFControlVolume的修改:

SFControlVolume.uc
  // Add these global vars to the top of the class
  var() StaticMesh Mesh;
  var() vector TranslationOffset;
  var() array<MaterialInterface> Materials;
  var() TextureRenderTarget2D RenderTexture;
  var SFControlVolumeMesh CVMesh;
  
  // Add this code to the event Touch() function, just after Super.Touch();
  CVMesh = Spawn(class'SFControlVolumeMesh');
  CVMesh.Mesh.SetStaticMesh(Mesh);
  CVMesh.Mesh.SetMaterial(0,Materials[0]);
  CVMesh.SetLocation(self.Location + TranslationOffset);
  CVMesh.PC = Other;
  
  // Add this line of code to the event UnTouch() function
  CVMesh.Destroy();
  
  // Add this line of code to the CreateControlVolumeMovie() function, after CVMovie.MovieInfo = Movie;
  CVMovie.RenderTexture = RenderTexture;
  

现在创建一个新的类。 这个类在游戏世界中将会用来显示状态栏。

SFControlVolumeMesh.uc
  class SFControlVolumeMesh extends StaticMeshActor
    placeable;
  
  var vector PlayerLoc;
  var actor PC;
  
  var() editinline const StaticMeshComponent Mesh;
  
  function Tick(float fDeltaTime)
  {
    Super.Tick(fDeltaTime);
  
    // Always face the player
    PlayerLoc = PC.Location;
    SetRotation(Rotator(PlayerLoc - self.Location));
  }
  
  defaultproperties
  {
    bStatic = false
    bMovable = true
  
    Begin Object class=StaticMeshComponent Name=StaticMeshComp1
      CollideActors = False
      BlockActors = false
      BlockRigidBody = False
    End Object
    Mesh = StaticMeshComp1
    Components.Add(StaticMeshComp1)
  }
  

  • 现在使用一个BSP构建画刷为您的关卡创建控制体积。
  • 进入体积的属性(按下F4)。
  • 设置Time To Control(控制时间)。 (捕捉的最大更新数)
  • 设置Update Rate(更新速率) (您希望状态栏几秒更新一次;数字越小,更新越快)
  • 将Movie(短片)域设置为您先前导入的SWF。
  • 打开内容浏览器
  • 创建一个新的TextureRenderTarget2D,根据您的喜好命名,然后将它的分辨率设置为512x256同SWF匹配。
  • 创建一个新的材质,根据您的喜好命名。
  • 在材质中,添加一个新的TextureSample(示例贴图)。
  • 在新的TextureSample的贴图域中插入您创建的TextureRenderTarget2D
  • 将TextureSample(示例贴图)的Diffuse(漫反射)输出口连接到Material(材质)的Diffuse(漫反射)输入口。
  • 将Material(材质)的Blend Mode(混合模式)设置为BLEND_AlphaComposite。
  • Add Color->New Desaturation.
  • Add Parameters->New ScalarParameter.
  • 将Parameter(参数)的Default Value(默认值)设置为-20。
  • 将TextureSample(贴图示例)的Diffuse(漫反射)输出口(黑色方块)连接到Desaturation的A。
  • 将参数"None"连接到Desaturation上的B。
  • 将Desaturation的输出口连接到材质的Opacity和Emissive端
  • 关闭材质窗口并保存修改。
  • 将您的包同您新建的材质和渲染贴图一起保存。
    Scaleform_Tutorial_02.jpg
  • 进入体积的属性(按下F4)。
  • 将Mesh(网格物体)域设置为平面网格物体,比如在以下内容中找: dwStaticMeshes.Plane
  • 设置Translation Offset(平移偏移) (这将相对于控制体积的中心移动状态栏)
  • 添加一个新的材质槽。
  • 将您创建的新的材质分配为材质槽0。
  • 将您所创建的TextureRenderTarget2D分别配到RenderTexture(渲染贴图)域。
  • 保存关卡并测试!

HUD上处于相对位置的状态栏


用Canvas Project将状态栏以相对体积的位置将其描画在HUD上 您可以环视一下,这个状态栏会在HUD上移动,所以它还是在同一个相对位置。

ALERT! 注意: 如果您已经对您的代码作过修改,取消这些修改。

您必须修正您HUD封装的PostRender()函数。

YourHUD.uc
  event PostRender()
  {
    local SFControlVolume SFCV;
  
    super.PostRender();
  
    // Find all control volumes in the level
    foreach WorldInfo.AllActors(class'SFControlVolume',SFCV)
    {
      //Project 3D world position of control volume to 2D screen position
      if (SFCV.CVMovie != none)
      {
        SFCV.CVMovie.UpdatePosition(Canvas.Project(SFCV.Location));
      }
    }
  
    // Tick HUD
    if (HudMovie != none)
    {
      HudMovie.TickHud(0);
    }
  }
  

SFControlVolumeMovie.uc Modifications: 首先,添加两个新的全局变量:

SFControlVolumeMovie.uc
  var int Width, Height;
  

然后将以下三行代码添加到Start()函数:

SFControlVolumeMovie.uc
  function bool Start(optional bool StartPaused = false)
  {
      local float x0, y0, x1, y1;
  
      super.Start();
      Advance(0.0);
  
      StatusBarMC = GetVariableObject("_root.BlueStatusBar");
  
      GetVisibleFrameRect(x0, y0, x1, y1);
      Width = x1-x0;
      Height = y1-y0;
  
      return true;
  }
  

然后在UpdateStatusBar()函数后添加这个函数。

SFControlVolumeMovie.uc
  function UpdatePosition(Vector ScreenPos)
  {
      self.SetViewPort(ScreenPos.X,ScreenPos.Y,Width,Height);
  }
  

Scaleform_Tutorial_03.jpg