【Godot】謎解きゲームで使えそうなアナログ時計UI

今回は Escape the room game (脱出ゲーム) など、謎解きゲームで使えそうなアナログ時計UIの実装方法について解説します

完成プロジェクト

今回使用するプロジェクトを添付しておきます

なお、プロジェクト内に含まれる時計の画像(clock.png)は「CLIP STUDIO ASSETSのシンプル壁掛け時計(可動)」からお借りしているものなので、個別に使用する場合は、別の画像素材を使うようお願いします(ソースコードは自由に使って問題ありません)

アナログ時計UIの作り方

ということでプロジェクトファイルの解説です

アナログ時計のパーツ

アナログ時計UIは以下のパーツで構成されています

  • 背景の時計(時計の文字盤)
  • 長針(分を表す)
  • 短針(時を表す)

秒針は、単位が細かすぎて謎解きではあまり使わなそうなので、今回は省略しました

背景は画像を用意するだけなのですが、時計の針の考え方が少し特殊なのでそのあたりを説明します

針UIの作り方

針の回転の中心は、針の根本となります

そのため回転の中心を時計の中心になるように設定する必要があります

今回の例では「ColorRect」を時計の針として使用するので、親ノードを「Node2D」にすることで、回転をやりやすくしています。もし Spriteノード を使用する場合は、直接スプライトの中心を移動させても良いと思います

時間の扱い

今回の時計の最小単位は「分」なので、内部的な値は「分」を基準に動作しています。

“clock_time” が内部的な時間の単位とすると、”clock_time” の 60 の剰余が「分」となり、”clock_time” を 60で割って 12の剰余を求めたものが「時」となります。

	# 分・秒に変換する
	var minute = fmod(clock_time, 60)
	var hour = fmod(clock_time/60, 12)

時計が一周したときの処理

「0時0分から11時55分になった」場合や「11時55分から0時0分になった」場合には丸め処理が必要となります。

# 最大時間
const MAX_TIME = 12 * 60

...

# 時間を増やす
func _on_ButtonRight_pressed() -> void:
	next_clock_time += CLOCK_UNIT
	if next_clock_time >= MAX_TIME:
		# 最大時間を超えたら折返し
		clock_time -= MAX_TIME
		next_clock_time -= MAX_TIME

# 時間を減らす
func _on_ButtonLeft_pressed() -> void:
	next_clock_time -= CLOCK_UNIT
	if next_clock_time < 0:
		# マイナスになったら折返し
		clock_time += MAX_TIME
		next_clock_time += MAX_TIME

というのも、内部的には「0」から「12 * 60」が有効な時間の範囲となるためです。

上記処理では、その範囲外となったら有効な範囲に丸めています。