ゲームエンジンGodot4.0で3Dスマホゲームを作りたいと思いますが、その前にお勉強しています。
2023/4/4リリースのGodot_v4.0.2-stable_win64を使用しています。
目的
ゲーム中の情報を2Dで表示する画面を追加していきます。
ベースプロジェクト
下記の記事を通して作成したプロジェクトをベースにしています。
github(Godotのプロジェクトマネージャーからインポートして利用できます)
目的
エネルギーバーを追加します。
ゲーム中の情報の表示について
ゲーム中の情報の表示はスコア、何かしらの量を表示するためのバーなどありますが、2Dで表示したいものがあると思います。
2Dで表示したい情報については、CanvasItemを継承したノード(Node2DやControlの派生クラスがたくさんあります)を追加して、そのノードに描画を行います。
描画位置/サイズはピクセル位置で指定します。
描画サイズはプロジェクト設定の表示/ウインドウのビューポートの幅と高さになります。
ビューポートの幅がX軸方向で、高さがY軸方向です。
左上がx=0,y=0で、右がXプラス、下がyプラスになります。
表示するゲームパラメータを実装する
エネルギーバーに表示するゲームパラメータを追加します。
画面タッチしっぱなしにするとBulletを発射しますが、Bulletを発射するたびにエネルギーがたまる変数を追加します。
複数のシーンのスクリプト(Player.gdとこれから追加するHUD.gd)からアクセスしたいので、シングルトン(自動読み込み)スクリプトを生成して変数を定義します。
グローバル変数を定義するスクリプトを作成します。
ファイルシステムのresを右クリックして新規>スクリプトを実行します。
global_variable.gdという名前で保存します。
res://global_variable.gdが作成されました。
エネルギー量を管理するためのスクリプトを実装する
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を設定します。ノード名が自動で入力されるので確認後「追加」ボタンを押下します。
追加されました。「グローバル変数」にチェックがついていることを確認してください。
チェックがついていると、名前「GlobalVariable」でどのスクリプトからもアクセスできるようになります。
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)に名称を変更します。
HUDを画面全体(プロジェクト設定の表示>ウインドウのビューポートの幅と高さ)と同じサイズにします。
HUDを選択した状態でインスペクタのControl/Layoutを開いて、さらのTransformを開いて、Sizeをx=500px、y=900pxにします。
中央の2D表示エリアの画面サイズを表す青い長方形と同じ大きさのHUDの長方形が描画されます。
エネルギーバー描画領域用Controlを配置します
HUDを右クリックして、子ノードを追加からControlを追加します。
名称をEnergyBarに変更します。
EnergyBarを選択した状態でインスペクタのControl/Layoutを開いて、さらのTransformを開いて、Sizeをx=450px、y=20pxにします。Positionのx=25px、y=870pxにします。
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と名前で保存します。
下記のように修正します。
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回発射すると一番右まで黄色のバーが伸びます。
エネルギーのたまり具合を数値で表示する
エネルギーのたまり具合を文字で表示しましょう。位置はエネルギーバーの中央にしたいと思うので、Controlノードのアンカーを使います。
labelを追加する
res://game_system.tscnを開きます
EnergyBarを右クリックして、子ノードを追加からLabelを追加します。
「EnergyPercent」に名称変更します。
Controlのアンカーを使ってLabelの位置をエネルギーバーの中央にする
画面上部の「2D」をクリックします。
EnergyPercentを選択した状態で、ビューの右にある丸の中に十字があるアイコンをクリックして、中央を選択します。
下図のようにEnergyPercentがエネルギーバーの中央に移動しました。
Controlのアンカー(Anchors)機能を使用すると、親Controlに対する子ノードの位置を中央とか右、左など設定できます。ざっくり位置を決めたいときは便利ですね。
文字色を変更する
黄色背景の白文字では見にくいので、文字色をグレーに変更します。
EnergyPercentを選択した状態で、インスペクタのLabel/Label Settingsの右の<空>をクリックして、「新規LabelSettings」を選択します。
追加されたLabelSettingsをクリックして詳細を開き、さらにFontを開きます。
Colorの右の白い長方形をクリックするとカラーピッカーが表示されるので、グレーに変更します。
(R,G,B)=(80,80,80)にしました。
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
以上