ぬーぶのメモ帳

フリーゲームエンジン「Godot」でプログラム経験のない素人の備忘録 最近は色々な動作を考えて試すのが好き。

【Godot】選択メニューを作る

自身で作ったメニューの完成図


「itch.io」と言うインディーズ、個人の方がゲームなどを販売、無料配布してるサイトがあり、中にはオープンソースとしてGodotのプロジェクト自体を公開してる方も
そのプロジェクトを参考にしてオプションを作る事にしました

参考プロジェクト

harmonyhoney.itch.io
※リンク先ページ中辺りにGitHubへのページがあります
ダウンロードしてGodotにインポートするとこのゲームのプロジェクトを呼び出す事が出来ます

参考にしたシーン、スクリプト
※選択メニューの構成で参考

  • StartMenu.tscn & StartMenu.gd (menu)

※内部のシーン切り替えやボリューム調整で参考

  • OptionsMenu.tscn & OptionsMenu.gd (menu→options)
  • Shared.gd (autoload)
  • Volume.gd (menu→options)



メニューリスト作成

まずStartMenu.gdからリストを構成させる部分を探した

  • ○○_list :Labelノード、これが画面にうつりメニューのビジュアルになる
  • ○○_items :配列(array)、この配列が内部でメニュー選択の分岐を担う。また配列内のデータはstring型なので、今回は上listの表示テキストの役割もある
  • cursor :上の配列と、この変数を比べて等しい数値のメニューが実行するように作られる




ready関数から順にプログラムの処理を追っていく

この関数は空のlist, itemsに指定した物を入れるための物


ready関数内でswitch_menu()関数を呼び出し、パラメーターに("main")を指定したことで下画像の関数内matchの分岐"main"と一致 "main" の中のコードが実行される
赤枠の外はメニューのビジュアル強化のためなので省略可能

最後write_menu()でタイトル画面にメニューリストが表示される

上の画像の処理を順番に終えた結果
見本

例えばoptionが選択されていれば-options-のように表示されます



メニュー選択を作る

メニューの表示ができたので次に選択できるようにします
引き続きStartMenu.gdのコードを見ていきます

_input(event)はGodotにあらかじめ用意されている関数
主にキー入力を行った後のレスポンスを設定するのに使われています

画像内の数字の順に追って書いていきます

  • 1. キーボードのCを押すとキャンセルされる、主にquitメニューが表示された時にメインメニューに戻るためのもの
  • 2. Xを押すと決定、3のコードでcursorを変化させ、次に出すmenu_select()関数内の対応したメニューを実行させる
  • 3. メニュー選択のキモ、上下キーでcursor内の数字を増減させる
	var up = event.is_action_pressed("up") or event.is_action_pressed("left")
	var down = event.is_action_pressed("down") or event.is_action_pressed("right")

if up or down:
		cursor = clamp(cursor + (-1 if up else 1), 0, menu_items.size() - 1)

clamp()clamp(現在の数値, 最低値, 最大値)となり、clampを使用するといくら数値を増減させようが最低値、最大値の範囲内の数値で固定されます
つまりcursorは0~呼び出された配列menu_itemsのサイズ内で完結します、便利

ただ配列自体は0から数えますが、.size()は配列内に格納してる数を返すのでメインメニューを例にすると4となります。
上のコードで.size()の右側に-1が無い場合存在しない配列5番目のメニューを引き出せるようになり、それを選択するとエラーになるため上のコードでは-1が記述されています。

またcursor + (-1 if up else 1)三項演算子というif文をコンパクトに使える書式のようです
上のコードを例にするとボタンupが押されると左の-1が、それ以外では右の1がcursorに足され
そして最後にwrite_menu()が実行されるとcursorの増減に合わせてスタートメニューが視覚的にも選択されている事を表現できるようになります。
見本

※実際に操作するとコードがどのように機能しているのかより感じ取れると思うのでぜひ参考にした方のゲームを遊んでみて欲しいです



選択したメニューを実行する

メニューを表示し選択できるようになったのでmenu_select()のコードを読み進めました

  • 1.matchの分岐menu_items[cursor]で呼び出した文字列が一致してmatch内の該当コードが実行される

やっている事は switch_menu()とほぼ同じだけど直接mainとquitを指定するのではなく、変数で変更可能なため柔軟になっているように見えました


  • 2. 1で一致したコードを実行、2は全てStartMenuとは別のシーンに切り替わる

Sharedは自動読み込みと呼ばれる機能を使いプロジェクト内全てのスクリプトで参照できる状態になっています。
2つ上の画像ではShared内に存在するwipe_scene()という関数を呼び出していますね。
複数のシーンで使用するようなコードや変数を登録すると非常に便利かも。

自動読み込みについてはこちら
【Godot】自動読み込みの設定方法 - ぬーぶのメモ帳



  • 3. quitメニューはStartMenu内に既に配置されて非表示になっている

その為2のようにシーン切り替えではなくswitch_menu()が使用されています

switch_menu("quit")が実行されるとラベルノードと配列の中身がmainからquitに置き換わり_input(event)write_menu()はQuitメニューのYESとNOの選択に変化する
見本

quit_itemsの中身が["yes", "no"]なのでmenu_items[cursor]で呼び出せる文字列もこの二種類に変化
memu_select()のmatch文で実行できるものもその二つのみになる
そしてNOを選択した場合またswitch_menu("main")でメインメニューの操作に戻る

自分が作ったメニューもポーズメニューとして採用したかったのでほぼ3の方法を参考にしました。
(ほぼというより再現するだけの腕がないとも)

参考にして動作までこぎつけた物



■ まとめ

プログラムの上達する方法の一つとして、プログラムがどのように意図して動いているか読み解く事と教えて貰った事があります
その点で言うと完成されたゲームは最高の教材で、それを参考にすることは非常に勉強になりこういった方々には感謝でいっぱいです
他の機能でも参考にできる部分が多く色々な機能を真似てみたいと感じました