今回は、円形のプログレスバーの作り方を紹介する。プログレスバーを、一般的な縦向きや横向きではなく、円形にすることによって、画面上のちょっとしたアクセントにもなるので使い所があれば是非参考にしていただきたい。また、チュートリアルの最後のほうで、円形以外の形状(例えばハート型)のプログレスバーもサンプルとしていくつか紹介するのでそちらも興味があればぜひご覧いただきたい。

このチュートリアルで最後にできあがるプロジェクトのファイルはGitHubリポジトリ に置いている。.zipファイルをダウンロードしていただき、「End」フォルダ内の「project.godot」ファイルを Godot Engine でインポートしていただければ、直接プロジェクトを確認していただくことも可能だ。

Environment
Godot のバージョン: 3.4.4
コンピュータのOS: macOS 11.6.5

Basic Articles
以下の記事もお役立てください。
Godot をダウンロードする
Godot のプロジェクトマネージャー
Godot の言語設定



準備

円形プログレスバーの画像を用意する

お使いのコンピュータに Photoshop や GIMP などの描画アプリがあれば、そちらをお使いいただければOKだ。描画アプリの使い方の詳細はここでは割愛させていただく。難しい場合はググってみてほしい。

真ん中をくり抜いた円の図形を作成する。この時、円の色は白にする。理由は Godot エディタ上で色の設定が簡単にできるだからだ。白以外の部分は透過させた状態にしておく。画像サイズを縦横 300 px にして png ファイルとして保存する。

ちなみに私の場合は、Mac の「Keynote」アプリ(Windows PC の PowerPointのようなスライドショー作成アプリ)で作成した図形オブジェクトをクリップボードにコピーして、「プレビュー」アプリを起動して、「クリップボードから新規作成」して、png として保存した。

この手順を省略したい場合は、下の画像をブラウザから直接ダウンロードしていただければと思う(背景が白いと画像が同化して何もないように見えるかもしれない…)。
circular progress bar image


新規プロジェクトを作成する

それでは Godot Engine を立ち上げて、新規プロジェクトを作成しよう。プロジェクトの名前はあなたのお好みで決めていただいてOKだ。もし思いつかなければ「Circular Progress Bar」としておこう。


用意した画像をインポートする

ファイルシステムドックで先にリソースフォルダ直下(res://)に「Textures」フォルダを作成する。そこにさきほど用意した円形の画像をドラッグ&ドロップしてインポートする。ファイル名は「CircularProgressBar.png」としておく(ファイルパスは res://Textures/CircularProgressBar.png )。



シーンを作る

まずは CircularProgressBar シーンを作ろう。

  1. 「シーン」メニュー>「新規シーン」を選択する。

  2. 「Control」クラスのノードをルートノードとして選択したら、名前を「CircularProgressBar」に変更する。

  3. 一旦ここでシーンを保存する。ファイルパスを「res://CircularProgressBar.tscn」としてシーンを保存する。

  4. 続けて「CircularProgressBar」ルートノードに「TextureProgress」ノードを追加する。

  5. さらに「CircularProgressBar」ルートノードに「Label」ノードを追加する。

シーンツリーは以下のようになったはずだ。
scene tree



ノードを編集する

CircularProgressBar (Control) ルートノード

  1. 2D ワークスペースで、ツールバー>「レイアウト」から「全画面」を選択する。
    CircularProgressBar - 2D workspace

TextureProgress ノード

  1. インスペクターにて、「Fill Mode」プロパティの値を「Clockwise」にする。これは時計回りにぐるりとプログレスバーが進行するスタイルだ。このプロパティはプログレスバーの形状に合わせて適切に選択することを心がけたい。例えば、もしハート型のプログレスバーなら下から上にバーが進行する「Bottom to Top」が相応しいだろう。
    TextureProgress - Fill Mode
  2. 「Texture」>「Under」プロパティに先にインポートしておいた画像リソース「res://Textures/CircularProgressBar.png」をドラッグして適用しよう。
  3. 「Texture」>「Progress」プロパティも同様にする。
    TextureProgress - Texture
  4. 「Tint」>「Under」プロパティの色を #000000 (黒) にする。
  5. 「Tint」>「Progress」プロパティは、味気ないが、ひとまずデフォルトの #ffffff (白) のままにしておく
    TextureProgress - Tint
  6. 2D ワークスペースで、ツールバー>「レイアウト」から「中央」を選択する。
    TextureProgress - 2D workspace

Label ノード

  1. インスペクターにて「Text」プロパティには初期値として適当に「100%」などと入力しておく。
  2. 「Align」プロパティを「Center」にする。
  3. 「Valign」プロパティも「Center」にする。
    Label - Text, Align, Valign

Open Font Package をダウンロードする

「Label」ノードにフォントを設定したいので、エディタ上部のタブで「Asset Library」に切り替えて「Open Font Package」をダウンロードしよう。

  1. 上部の「AssetLib」タブをクリックして「Asset Library」に切り替える。
  2. 「font」で検索するなどして「Open Font Package」を見つけたら、それをクリックする。
    AssetLib
  3. 「Download」をクリックする。
    AssetLib - Open Font Package download
  4. 必要なフォントファイルだけチェックして「Install」をクリックする。今回は「Xolonium-Bold.ttf」を選択。
    AssetLib - Open Font Package install
  5. ファイルシステムドックに表示されれば完了だ。
    AssetLib - Open Font Package in file system

Label ノード(続き)

  1. インスペクターに戻って、「Theme Overrides」>「Fonts」>「Font」プロパティに「新規 DynamicFont」を適用する。
  2. 適用した「DynamicFont」リソースを展開し、「Font」>「Font Data」プロパティにインストールしたばかりのフォントリソース「res://fonts/xolonium/xolonium-fonts-4.1/ttf/Xolonium-Bold.ttf」を適用する。
  3. 同じく「DynamicFont」リソースの「Settings」>「Size」プロパティを 40 にする。
  4. 同じく「DynamicFont」リソースの「Settings」>「Outline Size」プロパティを 4 にする。
  5. 少し戻って、「Theme Overrides」>「Colors」>「Font Color」を有効にして、色は #000000 (黒) のままにしておく。
    Label - Theme Overrides
  6. 2D ワークスペースにて、ツールバーの「レイアウト」から「中央」を選択する。
    Label - 2D workspace


スクリプトをアタッチしてコーディングする

上下矢印キーでプログレスバーを更新させる

ではキーボードの上下矢印キーでプログレスバーの値が変化するようにスクリプトをコーディングしていこう。「TextureProgress」ノードの「Value」プロパティの値を変化させることで、「Texture」>「Progress」プロパティの表示範囲も連動してくれる。

  1. 「CircularProgressBar」ルートノードにスクリプトをアタッチする。ファイル名を「Progress.gd」としてファイルパスは「res://Progress.gd」とする。
  2. エディタが開いたら、以下のように編集する。
###Progress.gd###
extends Control

# TextureProgressノードの参照
onready var progress_bar = $TextureProgress
# Labelノードの参照
onready var label = $Label


func _ready():
    # TextureProgressノードのvalueプロパティを0にリセットする
	progress_bar.value = 0


func _process(delta):
    # 入力操作を処理するメソッドを呼び出す
	get_input()
    # LabelノードのTextプロパティを更新するメソッドを呼び出す
	update_label()


# 入力操作を処理するメソッド
func get_input():
    # もし上矢印キーを押したら
	if Input.is_action_pressed("ui_up"):
        # TextureProgressノードのValueプロパティの値に1をプラス
		progress_bar.value += 1
    # もし下矢印キーを押したら
	if Input.is_action_pressed("ui_down"):
        # TextureProgressノードのValueプロパティの値から1をマイナス
		progress_bar.value -= 1

# Labelノードのtextプロパティを更新するメソッド
func update_label():
    # TextureProgressノードのValueプロパティの値に%をつけて表示する
	label.text = str(progress_bar.value) + "%"

ではプロジェクトを実行して、上下矢印キーでプログレスバーの値を変化させてみよう。初めてプロジェクトを実行する場合は、メインシーンの選択を促すダイアログにて、現在のシーンをメインシーンとして設定すればOKだ。
run project


プログレスバーの値に連動して色を変化させる

モノクロだと味気ないので、プログレスバーの色も変化させてみよう。今度は、プログレスバーの値の変化に合わせて、徐々にプログレスバーの色も変化させたい。「TextureProgress」ノードの「Value」プロパティの値の更新をより細かくするために「Step」プロパティの値を小さくしておこう。今回は 0.1 に設定する。
TextureProgress - step

スクリプトを以下のように編集する。

###Progress.gd###
extends Control

# TextureProgressノードのtint_progressプロパティ(Colorクラス)の...
# h, s, vプロパティの始まりと終わりの値を指定するプロパティ(HSVで色を指定する)
export (float) var h_start = 0.0
export (float) var h_end = 0.45
export (float) var s_start = 0.3
export (float) var s_end = 1.0
export (float) var v_start = 0.3
export (float) var v_end = 1.0

onready var progress_bar = $TextureProgress
onready var label = $Label


func _ready():
	progress_bar.value = 0


func _process(delta):
	get_input()
	update_label()
    # 追加:色相を更新するメソッドを呼び出す
	update_color()


func get_input():
	if Input.is_action_pressed("ui_up"):
		progress_bar.value += 1
	if Input.is_action_pressed("ui_down"):
		progress_bar.value -= 1


func update_label():
	label.text = str(progress_bar.value) + "%"

# 追加:色相を更新するメソッド
func update_color():
    # Valueプロパティの値がminからmaxへ変化するのに合わせてプログレスバーの色相を変化させる
	progress_bar.tint_progress.h = range_lerp(progress_bar.value, progress_bar.min_value, progress_bar.max_value, h_start, h_end)
    # Valueプロパティの値がminからmaxへ変化するのに合わせてプログレスバーの彩度を変化させる
	progress_bar.tint_progress.s = range_lerp(progress_bar.value, progress_bar.min_value, progress_bar.max_value, s_start, s_end)
    # Valueプロパティの値がminからmaxへ変化するのに合わせてプログレスバーの明度を変化させる
	progress_bar.tint_progress.v = range_lerp(progress_bar.value, progress_bar.min_value, progress_bar.max_value, v_start, v_end)

それでは改めてプロジェクトを実行してみよう。
run project

色の変化があると美しいような気はするが、あくまでゲームに合わせたデザインを心掛けたい。



さまざまな形状のプログレスバー

ここまで実装してみてお気づきかもしれないが、プログレスバーはその形状となる画像リソースさえあれば、割と応用が効くのだ。

ここまでに作成した「CircularProgressBar.tscn」を複製して、少しプロパティを変更するだけで、色々なパターンのプログレスバーを比較的簡単に作ることができる。いくつかのサンプルを用意したのでご覧いただきたい。


ハート型のプログレスバー

ルートノードの「Script Variables」の各プロパティ。色相は紫から赤へ。彩度と明度は最初から高め。
HeartProgress - Script Variables

「TextureProgress」ノードの「Fill Mode」プロパティ。下から上に進行。
HeartProgress - Fill Mode

「TextureProgress」ノードの「Textures」>「Under」/「Progress」プロパティ。ハートのテクスチャを適用。
HeartProgress - Textures

シーンを実行。
run scene - HeartProgress


ドクロ型のプログレスバー

ルートノードの「Script Variables」の各プロパティ。色相は緑から青へ。彩度は低めに抑える。
SkullProgress - Script Variables

「TextureProgress」ノードの「Fill Mode」プロパティ。中央から上下両方向へ。
SkullProgress - Fill Mode

「TextureProgress」ノードの「Textures」>「Under」/「Progress」プロパティ。ドクロ型のテクスチャを適用。
SkullProgress - Textures

シーンを実行。
run scene - SkullProgress


フラスコのプログレスバー

このサンプルでは「Progress.gd」スクリプトを少し編集する。

###Progress.gd###

# 追加: バーの限界値(初期値はmax_valueに合わせて100)
export (float) var value_limit = 100

# 入力操作処理のメソッド
func get_input():
	if Input.is_action_pressed("ui_up"):
		progress_bar.value += 1
        # 追加:バーの限界値までしかバーを進行させない
		progress_bar.value = min(progress_bar.value, value_limit)
	if Input.is_action_pressed("ui_down"):
		progress_bar.value -= 1

# Labelノードのtextプロパティを更新するメソッド
func update_label():
    # 追加:Labelの%をバーの限界値を1として計算
	var actual_value = floor(progress_bar.value / value_limit * 100)
	label.text = str(actual_value) + "%"

ルートノードの「Script Variables」の各プロパティ。ここで新たに追加したプロパティ「Value Limit」の値を 72.5 に変更している。これがちょうどこのあと適用するフラスコのテクスチャ画像に描かれている一番上の目盛りに合う値だ。
FrascoProgress - Script Variables

「TextureProgress」ノードの「Fill Mode」プロパティ。下から上へ。
FrascoProgress - Fill Mode

「TextureProgress」ノードの「Textures」>「Under」/「Progress」プロパティ。フラスコのテクスチャを適用。
FrascoProgress - Textures

シーンを実行。上記の調整で、フラスコのテクスチャの一番上の目盛りでバーの進行が止まる。
run scene - FrascoProgress


脳みそのプログレスバー

ルートノードの「Script Variables」の各プロパティ。
BrainProgress - Script Variables

「TextureProgress」ノードの「Fill Mode」プロパティ。
BrainProgress - Fill Mode

「TextureProgress」ノードの「Textures」>「Under」/「Progress」プロパティ。
BrainProgress - Textures

「TextureProgress」ノードの「Radial Fill」>「Fill Degrees」を180にして、進行バーの展開できる角度を最大 180° とした。進行バーの回転の中心を脳みそのテクスチャのすぐ下までずらすために「Center Offset」の y の値を 130 とした。
BrainProgress - Textures

シーンを実行。
run scene - BrainProgress


ここまでに作ったものを1つのシーンにまとめてみる。
new scene - AllProgress

メインシーンの設定を変更してプロジェクトを実行するとこんな感じだ。
run project - AllProgress



おわりに

今回は円形プログレスバーやその他の形状のプログレスバーの作成方法について紹介した。ポイントは以下の通りだ。

  • プログレスバーの形状を決めるのはテクスチャ用の画像リソース。
  • 形状に合わせて「TextureProgress」ノードの「Fill Mode」プロパティでバーの進行方向を設定する。
  • スクリプトで「TextureProgress」ノードの「Value」プロパティの値を変化させることで、進行バーも連動させられる。
  • スクリプトで「TextureProgress」ノードの「Tint」>「Progress」プロパティの色を変化させることで、バーの進行状況に合わせて色を変化させられる。

参考


UPDATE
2022/08/06 Header の構成とサイズを若干修正