赤宿 = Red Inn

素人の試行錯誤と2Dローグライク・ゲーム制作

Into Nez.UI [随時更新]

 PyQt5テキストエディタを組んでいたおかげで、UIフレームワーク全般への理解が深まった。そのため、自分のゲームでもNez.UIを導入することができそう。

 ちなみに、Nez.UIlibGDXのライブラリScene2Dを移植したもの。

英単語いろいろ

  • padding: コンテンツの内周の余白
  • margin: コンテンツの外周の余白
  • culling (area): ある範囲からはみ出た部分を描画しない謎技術

成果物 (クリックで拡大)

† Soul Garden † (PyQt5)

f:id:samba_4e:20180729203523p:plain:w320

 執筆用のテキストエディタ。フォルダは一つしか開けない。

 ツールバーの無い親切設計。こっそり配布中だが、.txtファイル以外を開くと死亡、検索・置換が無い、他アプリからテキストを編集した場合の対応が雑、など開発途中。Effective Pythonを読んだら組み直すかも。(でも読まないかも)。

開発中のゲーム (Nez)

f:id:samba_4e:20180729203522p:plain:w320

 メニューはBuilderを用意し、MenuBuilder().begin().size(). .. .build()という形で作っている。Builderただ1つをSerializableかつDesearizableにすれば、全メニューがデータ駆動になる……はず。

(実は2つのTableを使っている。1つは背景を描画し、タイトルとアイテム欄を配列している。もう1つはアイテム欄としてのTableで、ScrollPaneを親に持つ。Tableの解説は後述)

UIフレームワーク

オブジェクトの親子関係

 UIフレームワークのオブジェクトは、シーングラフと呼ばれるオブジェクトの親子関係を築く。正確にはルートが存在するツリーなのだが、慣用的にグラフと呼ばれているらしい?

座標変換/レイアウト

 親オブジェクトからの相対座標で描画する。子オブジェクトを縦や横に配列したり、セルの中に入れたり、何枚も重ねて表示する親もある。

 相対座標は、基本的にはTransform行列で伝達される?

キー入力の伝播

 UIオブジェクトのツリーの起点に、入力を扱うオブジェクトがある。それが、フォーカスの合った子オブジェクトにキー入力を伝播する。

 Nez.UIの場合、基底にあるのはStageオブジェクト。子のイベント関数を呼ぶことで入力を流すが、ここを書き換えることで、UIのキーセットを差し替える事ができる。

アニメーションを自在にする

 拡大率などは、値を(リフレクション経由で)直接tweenにするのではなく、関数経由で値を変更する。イベント関数が呼ばれるため。

 .tweenScale()など、特別な名前の拡張メソッドを定義する。

Nez.UI

代表的なクラス

UICanvas : Component, IUpdatable

 StageをNez本体のゲームループ(主にECSを更新)に参加さえるためのラッパ。Stageを更新するだけ。

Stage

 描画や更新の開始点。root: Groupを持つ。入力も扱うため、仮想キーを導入するには、まずここを書き換える。

Element

 シーングラフのNode基底クラスに相当。

Group : ELement

 子を持てるNode。

Container

 単一の子を持ち、その位置や大きさを設定する。background: Nez.UI.IDrawableを設定できる。

Table : Element

 Cellに分けて子を配列する。backgroundを設定できる。Cellのpaddingなども細かく設定できる。

TextButton : Table, IInputListener, IGamepadFocusable

 実装が楽なためか、Tableを継承して作られている。振る舞いはTableではないと思う。

ScrollPane

 子の真横にスクロールバーを表示し、cullingAreaの範囲内でのスクロールを可能にする。

  • elementA.addElement( new ScrollPane( elementB ) ) の形で使用する
     elementBの親が自動的にScrollPaneになることに注意。僕はここでハマりました……

  • スクロールバーの表示位置を調整するには
     子のpadRightを設定することで、上記スクリーンショットのような位置に表示していた。これはhack。せめて一定のAPIを作りたい。
     子の真横に表示される、というのが曲者。しかも自動的にリサイズされるのか、.setSize()では、スクロールバーの表示位置を設定することができない。

余談

IDEのショートカットを再設定すると便利だった

  • ctrl+shift+b/r: build/run
  • ctrl+g: go to definition
  • ctrl+tab: next tab
    などなど……

追記: Macの場合、Command+Enterでrunなど、初期状態でもファンクションキーを使わずに済む