【Gudot】謎解きゲームで使いそうな数値入力UIの作成方法

今回は謎解きゲームで使いそうな数値入力UIの作成方法を解説します。

数値入力UIの作成方法

素材データのダウンロード

今回は日本語テキストを使用したいので、日本語フォントをプロジェクトに追加しておきます。

Themeリソースの作成

日本語フォントを使用するために Theme リソースを作成します。ファイルシステムを右クリックして「新規リソース…」を選びます。

Themeリソースを作成します。

リソースの名前を指定します。ここでは「default_theme.tres」としました。

作成した Themeリソースをダブルクリックして、インスペクターから「Default Font > [空]」をクリックして「新規 DynamicFont」を選びます。

作成した DynamicFont をクリックするとフォントの設定が表示されるので「Font > FontData > [空]」をクリックして「読み込み」を選びます。

プロジェクトに追加した日本語フォント “mplus-1c-regular.ttf” を開きます。

これで日本語フォントを設定できたので「保存」をクリックしてセーブしておきます。

数値入力のパーツのシーンを作成する

次に数値入力のパーツのシーンを作成します。

コンテナを使ってUI部品をまとめたいので「+その他のノード」をクリックします。

作成するUIノードは「VBoxContainer」となります。これは縦方向にUIをまとめるコンテナとなります。

UIノードを作成したらノード名を「NumberInputSimgle」とリネームしておきます。

ボタンと数値テキストを表示する

次に「Button」ノードを追加します。

作成したら名前を「ButtonUp」に変更します。

このボタンは上向きの矢印ボタンとするためです。

次に数値をテキストとして表示するために「Label」を追加します。ただいったんルートノードを選択しないと “ButtonUp” の下の階層に作られてしまうので、「NumberInputSimgle」を選択してから作成するとよいです。

Labelノードは特にリネームせずに「NumberInputSimgle」を選択して、下向きのボタンノード (Button) を作成します。

作成したボタン名は「ButtonDown」にリネームします。

Themeリソースを設定する

各UIで日本語を表示できるように Themeリソースを設定します。

このとき Shiftキーを押しながらノードを選択するとまとめて選択でき、まとめて Themeリソースを割り当てることができます。

選択したらインスペクターから「Theme > Theme > [空]」をクリックして、「読み込み」を選びます。

先ほど作成した Themeリソース “default_theme.tres” を開きます。

これで日本語フォントが各UIで使用できるようになったので、それぞれの「Text」に以下の文字を設定します。

  • ButtonUp: ▲ (上向きの三角)
  • Label: 0
  • ButtonDown: ▼ (下向きの三角)

これで数値入力UIっぽいものができたのですが、文字が左揃えになっているので、”Label”ノードを選択して、インスペクターから「Label > Align」の値を「Center」にして “中央揃え” に変更しておきます。

補足:見た目を良くしたい場合

今回は楽をするために “Button”ノードを使用し、日本語フォントで上下の三角ボタンを作成しましたが、「TextureButton」を使用すると Texture からボタンの見た目を画像に変更できます。

よりクオリティを上げたい場合はこちらのUIノードを使用するのが良いと思います。

上下ボタンの入力を処理する

次に上下ボタンの入力を処理します。

その前にまずは「Ctrl+S (Cmd+S)」でシーンを「NumberInputSimgle.tscn」として保存します。

保存できたら “NumberInputSimgle” ノード(ルートノード) にスクリプトをアタッチします。

extends VBoxContainer

export var min_value = 0 # 最小値
export var max_value = 9 # 最大値
export var value = 0 # 現在の値

onready var label = $Label

func _process(_delta: float) -> void:
	# ラベルに数値を反映する
	label.text = str(value)

ここで扱う場合には1桁の数値なので「0〜9」の数値を入力できるとします

次に “ButtonUp” を選び pressed() シグナルを追加します。シグナルのコードは以下のとおりです。

func _on_ButtonUp_pressed() -> void:
	# 上ボタンを押した場合
	# 値を減算する
	value -= 1
	if value < min_value:
		value = max_value	

上ボタンは値が増加しそうな気がするのですが、私の好みで値が減少するようにしました。違和感がある場合は増加でも良いと思います。

ButtonDown” にも pressed() シグナルを追加します。シグナルのコードは以下のとおりです。

func _on_ButtonDown_pressed() -> void:
	# 下ボタンを押した場合
	# 値を加算する
	value += 1
	if value > max_value:
		value = min_value

では実行して動作を確認します。

念のため、NumberInputSimgle.gd スクリプトのコード全文をのせておきます。

extends VBoxContainer

export var min_value = 0 # 最小値
export var max_value = 9 # 最大値
export var value = 0 # 現在の値

onready var label = $Label

func _process(_delta: float) -> void:
	# ラベルに数値を反映する
	label.text = str(value)

func _on_ButtonUp_pressed() -> void:
	# 上ボタンを押した場合
	# 値を減算する
	value -= 1
	if value < min_value:
		value = max_value	

func _on_ButtonDown_pressed() -> void:
	# 下ボタンを押した場合
	# 値を加算する
	value += 1
	if value > max_value:
		value = min_value

余談: 文字入力を可能にしたい場合

今回は解説しませんが、数値入力ではなく、文字入力(文字選択)を可能にしたい場合は「選択可能な文字をリストにする」方法で実装できます。

以下実装例です。

# 文字を選ばせる入力UIの実装例

extends VBoxContainer

export var value = 0 # 現在の値
var table = ["あ", "い", "う", "え", "お"]

onready var label = $Label

func _process(_delta: float) -> void:
	# ラベルにvalueに対応するテーブルの文字を反映する
	label.text = table[ value ]

4桁の数値入力を行うUIを作成する

1桁の数値入力であればこれで良いのですが、たいていはある程度の桁数の数値入力が必要になると思います。

そこで4桁の数値入力をできるUIを作成してみます。

ルートノード(Mainシーン)の作成

コントロールノードを新規作成します。

ノード名は「Main」に変更して、シーンとして保存(Main.tscn)しておきます。

そしてスクリプト (Maingd) をアタッチしておきます。

extends Control

まだ何も実装しないので中身は型の定義のみで良いです。

HBoxContainerを作成する

複数の桁数を管理するために “HBoxContainer” ノードを作成します。

これは UIを横並びに整列するUIコンテナノードです。

そして作成した HBoxContainer に “NumberInputSimgle.tscn” をドラッグ&ドロップで追加していきます。

うまく追加できない (HBoxContainerの直接の子ノードにならない) 場合は、作成したノードをドラッグ&ドラップで調整をします。

入力判定確認用のラベルを作成する

入力判定確認用に2つのラベルを追加します。

それぞれ日本語フォントのテーマ(default_theme.tres) を設定しておいてください。

そして Label ノードの Text には「99かける99は?」と入力し、Label2ノードの Textには「入力した値」と設定して良い感じの位置に調整しておきます。

入力判定を行うボタンを追加する

次に「Button」ノードを追加します。

Themeには “default_theme.tres” を設定して日本語フォントを使えるようにしておき、Textには「決定」と設定してわかりやすい場所に移動させます。

そしてButtonの pressed() シグナルを追加し、Main.gd スクリプトを以下のように実装します。

extends Control

onready var label = $Label2
onready var numbers = $HBoxContainer

func _ready() -> void:
	pass # Replace with function body.

func _on_Button_pressed() -> void:
	var num = 0
	
	# 逆順で合計値を求める
	var digit = numbers.get_child_count() - 1
	
	for child in numbers.get_children():
		var v = child.value
		num += v * pow(10, digit)
		digit -= 1
	
	label.text = "入力した値: %d"%num
	
	if num == 9801:
		label.text = "正解!"

HBoxContainerのget_child() で上から順に数値入力(NumberInputSingle)が取得できるので、逆順(千の位→百の位→十の位→一の位)で合計値を計算します。

pow() を使うと10の指数(桁数)からその桁に対応する値を求めることができるので便利です。

では実行して動作を確認します。

99×99 は 9801 なので、”9801″ を入力すると正解となります。

完成プロジェクト

今回作成したプロジェクトファイルを添付しておきます。