UIWidget

トップに戻る

UIの使い方

HaxeFlixelが用意しているUIWidgetの使い方を紹介しています。



シンプルなUI

シンプルなUI(flixel.ui)として、ボタン(FlxButton)とバー(FlxBar)、アナログパッド(FlxAnalog?)とバーチャルパッド(FlxVirtualPad)が用意されています

ボタン(FlxButton)

/// PlayState.hx
class PlayState extends FlxState {

  override public function create():Void {
    var px = 80; // X座標は80
    var py = 160; // Y座標は160
    var button = new FlxButton(px, py, "CLICK", _cbBtn); // "CLICK"というラベルのボタンを生成
    add(button); // 登録
  }

  // ボタンをクリックした時のコールバック関数
  private function _cbBtn():Void {
    trace("click button.");
  }

バー(FlxBar)

体力ゲージなどに使えるバーです

/// PlayState.hx
class PlayState extends FlxState {

  private var _bar:FlxBar;

  override public function create():Void {
    var px = 80; // X座標は80
    var py = 160; // Y座標は160
    _bar = new FlxBar(px, py); // ゲージを生成
    add(_bar); // 登録
  }

  public function doSomething():Void {
    _bar.currentValue = val; // ゲージの値を0〜100で設定
  }

FlxBar.currentValueに0〜100の値を設定するとそれに合わせてゲージが増減します。 なおFlxBarのインスタンス生成後に、createFilledBar?を呼び出すとゲージの色やアウトラインを指定できます。

001.png
  _hpBar = new FlxBar(HPBAR_X, HPBAR_Y, FlxBar.FILL_LEFT_TO_RIGHT, BAR_W, BAR_H);
  // ゲージの色を変更
  _hpBar.createFilledBar(FlxColor.CRIMSON, FlxColor.CHARTREUSE);
  this.add(_hpBar);

アナログパッド(FlxAnalog?)

TODO

バーチャルパッド(FlxVirtualPad)

基本的な使い方を以下のページにまとめています。


拡張UI(UIWidget)

拡張UIを使うとより複雑なUIを作ることができます

Project.xmlの修正

拡張UIを使うにはProject.xmlにライブラリの指定が必要です

  <!-- 拡張UIを有効にする -->
  <haxelib name="flixel-ui" />

もし flixel-ui ライブラリをインストールしていなかったら以下のコマンドでインストールします

haxelib install flixel-ui

FlxUIState

UIをFlxStateで管理するクラスです。このクラスを実装すると、レイアウトデータを読み込んでUIを配置したり、UIのイベントをコールバックで取得することができるようになります。

最低限のレイアウトデータ

FlxUIStateで読み込む最低限のXMLは以下のように定義します

<?xml version="1.0" encoding="utf-8" ?>
<data>
</data>

dataタグの下に各種UIを定義します。なお配置場所は"assets/xml"のフォルダ内でなければなりません。

レイアウトデータの読み込み方法

/// MenuState.hx
class MenuState extends FlxUIState {

    override public function create():Void {
        _xml_id = "menu"; // "assets/xml/menu.xml"を読み込む
        super.create(); // 読み込み実行

読み込むには、FlxUIStateのフィールド「_xml_id」にファイル名を文字列で指定します。その後、super.create() を呼び出すことで読み込みが実行されます。

コールバック関数

UIWidgetのコールバックを受け取るには、FlxUIState.getEvent() をオーバーライドします。

/// MenuState.hx
class MenuState extends FlxUIState {

    // UIWidgetのコールバック受け取り
    public override function getEvent(id:String, sender:Dynamic, data:Dynamic, ?params:Array<Dynamic>):Void {

        var widget:IFlxUIWidget = cast sender;
        if(widget != null && Std.is(widget, FlxUIButton)) {

            var fuib:FlxUIButton = cast widget;
            // ボタンパラメータを判定
            if(fuib.params != null && fuib.params[0] == "btn001") {

                switch(id) {
                    case FlxUITypedButton.CLICK_EVENT:
                        // クリックされた
                        trace("click!");
                }
            }
        }
    }

レイアウト配置のXMLは以下のようになります。

<?xml version="1.0" encoding="utf-8" ?>
<data>
    <!-- ボタンを(x,y,width,height)=(64,8,200,100) ラベル名を"CLICK ME"で配置 -->
    <button id="btn001" label="CLICK ME" x="64" y="8" width="200" height="100">
         <param type="string" value="btn001" /> <!-- ボタン識別用のパラメータを定義 -->
    </button>
</data>

FlxUI

FlxUIは生成した拡張UIのインスタンスを管理しています。 FlxUIFlxUIStateのフィールド変数「_ui」でアクセスできます

class MenuState extends FlxUIState {

  // ...

  override public function update(elapsed:Float):Void {
    // FlxUIからUIグループ"mcguffin"を取得する
    var group:FlxUIGroup = _ui.getGroup("mcguffin");
  }
}

タグ・パラメータ説明

タグ説明

タグ名概要詳細
definitionパラメータ定義定義したパラメータは外部から再利用できる
mode表示モード定義表示・非表示のモードを定義できる
image画像FlxUISprite
9slicesprite / chrome9スライス / クロームFlxUI9SliceSprite
buttonボタンFlxUIButton
button_toggleトグルボタンFlxUIButton
checkboxチェックボックスFlxUICheckBox?
textテキストFlxUIText
input_text入力テキストFlxUIInputText?
radio_groupラジオボタンFlxUIRadioGroup
tab_menuタブFlxUITabMenu?
lineFlxUISprite
numeric_stepperFlxUINumericStepper?
dropdown_menuFlxUIDropDownMenu?
tile_testFlxUITileTest?

タグ説明(子要素)

タグ名概要親要素詳細
textテキストbutton
colortext / buttonidに条件を指定。valueに色の値を 0xAARRGGBB / 0xRRGGBB で指定
graphic画像リソースbuttonnameに条件、imageにリソースパスを指定

パラメータ説明

パラメータ概要詳細
id識別ID定義IDやオブジェクトIDを指定して、外部から参照することができる
fontフォント名適用するフォント名を指定する(拡張子は省略する)。読み込むフォントは"assets/fonts/"に配置すること
sizeフォントサイズ
styleフォントスタイルbold(太字) / italic(斜体)
colorフォントの色0xAARRGGBB or 0xRRGGBB で指定する
outlineフォントのアウトラインの色0xAARRGGBB or 0xRRGGBBで指定する
alignフォントのアラインメントleft(左揃え) / center(中央揃え) / right(右揃え)
srcデータリソースのパス(拡張子は省略する)データは"assets/gfx/"に配置する
image画像リソースのパス(拡張子は省略する)データは"assets/gfx/"に配置する
use_defdefinitionタグの値を参照する
groupグループ名グループはgroupタグで囲うのではなく各タグにつけなければならない
slice99スライスのパラメータカンマ区切りで指定

■注意点

  • id 及び group は大文字小文字を区別しない(実行時に小文字に置き換えられる)
    • そのため小文字のスネークケースで記述したほうが良い("Blue Button"ではなく、"blue_button"にする)
  • 所属するグループがある場合、"group"要素を各タグにつけなければならない
    • groupタグで囲う、という定義のしかたはできない
  • 9スライスのパラメータについて
    • パラメータはカンマ区切りで指定("x1,y1,x2,y2")
    • 例えば、"3,3,12,12"を指定すると以下のような境界線で分割を行う
      9Slice003.png
    • 9スライスの仕組みについては、「9スライスの仕組み」で説明しています

レイアウトの例

FlxUISprite (画像)

  <sprite src="ui/food" x="0" y="0"/>
  • 画像データを"assets/gfx/ui/food.png" に配置
  • (x, y) = (0, 0) に配置

FlxUI9SliceSprite (9スライスを使ったHPゲージ)

あらかじめ、HPゲージ用の画像 health_bar.png を "assets/gfx/ui/misc/health_bar.png" に配置しておきます

<?xml version="1.0" encoding="utf-8" ?>
<data>
  <!-- HPゲージ用 9スライスの定義。assets/gfx/ui/misc/health_bar.png を使う -->
  <definition id="health" src="ui/misc/health_bar" slice9="1,1,14,14"/>

  <!-- グループを"mcguffin"に設定 -->
  <group id="mcguffin"/>
    <!--
    ・(x,y) = (10,5)に配置
    ・サイズは(width,height) = (134,16)
    -->
    <chrome id="health_bar" x="10" y="5" width="134" height="16" use_def="health" group="mcguffin">
      <!-- 左上で位置を固定する -->
      <anchor x="portrait.right" y="portrait.top" x-flush="left" y-flush="top"/>
      <min_size width="stretch:portrait.right+10,right-10"/>
      <max_size width="stretch:portrait.right+10,right-10"/>
    </chrome>
    <!-- グループ"mcguffin"終了 -->
</data>

こんな感じで表示されます。

FlxUI9SliceSprite001.png

ゲージの増減は以下のように実装します

  // 経過時間(ゲージ増減用タイマー)
  var _timer:Float = 0.0;

  /**
   * 更新
   */
  override public function update(elapsed:Float):Void {
    super.update(elapsed);

    _timer += elapsed;
    if(_timer > 10) {
      // 10秒でゼロに戻す
      _timer = 0;
    }

    // UIグループ"mcguffin"を取得
    var group:FlxUIGroup = _ui.getGroup("mcguffin");
    group.forEachOfType(IFlxUIWidget, function(ui:IFlxUIWidget) {
      if(ui.name == "health_bar") {
        // 名前が一致
        var bar:FlxUI9SliceSprite = cast ui;
        // ゲージ更新
        bar.resize(_timer / 10 * 134, 16);
      }
    });
  }

FlxUIButton (ボタン)

FlxUIButton003.png
  <button id="btn001" label="CLICK ME" x="8" y="8" width="64" height="32">
  • idは"btn001"
  • (x, y)=(8, 8)を基準(左上座標)に配置
  • サイズは(width, height)=(64, 32)
  • ラベル名は "CLICK ME"

FlxUIButton (ボタン・画像差し替え)

標準のボタン画像を別の画像に差し替えます。まずは以下のような画像を用意します。

blue_button.png

縦に3つ並んでいるのは、それぞれに対応する状態の場合に表示するためです。

blue_button002.png
  • ボタンを押していないとき(up)
  • ボタンにカーソルがフォーカスしているとき(over)
  • ボタンをクリックしているとき(down)

"blue_button.png"を"assets/gfx/ui/buttons/"に配置したとすると、以下のようにレイアウトデータを指定します。

    <button id="btn001" label="CLICK ME" x="64" y="32" width="64" height="32">
        <graphic id="all" image="ui/buttons/blue_button" slice9="4,4,11,11" />
    </button>

これでボタン画像を差し替えることができます。

blue_button003.png

なお、graphicタグのidに"all"ではなく、"up" / "over" / "down" を指定すると個別に画像を指定することができます

    <button id="btn001" label="CLICK ME" x="64" y="32" width="64" height="32">
        <graphic id="up" image="ui/buttons/blue_button_up" slice9="4,4,11,11" /> <!-- ボタンを押していない -->
        <graphic id="over" image="ui/buttons/blue_button_over" slice9="4,4,11,11" /> <!-- カーソルが上にある -->
        <graphic id="down" image="ui/buttons/blue_button_down" slice9="4,4,11,11" /> <!-- クリック中 -->
    </button>

FlxUIButton (テキストボタン)

  <button id="popup" center_x="true" x="0" y="450" group="top" label="Popup">
    <graphic blank="true"/> <!-- ボタン画像を非表示 -->
  </button>
  • idは"popup"
  • X軸に中央揃え
  • (x, y)=(0, 450)を基準(左上座標)に配置
  • グループ "top"
  • 表示する文字列 "Popup"

FlxUIText (テキスト)

■例1

  <text id="title" x="32" y="160" width="120" text="JUMP ACTION" align="center" />
  • idは"title"
  • (x, y)=(32, 160)
  • 幅「120」で中央揃え
  • 表示する文字列は "JUMP ACTION"

■例2

  <definition id="sans12c" font="vera" size="12" style="bold" color="0xffffff" outline="0x000000" align="center"/>
  <text id="title" use_def="sans12c" x="32" y="160" width="120" text="JUMP ACTION" />
  • definitionの設定
    • idは"sans12c"
    • フォントは"vera" ("assets/fonts/vera.ttf"に配置)
    • フォントサイズは「12」
    • 書体は太字
    • フォントの色は白
    • フォントのアウトラインは黒
    • 中央揃え有効
  • textタグの設定
    • idは"title"
    • (x, y)=(32, 160)
    • 定義「sans12c」を参照
    • 幅「120」
    • 表示する文字列は "JUMP ACTION"

■テキストの変更
FlxUI.forEachOfType?で、nameが一致するIFlxUIWidgetを探し、FlxUITextにキャストして変更する

  override public function update(elapsed:Float):Void {
    super.update(elapsed);

    _ui.forEachOfType(IFlxUIWidget, function(ui:IFlxUIWidget) {
      if(ui.name == "title") {
        // 名前が一致
        var txt:FlxUIText = cast ui;
        // テキストを変更
        txt.text = "HOGE";
      }
    });
  }

FlxUIRadioGroup (ラジオボタン)

  <!-- ■定義 -->
  <!-- radio_srcは非選択時の画像。dat_srcは選択時の画像 -->
  <definition id="radio_1" radio_src="ui/misc/radio" dat_src="ui/misc/radio_dat">
    <text>
      <!-- マウスオーバー時のテキストの色 -->
      <color id="over" value="0xffff00" />
    </text>
  </definition>

  <!-- ■ラジオボタンの定義 -->
  <radio_group x="10" y="10" use_def="radio_1" id="radio_classes">
    <!-- クリックしたときのパラメータ。なくても問題なし -->
    <param type="string" value="radio_group" />

    <radio id="radio0" label="Class1" /> <!-- 1つめのラジオボタン -->
    <radio id="radio1" label="Class2" /> <!-- 2つめのラジオボタン -->
    <radio id="radio2" label="Class3" /> <!-- 3つめのラジオボタン -->
  </radio_group>

選択した項目を受け取るコールバックの書き方

  /**
   * UIWidgetのコールバック受け取り
   **/
  public override function getEvent(id:String, sender:Dynamic, data:Dynamic, ?params:Array<Dynamic>):Void {
    var widget:IFlxUIWidget = cast sender;
    if(widget != null) {
      if(Std.is(widget, FlxUIRadioGroup)) {
        var radio:FlxUIRadioGroup = cast widget;
        switch(id) {
          case FlxUIRadioGroup.CLICK_EVENT:
            trace("選択した項目の番号は", radio.selectedIndex, "です");
        }
      }
    }
  }

実行時にラジオボタンのラベルを変更する場合は、FlxUIRadioGroup.updateLabel() を使用します

共通設定ファイルの作り方

includeタグを使うと、別のXMLファイルをインクルードして展開することができます。

<?xml version="1.0" encoding="utf-8" ?>
<data>	
  <include id="_ui_globals"/> <!-- "_ui_globals.xml"をインクルードする -->
</data>

_ui_globals.xml ファイルを例えば以下のように定義します。

<?xml version="1.0" encoding="utf-8" ?>
<data>

  <!-- idは"sans16c"、フォントは"vera" サイズは16、太字、色は白、アウトラインは黒、中央揃え -->
  <definition id="sans16c" font="vera" size="16" style="bold" color="0xffffff" outline="0x000000" align="center"/>

  <!-- idを"text_button"、サイズを 64x32 にする -->
  <definition id="text_button" width="64" height="32">
    <graphic blank="true"/> <!-- 画像はなし -->
    <text use_def="sans16c" color="0xffffff"> <!-- テキスト設定は "sans16c" を使う -->
      <color id="up"   value="0xffffff"/> <!-- ボタンを押していない場合は白色 -->
      <color id="over" value="0xffff00"/> <!-- ボタンの上にカーソルがあれば黄色 -->
      <color id="down" value="0xffff00"/> <!-- クリックしていたら黄色 -->
    </text>
  </definition>
</data>

すると、この設定を別のUI定義ファイルで再利用できます。

<?xml version="1.0" encoding="utf-8" ?>
<data>	
  <include id="_ui_globals"/> <!-- "_ui_globals.xml"をインクルードする -->

  <!-- use_def に"text_button"を指定することで、"text_button"の設定を再利用する -->
  <button id="saves" center_x="true" x="-100" y="505" use_def="text_button" group="top" label="Save">
</data>

modeタグの使い方

modeタグを使うと、表示・非表示にするグループを簡単に定義できるようになります。例えば、フィールド用メニュー(field)とバトル用メニュー(battle)のモードを以下のように定義します。

  <mode id="field" is_default="true"> <!-- 標準のモードにする -->
    <show id="search" /> <!-- 探索を表示 -->
    <show id="menu" /> <!-- メニューを表示 -->
    <hide id="attack" />
    <hide id="skill" />
    <hide id="escape" />
  </mode>
  <mode id="battle">
    <hide id="search" />
    <hide id="menu" />
    <show id="attack" /> <!-- 攻撃を表示 -->
    <show id="skill" /> <!-- スキルを表示 -->
    <show id="escape" /> <!-- 逃走を表示 -->
  </mode>

そうすると、FlxUI.setModeで表示・非表示を切り替えられるようになります。

class PlayState extends FlxUIState {
  public override function create():Void {
    _xml_id = "menu";
    super.create();
    _ui.setMode("battle"); // バトル用メニューの表示
  }
}

なお、nameはカンマ区切りで複数指定することも可能です。

  <mode name="field">
    <show name="search,menu" />
    <hide name="attack,skill,escape" />
  </mode>

動的なUI生成

ボタンにアイコン画像をのせる

例えばこのようなボタンがあるとします。

FlxUIButton001.png

このボタンにこのようなハートの画像をのせてみます。

heart.png

FlxUIButton.addIcon()を使うとボタンの上にアイコン画像をのせることができます。

  var btn:FlxUIButton;
  var icon = new FlxSprite(0, 0, "assets/images/heart.png"); // ハート画像読み込み
  // アイコン画像をのせる
  btn.addIcon(icon, 0, -4, false); // (0, -4)にオフセットする

するとボタンの上にアイコン画像がのります。なおアイコン画像は余白を大きめに取らないと正しく表示されないことがあるようです

FlxUIButton002.png

FlxUIList

FlxUIListを使用すると項目をリスト化できます。

/// MenuState.hx
class MenuState extends FlxState {
  private var _list:FlxUIList;

  override public function create():Void {
    var widgets:Array<IFlxUIWidget> = [
      new FlxUIText(0, 0, "hoge"),
      new FlxUIText(0, 0, "piyo"),
      new FlxUIText(0, 0, "momo"),
    ]
    _list = new FlxUIList(8, 32, widgets);
    add(_list);
  }

  // リストにテキストを追加
  public function addList(text:FlxUIText):Void {
    _list.add(text);
    _list.visible = true; // これによりリストに反映される
  }

参考