今回はデバッグ時に役立つ「通知ボード」の実装方法について紹介します。
目次
通知ボードを実装する
今回紹介する「通知ボード」とは、画面の一部分にデバッグメッセージを表示するものです。
print() でもデバッグ用のメッセージを出力できますが、ちょっとした警告・エラーメッセージであれば画面内に表示したほうが気が付きやすいので、そういった場合に使えるのかと思います。
フォントデータのダウンロード
今回使用するフォントデータをダウンロードします。
ダウンロードしたフォントデータをプロジェクトに追加します。
テーマリソースの作成
次にフォントデータを利用するためのテーマリソースを作成します。
ファイルシステムで右クリックして「新規リソース」を選びます。
Themeを選んで「作成」をクリックします。
「保存」を選びます。
インスペクターから「Default Font > [空]」をクリックして「新規 DynamicFont」を選びます。
作成した Dynamic Font をクリックするとフォント設定が表示されるので「Font > Font Data > [空]」をクリックして、「新規 DynamicFontData」を選びます。
作成した 新規 DynamicFontData をクリックして「Font Path」のところにあるフォルダアイコンをクリックします。
設定したフォントにアウトライン(縁取り)をつけるために「Settings > Outline Size」を「1」にして「Outline Color」を黒色にします。
するとエディタの下部分に表示されているテーマのプレビュー画面に縁取りされたフォントが表示されます。
表示されていなかったり小さくてよくわからない場合は Settings > Size を変更すると大きくしたり表示が更新されます。
今回は文字サイズを「16pt」とするので「16」にしておきます。
最後にテーマビューの「保存」を押して保存します。
特にこのボタンは押さなくても自動保存されるようですが、念のため押しておきます。
通知ボードオブジェクトの作成
ノードの作成
次にNode2Dを作成して名前を「NoticeBoard」に変更します。
ファイルシステムで右クリックして「新規リソース」を選びます。
次に「ColorRect」「Label」の順でノードを作成します。
,ノード階層は以下のようになります。
まず Label ノードの Text に「デバッグメッセージ」と入力しておきます。
ただテーマが設定されていないので文字が表示されません。
ラベルにテーマを設定する
「Control > Theme > [空]」をクリックして「読み込み」を選びます。
先ほど作成した「new_theme.tres」を読み込みます。
するとこのように文字が表示されるようになりました。
背景のサイズと色を設定する
次に ColorRect を選んでサイズを調整します。
インスペクタから Position > x を「-8」、Sizeを「1024×24」としました。
Positionのxを左にずらしているのは余白にゆとりを持たせるためで、サイズは画面サイズの幅がデフォルトで 1024 となっており、高さについてはフォント16ptだと 24px くらいがちょうど良いためです。
このあたりは好みで設定して問題ないと思います。
次に「Color」のA (アルファ値) を 「80」にしておきます。
この値も好みで良いと思います。
スクリプトのアタッチ
これでUIの部品は設定できたのでスクリプトを作成します。
NoticeBoardノードを選んでスクリプトをアタッチします。
extends Node2D
const MARGIN_X = 8
const START_X = 1024+MARGIN_X # 開始座標
const MIN_W = 240 # 最小の幅
# 状態
enum eState {
IN, # 入場
WAIT, # 少し待つ
OUT, # 退場
}
var _state = eState.IN # 状態
var _timer := 0.0 # タイマー
onready var bg = $ColorRect
onready var label = $Label
func _ready() -> void:
# 開始位置を設定する
position.x = START_X
func start(msg:String, color=Color.black) -> void:
# 開始処理
label.text = msg
bg.modulate = color
func _process(delta: float) -> void:
_timer += delta
# メッセージの横幅を求める
var font = label.get_theme_default_font()
var w = font.get_string_size(label.text).x
# 最低保障の幅より大きければ拡張する
w = max(w, MIN_W)
w += MARGIN_X
match _state:
eState.IN: # 入場中
position.x = START_X - w * _expo_out(_timer)
if _timer > 1.0:
# 少し待つ
_state = eState.WAIT
_timer = 0
eState.WAIT: # 少し待つ
position.x = START_X - w
if _timer > 3.0:
# 退場する
_state = eState.OUT
_timer = 0
eState.OUT: # 退場する
position.x = START_X - w * (1.0 - _expo_out(_timer))
if _timer > 1.0:
# 終了
queue_free()
func _expo_out(t):
return -pow(2, -10*t) + 1
このオブジェクトは生成された後、start()関数でメッセージと色を設定します。
動きとしては、
開始時は左の外側にいて少しずつ入場します。(eState.IN)
そして入りきったら 3秒ほど停止します。(eState.WAIT)
そして左側へ退場して消滅します。(eState.OUT)
通知ボードを使用するシーンの作成
ではこの通知ボードオブジェクトを作成するテスト用のシーンを作成します。
Node2Dシーンを作成して名前を「Main」にリネームします。
そして以下のスクリプトをアタッチします。
extends Node2D
const NoticeBoard = preload("res://NoticeBoard.tscn")
var count = 0
func _process(delta: float) -> void:
if Input.is_action_just_pressed("ui_accept"):
# ランダムで表示するメッセージ
var msg_tbl = [
"デバッグメッセージ",
"警告メッセージ",
"エラーメッセージ",
]
# ランダムで変化する色
var color_tbl = [
Color.black,
Color.yellow,
Color.red
]
#var msg = _choice(msg_tbl)
#var color = _choice(color_tbl)
var rnd = randi()%3
var msg = msg_tbl[rnd]
msg += str(count)
var color = color_tbl[rnd]
# 通知ボードを表示する
_add_notice(msg, color)
# リストから抽選を行う
func _choice(tbl):
var length = tbl.size()
var rnd = randi()%length
return tbl[rnd]
# 通知ボードを生成する
func _add_notice(msg:String, color:Color = Color.black):
var notice = NoticeBoard.instance()
add_child(notice)
notice.start(msg, color)
# 生成数に応じてY座標を移動する
notice.position.y = 24 * count
# 生成数をカウントアップする
count = (count + 1)%20
このスクリプトはスペースキーを押すと、ランダムな通知メッセージを表示するものです。
_add_notice() が実際に通知ボードを生成している関数です。
# 通知ボードを生成する
func _add_notice(msg:String, color:Color = Color.black):
var notice = NoticeBoard.instance()
add_child(notice)
notice.start(msg, color)
# 生成数に応じてY座標を移動する
notice.position.y = 24 * count
# 生成数をカウントアップする
count = (count + 1)%20
変数「count」に生成した回数をカウントして、その値をもとに Y座標を下にずらしていきます。
そして20回呼び出すたびに一番上に戻るようにしています。
では実行して動作を確認します。
完成プロジェクト
今回作成したプロジェクトを添付しておきます。
入退場に1秒は長いような気がしたので 0.5 秒に変更しています。