0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Godot 4.0】スマホ3Dゲームを作るための勉強 その36 HUD(Head Up Display)を追加する

Posted at

 ゲームエンジンGodot4.0で3Dスマホゲームを作りたいと思いますが、その前にお勉強しています。
 2023/4/4リリースのGodot_v4.0.2-stable_win64を使用しています。

目的

 ゲーム中の情報を2Dで表示する画面を追加していきます。

ベースプロジェクト

 下記の記事を通して作成したプロジェクトをベースにしています。

 github(Godotのプロジェクトマネージャーからインポートして利用できます)

目的

 エネルギーバーを追加します。

powerbar.png

ゲーム中の情報の表示について

 ゲーム中の情報の表示はスコア、何かしらの量を表示するためのバーなどありますが、2Dで表示したいものがあると思います。
 2Dで表示したい情報については、CanvasItemを継承したノード(Node2DやControlの派生クラスがたくさんあります)を追加して、そのノードに描画を行います。
 描画位置/サイズはピクセル位置で指定します。
 描画サイズはプロジェクト設定の表示/ウインドウのビューポートの幅と高さになります。
スクリーンショット (695).png
 ビューポートの幅がX軸方向で、高さがY軸方向です。
 左上がx=0,y=0で、右がXプラス、下がyプラスになります。
スクリーンショット (698).png

表示するゲームパラメータを実装する

 エネルギーバーに表示するゲームパラメータを追加します。
 画面タッチしっぱなしにするとBulletを発射しますが、Bulletを発射するたびにエネルギーがたまる変数を追加します。
 複数のシーンのスクリプト(Player.gdとこれから追加するHUD.gd)からアクセスしたいので、シングルトン(自動読み込み)スクリプトを生成して変数を定義します。

グローバル変数を定義するスクリプトを作成します。

 ファイルシステムのresを右クリックして新規>スクリプトを実行します。
 スクリーンショット (699).png
 global_variable.gdという名前で保存します。
スクリーンショット (700).png
 res://global_variable.gdが作成されました。
スクリーンショット (701).png

エネルギー量を管理するためのスクリプトを実装する

 res://global_variable.gdを開いて下記のように修正します。

extends Node

# パラメータ
@export var m_d_energy_max : float = 100.0
@export var m_d_energy_min : float = 0.0
@export var m_d_energy_add : float = 5.0	# Bullet発射間隔が1秒の場合、20秒で100になる計算

# グローバル変数
var m_d_energy : float = 0.0

func increase_energy():
	m_d_energy = clampf(
				m_d_energy + m_d_energy_add,
				m_d_energy_min,
				m_d_energy_max
			)

 m_d_energyが現在のエネルギー量を表すグローバル変数です。
 最大/最小値を定義します。0~100までにしました。また1回に追加する量をm_d_energy_addとして定義します。
 @exportしてインスペクタから変更できるようにしています。
 最後にエネルギを蓄積するAPIをincrease_energy()という名前で追加しました。
 エネルギーを増加した後の値をclampf()関数で0以下の場合は0に、100以上の場合は100になるようにクランプします(リミットする、制限するなどと同じ意味です)。

シングルトン(自動読み込み)スクリプトして登録する

 次に実装したスクリプトをシングルトン(自動読み込み)スクリプトとして登録します。
 プロジェクトメニューのプロジェクト設定を開いて、「Autoload」タブを選択します。
 パスに先ほど作成したres://global_variable.gdを設定します。ノード名が自動で入力されるので確認後「追加」ボタンを押下します。
スクリーンショット (702).png
 追加されました。「グローバル変数」にチェックがついていることを確認してください。
 チェックがついていると、名前「GlobalVariable」でどのスクリプトからもアクセスできるようになります。
スクリーンショット (703).png

PlayerからBulletが発射されるとエネルギーをためるようにします。

 res://Characters/Player.gdを開きます。
 _on_timer_fire_timeout()がBullet発射処理なので、最後にエネルギーをためるメソッドを実行します。

func _on_timer_fire_timeout():
	# スマホタッチ中の場合、発射する
	if m_f_is_screen_touch:
		var scn_bullet = m_scn_bullet.instantiate()
		scn_bullet.transform.origin = $Marker3D.global_transform.origin
		add_sibling(scn_bullet)
		
		# エネルギーをためる
		GlobalVariable.increase_energy()

エネルギーバーを描画する位置を決める

 エネルギーバーを描画する位置は直接ピクセルで指定してもよいのですが、エディター上で位置とサイズを確認したいので、Controlを配置して位置を指定しました。

HUD描画領域全体を定義します。

 res://game_system.tscnを開きます。
 ルートノードのGameSystemを右クリックして、子ノードを追加からControlを追加します。
 「HUD」(Head Up Display)に名称を変更します。
スクリーンショット (704).png
 HUDを画面全体(プロジェクト設定の表示>ウインドウのビューポートの幅と高さ)と同じサイズにします。
 HUDを選択した状態でインスペクタのControl/Layoutを開いて、さらのTransformを開いて、Sizeをx=500px、y=900pxにします。
 中央の2D表示エリアの画面サイズを表す青い長方形と同じ大きさのHUDの長方形が描画されます。
スクリーンショット (705).png

エネルギーバー描画領域用Controlを配置します

 HUDを右クリックして、子ノードを追加からControlを追加します。
 名称をEnergyBarに変更します。
スクリーンショット (706).png
 EnergyBarを選択した状態でインスペクタのControl/Layoutを開いて、さらのTransformを開いて、Sizeをx=450px、y=20pxにします。Positionのx=25px、y=870pxにします。
スクリーンショット (707).png

HUDとEnergyBarをControlにしたのは、同時に選択すると2Dビュー上で位置・サイズ関係を確認することができるためです。描画はHUDのCanvasItemに対して実行しているので、EnergyBarは位置・サイズを取得するためだけに使用しています。あとでLabelを追加する時にはControlの機能を利用しています。
スクリーンショット (709).png

EnergyBarを描画します

エネルギー割合取得用のAPIを追加

 res://global_variable.gdを開いて、エネルギー割合取得用のAPIを追加します。
 エネルギーのたまり具合を%(0.0が0%、1.0が100%)で取得するようにしました。「->float」でリターン値がfloat型であることを指定しています。

func get_energy_percent() ->float:
	return m_d_energy / m_d_energy_max

HUDにスクリプトを生成する

 HUDを右クリックしてスクリプトをアタッチします。そのままHUD.gdと名前で保存します。
スクリーンショット (708).png
 下記のように修正します。

extends Control

func _process(delta):
	# Godotエンジンに描画更新を依頼する(_drawメソッド起動を依頼する)
	queue_redraw()
	
func _draw():
	# EnergyBarのサイズ(と使わないけど左上位置)を取得する
	var r : Rect2 = $EnergyBar.get_global_rect()
	# エネルギーバーの背景を黒で描画する
	draw_rect(r, Color.BLACK, true, -1)
	# エネルギーバーの描画領域は1ピクセルずつ小さくする
	var er = r;
	er.size     -= Vector2(2, 2)	# サイズは上下左右一回り小さくする
	er.position += Vector2(1, 1)	# 1ピクセルずつ右下に移動する
	# エネルギーの蓄積割合に従い長さを決めて黄色のバーで描画する。
	er.size.x *= GlobalVariable.get_energy_percent()	# 0.0~1.0の間
	draw_rect(er, Color.YELLOW, true, -1)

 _drawメソッドは1回しか起動されないため、更新したい場合queue_redraw()でGodotエンジンに描画を依頼する必要があります。
 今回は毎周期更新依頼をするようにしました。
 「var r : Rect2 = \$EnergyBar.get_global_rect()」で先ほど2Dビューの中で配置したEnergyBarの位置とサイズをRect2型で取得しています。「var r : Rect2」のように型を指定すると、エディターのコード補完ができるので便利ですね。(var r = $EnergyBar.get_global_rect()でも動作上は問題ありません)
 draw_rect(er, Color.YELLOW, true, -1)で長方形を描画します。第3引数をtrueにすると長方形の中を塗りつぶします。ちなみにfalseにすると枠のみ描画になって、第4引数で枠の太さを指定できるみたいですね。

 実行します。画面の下の方にエネルギーバーが表示されます。発射するたびに黄色のバーが伸びて、20回発射すると一番右まで黄色のバーが伸びます。
スクリーンショット (710).png

エネルギーのたまり具合を数値で表示する

 エネルギーのたまり具合を文字で表示しましょう。位置はエネルギーバーの中央にしたいと思うので、Controlノードのアンカーを使います。

labelを追加する

 res://game_system.tscnを開きます
 EnergyBarを右クリックして、子ノードを追加からLabelを追加します。
 「EnergyPercent」に名称変更します。
スクリーンショット (711).png

Controlのアンカーを使ってLabelの位置をエネルギーバーの中央にする

 画面上部の「2D」をクリックします。
 EnergyPercentを選択した状態で、ビューの右にある丸の中に十字があるアイコンをクリックして、中央を選択します。
 下図のようにEnergyPercentがエネルギーバーの中央に移動しました。
スクリーンショット (713).png

Controlのアンカー(Anchors)機能を使用すると、親Controlに対する子ノードの位置を中央とか右、左など設定できます。ざっくり位置を決めたいときは便利ですね。

文字色を変更する

 黄色背景の白文字では見にくいので、文字色をグレーに変更します。
 EnergyPercentを選択した状態で、インスペクタのLabel/Label Settingsの右の<空>をクリックして、「新規LabelSettings」を選択します。
スクリーンショット (714).png
 追加されたLabelSettingsをクリックして詳細を開き、さらにFontを開きます。
スクリーンショット (716).png
 Colorの右の白い長方形をクリックするとカラーピッカーが表示されるので、グレーに変更します。
 (R,G,B)=(80,80,80)にしました。
スクリーンショット (718).png

Labelの文字列を更新する

res://HUD.gdを開いて、_draw()の最後に、エネルギーのたまり具体を文字列として設定する処置を追加します。

extends Control

func _process(delta):
	# Godotエンジンに描画更新を依頼する(_drawメソッド起動を依頼する)
	queue_redraw()
	
func _draw():
	# EnergyBarのサイズ(と使わないけど左上位置)を取得する
	var r : Rect2 = $EnergyBar.get_global_rect()
	# エネルギーバーの背景を黒で描画する
	draw_rect(r, Color.BLACK, true, -1)
	# エネルギーバーの描画領域は1ピクセルずつ小さくする
	var er = r;
	er.size     -= Vector2(2, 2)	# サイズは上下左右一回り小さくする
	er.position += Vector2(1, 1)	# 1ピクセルずつ右下に移動する
	# エネルギーの蓄積割合に従い長さを決めて黄色のバーで描画する。
	er.size.x *= GlobalVariable.get_energy_percent()	# 0.0~1.0の間
	draw_rect(er, Color.YELLOW, true, -1)

	# エネルギーのたまり具体を%(0.0%~100.0%で表示する)
	$EnergyBar/EnergyPercent.text = "%.1f%%" % ( GlobalVariable.get_energy_percent() * 100.0 )

 GlobalVariable.get_energy_percent()の0.0~1.0が0%~100%に対応するため100倍します。
 フォーマット文字列ではfloatの値を表示するので%fで受けます。小数点第1位まで表示するので「%.1f」としています。
 最後に「%」を文字として表示したいのですが、GDScript format stringsの中で「%」はプレイスホルダーとしての特別な機能を持つため、文字として表示するために%%と2回繰り返します。

GDScript format strings
https://docs.godotengine.org/en/latest/tutorials/scripting/gdscript/gdscript_format_string.html#doc-gdscript-printf

 実行します。
スクリーンショット (719).png

以上

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?