0
0

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ゲームを作るための勉強 その21 ゲームシステムを作る その6 設定画面をPopupPanelで作成する

Last updated at Posted at 2023-03-14

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

目的

 ゲームシステムをつくっていきます。
 設定仮面をつくりましょう。ポップアップダイアログで表示/消去するまでです。

設定画面について

 設定画面はタイトルと同じように新規にシーンを作成して、global.gd経由で切り替えることもできますが、PopupPanelという機能を使用して表示しましょう。

 2023/3/1リリースのGodot4.0 stable版はPopupPanelにいくつか問題がありそうです。
 以下の記事では2つ問題がありつつも実装をすすめていますが、不安な方は別の方法(Window/Popup/PopupPanelを使用しない方法)で実装した方がよいと思います。

ベースプロジェクト

 下記で作成したプロジェクトをベースに機能追加をします。
 【Godot 4.0】スマホ3Dゲームを作るための勉強 その20 ゲームシステムを作る その5 タイトルシーンを作って、神様スクリプトからタイトルシーンとプレイシーンを入れ替えるようにする
 https://qiita.com/FootInGlow/items/08a31719f0077d09d4eb
 
 github(Godotのプロジェクトマネージャーからインポートして利用できます)
 https://github.com/footinglow/Godot4/tree/main/02_study/S20_GameSystem_005

設定ダイアログを作成します。

 プレイヤーがBulletを発射するタイミングは固定で1秒ですが、その間隔を0.1秒~1.0秒の間で設定できるようにします。

新規シーンを作成します。

 シーンメニューから新規シーンを作成します。「その他のノード」ボタンを押下します。
スクリーンショット (212).png
「PopupPanel」を追加します。
スクリーンショット (213).png
名称を「SettingsPopupPanel」に変更して、保存します。
スクリーンショット (214).png
「res://settings_popup_panel.tscn」として保存されました。
スクリーンショット (216).png

設定パネルのサイズを決めるControlを追加します。

 この後追加するボタンなどのコントロールの親となるControlノードを追加します。
 このControlのサイズがPopupPanel全体のサイズになります。

 「SettingsPopupPanel」を右クリックして、「Contorl」ノードを追加します。
 名称を「ControlBaseSize」に変更します。
スクリーンショット (217).png
 「ControlBaseSize」を選択した状態で、インスペクタのControl/Custom Minimum Sizeのx=300px、y=200pxを設定します。
スクリーンショット (218).png

 2023.3.1リリースのGodot4.0ではPopupPanelのサイズ変更がGUI上でできません。そのためContolのインスペクタでサイズを直接設定しました。
 下図のようにGodot3.5の場合はPopupPanelの変更ができるようです。
スクリーンショット (81).png
 PopupPanelのGODOT DOCを参照すると、「similar to how PanelContainer works」とあるので、GUI上でもサイズ変更できるのが正しいような気がします。(PanelContainerにするとGUIでサイズ変更可能)

コントロールを配置します。

 コントロール3つ表示することにします。

コントロール 用途
Label 「発射間隔1秒」のように現在の設定値をテキスト表示する
HSlider スライダーで発射間隔を0.1秒から1.0秒まで0.1秒刻みで調整できるようにします。その結果はLabelに表示します
Button 設定完了時に押下します

 Godotのコントロールの配置はコンテナというのを利用して、Controlパーツを縦/横に並べるように配置していきます。
 今回は縦に3つ並べたいので、VBoxContainerを使用します(横に並べる場合はHBoxContainerを使用します)

 「ControlBaseSize」を右クリックして子ノードを追加から「VBoxContainer」を追加します。
 「VBoxContainer」を右クリックして子ノードを追加から下記の3つのコントロールを追加して各種設定をします。

  • Label
     インスペクタのLabel/Textに「発射間隔1秒」と設定します。
     あとでスクリプトから文字列を設定しますが、位置・サイズを見たいので設定します。
  • HSlider
  • Button
     インスペクタのLabel/Textに「設定完了」と設定します。
    スクリーンショット (82).png
    上部の2Dをクリックすると表示イメージを確認することができます。
    スクリーンショット (220).png

 表示イメージが表示されない場合、「SettingsPopupPanel」を選択した状態で、インスペクタのWindow/FlagsのVisibleをオンにします。

タイトル画面から設定画面を呼び出すように修正します。

タイトル画面に「設定」ボタンを追加します。

 res://title.tscnを開きます。
 Titleを右クリックして、子ノードを追加から「Button」を追加します。
 名称を「SettingsButton」に変更します。
 インスペクタのButton/Textに「設定」と入力します。
スクリーンショット (85).png

 シーン内でSettingsButtonをドラッグしてButtonの下に移動しましょう。
 スクリーンショット (84).png

「設定」ボタンと「Game Start!」ボタンの配置を変更します。

 画面上部の2Dをクリックします。
 SettingsButtonが選択されている状態で、ビューの右のアイコンをクリックして中央下のアイコンをクリックします。
スクリーンショット (86).png
「Game Start!」ボタンの下に「設定」ボタンが移動しました。
スクリーンショット (87).png

 「Game Start!」ボタンと「設定」ボタンをマウスでドラッグして横に並べましょう。
スクリーンショット (88).png
画面全体で確認するとこのような感じにしました。
スクリーンショット (89).png

「設定」ボタンを押下するとPopupPanelを表示するようにします。

 res://title.tscnを開きます(開いていると思います)。
 ファイルシステム内の「res://settings_popup_panel.tscn」をシーン内の「Title」にドラッグアンドドロップして追加します。
 スクリーンショット (91).png
 追加されました。
 ディフォルトでは非表示にしたいので、シーン内のSettingsPopupPanelの右の「目」のアイコンをクリックして、目を閉じたアイコンに変更します。
スクリーンショット (93).png

 「設定」ボタンのシグナルを受信する処理を実装します。
 シーン内の「SettingsButton」を選択した状態で、インスペクタの横のノード/シグナルをクリックしてください。
 BaseButton/pressedシグナルを右クリックして「接続」を実行します。
 スクリーンショット (94).png
 Titleを選択します。受信側メソッドを確認して、「接続」ボタンを押下します。
スクリーンショット (95).png

 res://title.gdに_on_settings_button_pressed()メソッドが追加されました。
 res://title.gdを下記のように修正します。

extends Control

func _on_button_pressed():
	Global.goto_scene("res://game_system.tscn")

func _on_settings_button_pressed():
	$SettingsPopupPanel.open()

 「設定」ボタンが押下されたシグナルを受信したときに、SettingsPopupPanelのスクリプト内のopen()メソッドを実行するようにします。

 次に、SettingsPopupPanelにスクリプトを追加してopen()メソッドを実装します。
 res://settings_popup_panel.tscnを開きます。

 シーン内のSettingsPopupPanelを右クリックして、「スクリプトをアタッチ」を実行します。
 スクリーンショット (96).png
 「作成」ボタンを押下するとファイルが追加されます。
スクリーンショット (97).png

extends PopupPanel

func open():
	popup_centered()

 実行しましょう。
 「設定」ボタンを押下すると、PopupPanelが表示されます。「設定完了」ボタン押下やスライダーの処理は実装していないため、操作はできますが何も起きません。PopupPanelの外をクリックするとPopupPanelの表示が消えるのはPopupPanelの機能です。
 ちなみにPopupPanelが開いているときに「Game Start!」ボタンを押下するとゲームが開始してしまいますが、これは後で修正します。
スクリーンショット (98).png

 PopupPanelを表示するとタイトルの「MyGame」の「M」が消えてしまいます。2023/3/1リリースのGodot4.0にはまだ問題があります。

スライダーの実装

 スライダーを変更すると、発射間隔を変更するようにします。
 0.1から1.0まで、0.1刻みで選択できるようにします。
 
 res://settings_popup_panel.tscnを開きます。

 HSliderを選択した状態でインスペクタのRangeのMin Valueは0.1、Max Valueは1、Stepは0.1にします。
スクリーンショット (103).png

 HSliderを選択した状態でインスペクタの横のノード/シグナルの「drag_ended(value_changed:bool)」を右クリックして、「接続」を実行します。
スクリーンショット (101).png
SettingsPopupPanelを選択して、受信側メソッドを確認後、「接続」ボタンを押下します。
スクリーンショット (102).png

 res://settings_popup_panel.gdに_on_h_slider_drag_endedメソッドが追加されるので下記のように修正しましょう。

extends PopupPanel

func open():
	popup_centered()

func _on_h_slider_drag_ended(value_changed):
	$ControlBaseSize/VBoxContainer/Label.text = "発射間隔 %.1f秒" % $ControlBaseSize/VBoxContainer/HSlider.value
  • func _on_h_slider_drag_ended(value_changed):
     スライダーを操作して、離したときに呼ばれます。

  • $ControlBaseSize/VBoxContainer/HSlider.value
     スライダーの値はHSlider.valueに格納されています。
     0.1~1.0の値が取得できます。

  • "発射間隔 %.1f秒" % $ControlBaseSize/VBoxContainer/HSlider.value
    文字列を編集するためのformatです。
     スライダーの値は浮動小数点なので、%fで受けています。間にある「.1」により小数点第1位まで表示します。

  • $ControlBaseSize/VBoxContainer/Label.text
     Label.textに文字列を設定するとLabelの表示を変更できます。

 実行しましょう。
 スライダーを操作するとLabel表示が変更します。
スクリーンショット (104).png

「設定完了」ボタンを実装する

 「設定完了」ボタン押下でPopupPanelの表示を消すようにします。

 res://settings_popup_panel.tscnを開きます。
 Buttonを選択した状態でインスペクタの横のノード/シグナルの「BaseButton/pressed()」を右クリックして、「接続」を実行します。
スクリーンショット (105).png
SettingsPopupPanelを選択して、受信側メソッドを確認後、「接続」ボタンを押下します。
スクリーンショット (106).png

 res://settings_popup_panel.gdに_on_button_pressedメソッドが追加されました。
 res://settings_popup_panel.gdを開いて下記のように実装します。

extends PopupPanel

func open():
	popup_centered()

func _on_h_slider_drag_ended(value_changed):
	print($ControlBaseSize/VBoxContainer/HSlider.value)
	$ControlBaseSize/VBoxContainer/Label.text = "発射間隔 %.1f秒" % $ControlBaseSize/VBoxContainer/HSlider.value

func _on_button_pressed():
	hide()

 _on_button_pressed()メソッドが呼ばれたときに「hide()」を実行して、PopupPanelの表示を消します。

 設定完了ボタンを押下するとPopupPanelが消える様になりました。
スクリーンショット (107).png

PopupPanel表示中に「Game Start!」ボタンを押せないようにする

 PopupPanel表示中に背景のボタン(Game Start!ボタン、設定ボタン)を押下できないようにします。

SceneTreeを停止する

 res://settings_popup_panel.gdを開きます。
 get_tree()でSceneTree(アクティブなシーン全体)を取得してpausedフラグをtrueにすると、シーンが停止します。
 子ノードも親シーンに従って停止するので、アクティブなシーン全体が停止します。

func open():
	get_tree().paused = true
	popup_centered()

PopupPanelが消えるときにSceneTreeを再開する

 PopupPanelは設定完了ボタン以外にも背景をクリックすると消えるので、PopupPanelが消えるときに発行されるシグナルを利用して、SceneTreeを再開します。

 SettingsPopupPanelを選択した状態でインスペクタの横のノード/シグナルの「Popup/popup_hide()」を右クリックして、「接続」を実行します。
スクリーンショット (108).png
SettingsPopupPanelを選択して、受信側メソッドを確認後、「接続」ボタンを押下します。
スクリーンショット (109).png

res://settings_popup_panel.gdに_on_popup_hideメソッドが追加されるので、下記のように修正します。

func _on_popup_hide():
	get_tree().paused = false

 res://settings_popup_panel.gd全体は下記のようになりました。

extends PopupPanel

func open():
	get_tree().paused = true
	popup_centered()

func _on_h_slider_drag_ended(value_changed):
	print($ControlBaseSize/VBoxContainer/HSlider.value)
	$ControlBaseSize/VBoxContainer/Label.text = "発射間隔 %.1f秒" % $ControlBaseSize/VBoxContainer/HSlider.value

func _on_button_pressed():
	hide()

func _on_popup_hide():
	get_tree().paused = false

PopupPanelは動けるようにする

 SceneTreeを停止してもPopupPanelが動けるようにします。

 SettingsPopupPanelノードを選択してインスペクタの一番下にある「Node/Process/Mode」を「Always」に変更します。
スクリーンショット (110).png

 実行します。
 PopupPanel表示中は背景が停止して、PopupPanelを閉じると背景が動き出すのがわかります。
 またPopupPanel表示中に「Game Start!」ボタンを押下してもゲームが開始しなくなりました。

Controlをまとめる

PopupPanelを表示するとタイトルの「MyGame」の「M」が消える問題について試行錯誤したときにルートノードのTitleとLabel、Button、SettingsButtonの間にControlを親ノードとして追加したものが残っていました。
 あまり意味はないのですが、その22以降にもあるので作業手順として残しておきます。

 res://title.tscnのLabel、Button、SettingsButtonの親Controlを作成します。
 Titleを右クリックして、子ノードを追加からControlを追加します。
 Label、Button、SettingsButtonをドラッグしてControlの子ノードにします。
 Titleの下に移動します。
スクリーンショット (184).png

以上です。

0
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?