UDN
Search public documentation:

CLIKChatBoxCH
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 > 怎样创建一个简易的聊天框

怎样创建一个简易的聊天框


使用2011年9月的UDK进行了最后测试

概述


这一中级到高级水平的教程会包括一些在游戏运行中所需要的初级多玩家多行聊天窗口步骤,这些步骤会捕捉所有的键盘输入,并在聊天窗口处于聚焦状态下禁止游戏捕捉键盘进入。 它会提供两种方法来访问聊天输入——鼠标点击和键盘指令。

这个教程假设您已经十分熟悉对Scaleform和CLIK控件的设置和使用,并且您在一个基于HUD的Scaleform中已有一个可正常工作的鼠标指针。 该教程同样要求熟悉 replication(复制)

ALERT! 重要: 该教程同样要求熟悉 toggle-able mouse tutorial(可切换鼠标教程)

Flash设置


文本输入框

  • 将一个CLIK TexInput(CLIK文本输入)控件放到您的HUD上。 (C:\UDK\UDK-2011-09\Development\Flash\CLIK\components\TextInput.FLA )
  • 赋予它一个chatInput的实例名。
  • 打开Component Inspector(组件查看器)(CS4),或者展开Component Parameter(组件参数)(CS5)并启用"actAsButton"。

Send(发送)按钮

  • 下一步将一个CLIK Button(CLIK按钮)控件放到TextInput组件的旁边。 (C:\UDK\UDK-2011-09\Development\Flash\CLIK\components\Button.FLA)
  • 赋予它一个实例名chatSendBtn。
  • 打开Component Inspector(组件查看器)(CS4),或者展开Component Parameter(组件参数)(CS5)并在按钮的标签域里键入"Send"。

多行可滚动聊天日志

  • 将一个CLIK Text Area(CLIK文本区域)控件放到TexInput控件上方。 (C:\UDK\UDK-2011-09\Development\Flash\CLIK\components\TextArea.FLA)
  • 赋予它一个chatLog的实例名。
  • 打开Component Inspector(组件查看器)(CS4),或者展开Component Parameter(组件参数)(CS5)并禁用"editable"。
  • 将一个CLIKScroll Bar(CLIK滚动栏)控件放到TextInput控件的右边。 (C:\UDK\UDK-2011-09\Development\Flash\CLIK\components\Scrollbar.FLA )
  • 赋予它一个chatScrollBar的实例名。
  • 选中该Text Area(文本区)并打开Component Inspector(组件查看器)(CS4)或展开Component Parameter(组件参数)(CS5)并将Text Area(文本区)的scrollBar(滚动栏)设置为chatScrollBar。

聊天框形状

  • 在页面中对齐这四个控件,使它们紧挨着对方,构成一个方框。 您可以根据需要延展(不均匀缩放)这些控件。
  • 选中在页面中所有的四个控件,右击并选择Convert to Symbol(转换成标记)。
  • 将名称设置为chatForm
  • 将Type(种类)设置为Movie Clip(视频短片)
  • 启用Export for ActionScript(动作脚本输出)和Export in frame 1(在第一帧输出)。
  • 将Identifier(标识符)设置为chatForm
  • 将Class(类)设置为gfx.core.UIComponent
  • 点击OK。
  • 从页面中删除chatForm视频短片,将它保留在库中。

聊天窗口

  • 复制位于\Development\Flash\CLIK\demos\com\Scaleform\Window .as 的文件到\Development\Flash\CLIK\gfx\controls\Window.as
  • 将这个类文件打开,将第七行(类的声明行)修改成如下:

ActionScript
class gfx.controls.Window extends UIComponent {

  • 打开文件\Development\Flash\CLIK\demos\WindowDemo.FLA.
  • 进入这个文件的库面板。
  • 选中WindowSkinned标记。
  • 右击WindowSkinned标记并选择Copy(复制)。
  • 回到您的HUD.FLA文件。
  • 在页面上右击并选择Paste(粘帖)在合适的地方粘帖Window标记。
  • 将窗口对齐到页面左下角附近。
  • 赋予它一个实例名chatWindow。
  • 在页面上选中chatWindow,打开Component Inspector(组件查看器)(CS4)或展开Component Parameters(组件参数)(CS5)。
  • 将formSource设置为chatForm。
  • 请确保formType设置成标记。
  • 将maxHeight和maxWidget设置成400。
  • 将minHeight和minWidget设置成200。
  • 将offsetBottom设置成24、offsetLeft设置成20、offsetRight设置成20、offsetTop设置成46,或者您可以在测试后根据情况自行设置。
  • 将标题设置成Chat。
  • 在库面板中右击WindowSkinned标记并选中Properties(属性)。
  • 将Class(类)域设置成gfx.controls.Window并按OK。
  • 再次右击该标记并选择Component Definition(组件定义)。
  • 将Class(类)域设置成gfx.controls.Window并按OK。
  • 保存、发布并将您的SWF文件跟以往一样导入UDK。 您在页面上应该可以有一个可拖曳的聊天窗口了,它包含了聊天输入、聊天区域、发送按钮和滚动栏。

HUD类的虚幻脚本


您的HUD Class(HUD类)可以继承GFxMoviePlayer。 将这些新的变量添加到您的虚幻脚本HUD类文件:

YourHUD.uc
var WorldInfo ThisWorld;
var SFPlayerController PC;

var array<string> chatMessages; // this will hold all the chat messages
var bool bChatting;

// These are our CLIK widgets for the chat system
var GFxClikWidget MyChatInput, MyChatSendButton, MyChatLog;

将您的Start()/Init()函数修改成以下内容(添加红色的行):

YourHUD.uc
function Init(optional LocalPlayer player)
{
  super.Init(player);
  ThisWorld = GetPC().WorldInfo;

  Start();
  Advance(0);

  // ... other initialization code here ...

  // Register the HUD with the PlayerController
  PC = SFPlayerController(GetPC());
  PC.registerHUD(self);
}

修改ToggleCursor()函数(从先前的鼠标教程中)。

YourHUD.uc
/** Toggles mouse cursor on/off */
function ToggleCursor(bool showCursor, float mx, float my)
{
  if (showCursor)
  {
    MouseContainer = CreateMouseCursor();
    MouseCursor = MouseContainer.GetObject("my_cursor");
    MouseCursor.SetPosition(mx,my);
    MouseContainer.SetBool("topmostLevel", true);
  }
  else
  {
    MouseContainer.Invoke("removeMovieClip", args);
    MouseContainer = none;
  }

  if (!bChatting)
  {
    bCaptureInput = showCursor;
    bIgnoreMouseInput = !showCursor;
  }
  else
  {
    bCaptureInput = true;
    bIgnoreMouseInput = false;
  }
}

现在修改您HUD的WidgetInitialized()函数并在聊天文本域上和聊天发送按钮上设置针对鼠标点击的事件监听器。

YourHUD.uc
event bool WidgetInitialized(name WidgetName, name WidgetPath, GFxObject Widget)
{
  switch(WidgetName)
  {
  case ('chatInput'):
    MyChatInput = GFxClikWidget(Widget);
    MyChatInput.AddEventListener('CLIK_press', OnChat);
    break;

  case ('chatSendBtn'):
    MyChatSendButton = GFxClikWidget(Widget);
    MyWidget.AddEventListener('CLIK_press', OnClickHandler);
    break;

  case ('chatLog'):
    MyChatLog = GFxClikWidget(Widget);
    break;

  default:
    break;
  }

  return true;
}

添加OnChat()事件处理器。

YourHUD.uc
// Event Handler - handles when the player clicks on the chat box text input field.
function OnChat(GFxClikWidget.EventData ev)
{
  bChatting = true;
}

添加OnChatSend()函数。 该函数在按下Send(发送)时发布信息,并返回对游戏的控制。

YourHUD.uc
function OnChatSend(GFxClikWidget.EventData ev)
{
  local string Msg;

  Msg = MyChatInput.GetString("text");

  if (Msg != "")
  {
    PC.SendTextToServer(PC, Msg);
  }

  MyChatInput.SetString("text", "");
  self.bCaptureInput = false;
  bChatting = false;
}

现在针对更新这个聊天区域的函数,显示到目前为止从Broadcast()函数收到的每条信息

YourHUD.uc
function UpdateChatLog(string message)
{
  local string displayMsg;
  local int i;

  chatMessages.AddItem(message);

  displayMsg = "";

  for (i = 0; i < chatMessages.length; i++)
  {
    displayMsg @= chatMessages[i];
    displayMsg @= "\n";
  }

  MyChatLog.SetString("text", displayMsg);
  MyChatLog.SetFloat("position", MyChatLog.GetFloat("maxscroll"));
}

在您的默认属性中添加控件绑定和其他重要的变量:

YourHUD.uc
defaultproperties
{
    WidgetBindings.Add((WidgetName="chatInput",WidgetClass=class'GFxClikWidget'))
    WidgetBindings.Add((WidgetName="chatSendBtn",WidgetClass=class'GFxClikWidget'))
    WidgetBindings.Add((WidgetName="chatLog",WidgetClass=class'GFxClikWidget'))

    bIgnoreMouseInput = true;
    bCaptureInput = false;
}

GameInfo类的设置


打开您的GameInfo类。

如果它不扩展UTGame或UTGame的子项,比如UTDeathmatch,就只将这些变量添加到您的game info类。 如果已经声明了这些变量,您将会收到编译警告。 如果收到了警告,请将它们从您的game info类中移除。

YourGameInfo.uc
var class<BroadcastHandler> BroadcastHandlerClass;
var BroadcastHandler BroadcastHandler;   // handles message (text and localized) broadcasts

接下来,将这些内容添加到您GameInfo类中的InitGame()函数:

YourGameInfo.uc
event InitGame( string Options, out string ErrorMessage )
{
    Super.InitGame(Options, ErrorMessage);
    BroadcastHandler = spawn(BroadcastHandlerClass);
}

在我们的GameInfo类中,我们会从\Development\Src\Engine\Classes\GameInfo.uc覆盖Broadcast事件。

YourGameInfo.uc
event Broadcast(Actor Sender, coerce string Msg, optional name Type)
{
  local SFPlayerController PC;
  local PlayerReplicationInfo PRI;

  // This code gets the PlayerReplicationInfo of the sender. 我们会使用它得到带有PRI.PlayerName的发送者的名字。
  if (Pawn(Sender) != None)
  {
    PRI = Pawn(Sender).PlayerReplicationInfo;
  }
  else if (Controller(Sender) != None)
  {
    PRI = Controller(Sender).PlayerReplicationInfo;
  }

  // This line executes a "Say"
  BroadcastHandler.Broadcast(Sender, Msg, Type);

  // This is where we broadcast the received message to all players (PlayerControllers)
  if (WorldInfo != None)
  {
    ForEach WorldInfo.AllControllers(class'SFPlayerController',PC)
    {
      `Log(Self$":: Sending "$PC$" a broadcast message from "$PRI.PlayerName$" which is '"$Msg$"'.");
      PC.ReceiveBroadcast(PRI.PlayerName, Msg);
    }
  }
}

最后,将这些内容添加到您的GameInfo类中的默认属性,请确定您已经通过您的类名称对它们进行修改。

YourGameInfo.uc
defaultproperties
{
  PlayerControllerClass=class'SFPlayerController'
  BroadcastHandlerClass=class'Engine.BroadcastHandler'
  HUDType=class'SFTutorial.SFHudWrapper'
  bUseClassicHUD=true
}

PlayerController(玩家控制器)类设置


新建/打开PlayerController类(在这个示例中: 为SFPlayerController):

SFPlayerController.uc
class SFPlayerController extends UTPlayerController;

首先我们会创建一个在PlayerController(玩家控制器)中注册HUD的函数,这样我们就能轻易地从PlayerController(玩家控制器)将函数调用HUD中的函数。

SFPlayerController.uc
var SFHud MySFHud;

function registerHUD(SFHud hud)
{
  MySFHud = hud;
}

以下的函数是用来把信息发送到服务器的:

SFPlayerController.uc
exec function SendTextToServer(SFPlayerController PC, String TextToSend)
{
  `Log(Self$":: Client wants to send '"$TextToSend$"' to the server.");
  ServerReceiveText(PC, TextToSend);
}

这个函数用来收取一个服务器信息然后将其发布:

SFPlayerController.uc
reliable server function ServerReceiveText(SFPlayerController PC, String ReceivedText)
{
  WorldInfo.Game.Broadcast(PC, ReceivedText, 'Say');
}

最后,我们需要新建一个监听来自服务端所发布内容的客户端函数,这些广播信息发布到聊天窗口。

SFPlayerController.uc
reliable client function ReceiveBroadcast(String PlayerName, String ReceivedText)
{
    `Log(Self$":: The Server sent me '"$ReceivedText$"' from "$PlayerName$".");
    MySFHud.UpdateChatLog(PlayerName @ ": " @ ReceivedText);
}

通过键盘命令启用Chatting(聊天功能)(按下Enter回车键)

对这一步骤来说,我们会使用Enter(回车键)开启对话并发送(完成)聊天信息。 您也可以使用您喜欢的按键。

添加按键绑定

打开DefaultInput.ini并添加以下代码:

.Bindings=(Name="Enter",Command="ChatHandler")

ALERT! 注意: 您需要注释掉或删除以下代码行,以便按下的按键可以在聊天时正常工作。

.Bindings=(Name="Enter",Command="GBA_Use")

HUDWrapper类设置

打开您的HUDWrapper(HUD封装)。 这就是实例化该HUD的类。 添加这个在按下键时将被执行的函数:

YourHUDWrapper.uc
exec function ChatHandler()
{
  HudMovie.ToggleChat(); // Replace HudMovie with the reference name of your HUD movie.
}

HUD类设置

打开您的HUD类。

首先我们必须要确保所选的键永远不会被我们的HUD短片捕捉为输入。 我们通过将它添加到聚焦忽略键位列表的方法达到目的。 将这些代码添加到您的Start()/Init()函数中。

AddFocusIgnoreKey('Enter');

然后,加入一个通过键盘命令启用聊天的函数。 HUDWrapper(HUD封装)调用这个函数:

function ToggleChat()
{
  if (!bChatting)
  {
    bCaptureInput = true;
    OnChat();
  }
  else
  {
    bCaptureInput = false;
    OnChatSend();
  }
}

然后修改OnChat()和OnChatSend()函数的参数,使它们可选:

function OnChat(optional GFxClikWidget.EventData ev)
function OnChatSend(optional GFxClikWidget.EventData ev)

现在通过添加以下代码修改OnChat()函数:

MyChatInput.SetBool("focused", true);

最后,使用以下代码对OnChatSend()函数进行修改:

MyChatLog.SetBool("focused", true);

重新编译脚本并测试您的HUD。

下载