7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Godot 4.x】2D脱出ゲームを作ってみる⑤〜Claude CodeとMCPで背景の特定領域をタップしてフェード遷移する〜

7
Last updated at Posted at 2026-07-01

はじめに

この記事は、Godot 4.xで脱出ゲームを作る連載の第5回です。

前回(第4回)ではタイトル画面からメイン画面への遷移を実装しました。今回はメイン画面の背景に描かれた郵便受けをタップすると、フェードアウト→フェードインで別シーンに切り替わる仕組みを実装します。

この記事で作るもの

  • 背景画像の特定領域だけに当たり判定を設ける(ホットスポット)
  • タップ時にフェードアウトしてシーン遷移する
  • 遷移先シーンでフェードインする

前提条件

  • Claude Code + godot-mcpのセットアップ完了(第2回参照)
  • scenes/main.tscnassets/images/bg_stage_001.png が配置済み(第4回参照)
  • 遷移先で使用する assets/images/bg_stage_002.png が配置済み

今回用意した画像(ChatGPT作)
bg_stage_002.png

Claude Code

下記プロンプトのみで実装できました(実装された)

プロンプト:
main.tscnでbg_stage_001.pngの左側の郵便受けの領域をタップしたら、post.tscnにフェードイン・フェードアウトで切
り替えてbg_stage_002.pngを表示

設計方針

脱出ゲームではシーン遷移のたびに「ブツ切り感」が出がちです。今回はフェードアウト→フェードインで自然に繋ぐ演出を加えます。

ただし、トランジション専用のシングルトン(Autoload)など大掛かりな仕組みは作りません。「出るシーンが自分をフェードアウト」「入るシーンが自分をフェードイン」 という最小限のパターンを各シーンに持たせるだけで、シンプルな行き来は十分に実現できます。


1. 当たり判定の仕組みを理解する

実装に入る前に、今回使う当たり判定の考え方を整理します。

Area2D + CollisionShape2D でも当たり判定は作れますが、今回はControlノードを使います。理由は座標系にあります。

背景画像(TextureRect)を原点(0, 0)基準で敷いていて、画像サイズとビューポートサイズがほぼ一致しているため、画像のピクセル座標をそのままUIノードの座標として使える構成になっています。Controlノードであれば offset_left などに画像のピクセル座標をそのまま指定でき、余計な座標変換を考えずに済みます。

また、ノードツリーの後方に配置されたノードほど入力判定が先に来るというGodotの仕様を活用します。TextureRect(背景)の後ろにControl(当たり判定)を追加することで、郵便受けの矩形範囲だけ入力を先取りできます。


2. main.tscnにホットスポットを追加する

2-1. Claude Codeへの指示

main.tscnのBgStage001(TextureRect)の後ろに、MailboxAreaという名前のControlノードを追加して。
郵便受けの位置(offset_left=280, offset_top=370, offset_right=540, offset_bottom=830)に配置し、
ホバー時に指カーソルが表示されるようにして。

2-2. 生成された差分

Update(escape-game-sample/scenes/main.tscn)
  ⎿  Added 7 lines
[node name="MailboxArea" type="Control" parent="."]
layout_mode = 0
offset_left = 280.0
offset_top = 370.0
offset_right = 540.0
offset_bottom = 830.0
mouse_default_cursor_shape = 2

2-3. ポイント解説

ノードの配置順が入力判定の優先順位になる

Godotはノードツリーの後方のノードほど入力を先に受け取ります。BgStage001(背景)の後ろにMailboxAreaを追加することで、郵便受けの範囲内のタップはMailboxAreaが先に受け取れます。

mouse_default_cursor_shape = 2

カーソル形状をCURSOR_POINTING_HAND(指カーソル)に設定します。郵便受けにカーソルを乗せると指カーソルに変わり、「ここはタップできる」ことを視覚的に伝えられます。

当たり判定の座標

今回の構成では背景画像のピクセル座標がそのままノードの座標になります。郵便受けが画像上のどの範囲にあるかをピクセル単位で確認し、offset_left/top/right/bottom にそのまま入力するだけです。


3. タップ検知とフェードアウトの実装

3-1. Claude Codeへの指示

scripts/main.gdを作成して。
MailboxAreaをタップしたら、シーン全体を0.4秒でフェードアウトしてからres://scenes/post.tscnに遷移して。
@exportでフェードアウト時間を調整できるようにして。

3-2. 生成されたスクリプト(main.gd)

extends Control

@export var fade_out_duration: float = 0.4

func _ready() -> void:
    $MailboxArea.gui_input.connect(_on_mailbox_area_gui_input)

func _on_mailbox_area_gui_input(event: InputEvent) -> void:
    if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
        _go_to_post()

func _go_to_post() -> void:
    var tween := create_tween()
    tween.tween_property(self, "modulate:a", 0.0, fade_out_duration)
    tween.tween_callback(_on_fade_out_complete)

func _on_fade_out_complete() -> void:
    get_tree().change_scene_to_file("res://scenes/post.tscn")

3-3. ポイント解説

gui_input シグナルでタップを検知

Controlノードにはgui_inputシグナルがあり、そのノードの矩形範囲内でのマウス・タッチ入力を受け取れます。Area2Dinput_eventと似た仕組みですが、Controlノードはビューポートの2D空間ではなくUI空間で動作するため、今回の構成に適しています。

タッチ入力もInputEventMouseButtonでカバーできる

Godotはデフォルトでタッチイベントをマウスイベントとしてもエミュレートします。InputEventMouseButtonの判定だけでタッチ端末にも対応できます。

modulate:aをルートノードに適用する

self(Mainノード)のmodulate:aを0にすることで、子ノード全体がまとめてフェードアウトします。スプラッシュ画面(第3回)でも同じパターンを使いましたが、ルートノードに適用することで個別ノードを列挙せずに済みます。

tween_callback で完了後の処理を繋ぐ

tween_callback() はTweenのステップとして「関数の呼び出し」を登録できます。フェードアウト完了直後にシーン遷移が実行されるため、アニメーションが終わる前に画面が切り替わる問題が起きません。


4. 遷移先シーン(post.tscn)の作成

4-1. Claude Codeへの指示

scenes/post.tscnを作成して。
bg_stage_002.pngをbg_stage_001.pngと同じようにフルスクリーン表示して。
シーン開始時に0.4秒でフェードインするようにして。
scripts/post.gdも作成して。

4-2. 生成されたシーン(post.tscn)

[gd_scene format=3]

[ext_resource type="Texture2D" path="res://assets/images/bg_stage_002.png" id="1_bg"]
[ext_resource type="Script" path="res://scripts/post.gd" id="2_post"]

[node name="Post" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("2_post")

[node name="BgStage002" type="TextureRect" parent="."]
layout_mode = 0
offset_right = 1920.0
offset_bottom = 1083.0
texture = ExtResource("1_bg")
expand_mode = 1
stretch_mode = 1

4-3. 生成されたスクリプト(post.gd)

extends Control

@export var fade_in_duration: float = 0.4

func _ready() -> void:
    modulate.a = 0.0
    var tween := create_tween()
    tween.tween_property(self, "modulate:a", 1.0, fade_in_duration)

4-4. ポイント解説

フェードインの実装はスプラッシュ画面(第3回)で使ったパターンとまったく同じです。

modulate.a = 0.0          # 透明な状態からスタート
tween_property  1.0      # 不透明まで補間

この「出るシーンでフェードアウト・入るシーンでフェードイン」というパターンを各シーンに持たせることで、トランジション専用のAutoloadを作らずにシンプルなフェード遷移が実現できます。


5. 動作確認

F5 でゲームを実行し、以下の流れで動作すれば成功です。

  1. タイトル画面から「Tap to Start」でメイン画面に遷移する
  2. 郵便受けの範囲にカーソルを乗せると指カーソルに変わる
  3. 郵便受けをクリック/タップすると画面がフェードアウトする
  4. post.tscnフェードインしながら表示される

うまく動かない場合

症状 確認ポイント
郵便受けをタップしても反応しない MailboxAreaのoffset座標が郵便受けの範囲に合っているか。main.gdがMainノードにアタッチされているか
指カーソルに変わらない mouse_default_cursor_shape = 2 が設定されているか
フェードせずにブツ切り遷移する main.gd_go_to_post() 内で tween_callback が正しく設定されているか
post.tscnでフェードインしない post.gd_ready()modulate.a = 0.0 からスタートしているか

成果物

スタート地点から、左の郵便受けをタップ!
スクリーンショット 2026-07-01 18.49.02.png

郵便受けにフェードして近接(post.tscn)

スクリーンショット 2026-07-01 18.49.15.png

まとめ

今回はClaude Code + godot-mcpを使って以下を実装しました。
プロンプト1回だけでこの成果、お得な感じです!

やったこと ポイント
ホットスポット(当たり判定) TextureRectの後ろにControlを配置してノードツリー順で入力を先取り
指カーソル mouse_default_cursor_shape = 2 で視覚的フィードバック
タップ検知 gui_inputシグナル + InputEventMouseButton
フェードアウト→シーン遷移 tween_property + tween_callback で完了後に遷移
フェードイン modulate.a = 0.0 からスタートしてtween_propertyで補間
トランジション設計 各シーンが「自分のフェード」を持つ最小限パターン

今回のフェードパターン(出るシーンでフェードアウト・入るシーンでフェードイン)は、連載全体を通して使い回せる汎用的な設計です。スプラッシュ画面(第3回)で初めて登場し、今回で本格的に活用しました。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?