※この連載の全ての記事は、タグ「ビッグカツ」の検索一覧から探すことができます。
※この連載で作ったゲームは「BigBreakOut(ゲームの作り方の記事付き) | フリーゲーム投稿サイト GodotPlayer」でプレイできます。
昔から人気の駄菓子「ビッグカツ」のフリー素材画像が公開されたので、無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 を使って、ビッグカツ画像を使ったブロック崩しを作成します。
「ビッグカツブロック崩し」作成の第15回では、ボールがぶつかった際に消されるブロック群を配置して、そのブロック群が全て消えたらそのレベルをクリアしたと判定するスクリプト例を紹介します。
ノードは、下位に子ノードを追加でき、その子ノードの個数を数えられる機能を利用します。
![](https://compota-soft.work/wp1/wp-content/uploads/2024/09/GodotEngine4.3-公式サイトの一部-20240911.png)
※ GodotEngine 4.3 を使用しています。.NET 版ではありません。
※スクリプトは自己責任でご使用ください。
前回の記事
前回は、ゲームで流す BGM などの音声ファイルから音を再生する際のループ設定の方法と、フォルダでファイルシステムドックのファイルを整理する手順を紹介しました。
ブロックの配置と残りを数えるための上位ノードの作成
以下の記事で、ボールにぶつかると消えるブロックのシーンを作成して、それをステージのシーンに子ノードとして複数配置しました。
これらのブロックが全て消えたらクリアです。
その具体的な判定処理のために、ブロックノードだけを持つ上位ノードを作成して、そのノードの子ノードの個数を数えて 0 になったらクリアと判定します。
そのために、Stage ルートノードを右クリックして表示されるメニュー「子ノードを追加」を選択して、ブロックノードを持たせるノード Layout1 を作成します。
![Godot4 ビッグカツブロック崩し クリア判定のためにブロックだけを持つ上位ノードを作成1](https://compota-soft.work/wp1/wp-content/uploads/2024/12/Godot4-ビッグカツブロック崩し-クリア判定のためにブロックだけを持つ上位ノードを作成1.png)
Node クラスを選択して「作成」ボタンを押します。
クラスを Node としたのは、シーンに配置するための基本のクラスだからです。そして、子ノードの個数を数える関数 get_child_count が実装されているからです。
![Godot4 ビッグカツブロック崩し クリア判定のためにブロックだけを持つ上位ノードを作成2](https://compota-soft.work/wp1/wp-content/uploads/2024/12/Godot4-ビッグカツブロック崩し-クリア判定のためにブロックだけを持つ上位ノードを作成2.png)
作成したノードを Layout1 にリネームして、その Layout1 ノードにすべてのブロックのノードをマウスドラッグで移動させて、Layout1 の子ノードにします。
※ノード名の変更は、シーンドックでノードを右クリックして表示されるメニュー「名前を変更」などから行います。
![Godot4 ビッグカツブロック崩し クリア判定のためにブロックだけを持つ上位ノードを作成3](https://compota-soft.work/wp1/wp-content/uploads/2024/12/Godot4-ビッグカツブロック崩し-クリア判定のためにブロックだけを持つ上位ノードを作成3.png)
クリアの判定の実装例
クリア判定や、ゲームのプレイ状況を管理するためのスクリプトを Stage ルートノードに割り当てます。
シーンドックで、Stage ルートノードを選択してから右上の + のアイコンの「選択したノードに新規または既存のスクリプトをアタッチする」ボタンを押します。
![Godot4 ビッグカツブロック崩し ゲーム進行を管理するスクリプトをStageノードに設定1](https://compota-soft.work/wp1/wp-content/uploads/2024/12/Godot4-ビッグカツブロック崩し-ゲーム進行を管理するスクリプトをStageノードに設定1.png)
stage.gd スクリプトを作成します。
![Godot4 ビッグカツブロック崩し ゲーム進行を管理するスクリプトをStageノードに設定2](https://compota-soft.work/wp1/wp-content/uploads/2024/12/Godot4-ビッグカツブロック崩し-ゲーム進行を管理するスクリプトをStageノードに設定2.png)
作成した Stage ルートノードに割り当てられた stage.gd を以下のスクリプトで上書きします。
スペースキーを押すとボールが動き出し、すべてのブロックを消すとクリア判定のメッセージが下パネルの出力に標準出力されます。
※詳細は、スクリプトのコメントを参照してください。
extends Node2D
class_name Stage
## ゲーム進行を管理するクラスです。
## 制作過程であり、直接 Layout ノードにブロック群を配置して個数を計測しています。
## この後の記事では、複数の面を実装するために、面ごとにレベルシーンを保存して、それをこのメンバの配列に割り当てます。
## ボールの初期位置です。
## $Ball の最初の位置を初期位置として保存して、各レベルの始まりにその位置にボールを配置します。
var ball_start_position: Vector2
## 現在読み込んでいるレベルのシーンのインスタンス(子ノード)です。
var current_level_scene:Node = null
## 現在のゲームのプレイ段階の種類です。
## タイトルシーンと異なり、ゲームオーバーやゲームクリアはプレイ時の画面の上に UI を表記するので
## シーンを切り替えずに、ラベルやボタンなどを必要に応じて表示するため、同一のシーン内でフェーズを変えて
## 見た目や入力による反応を切り替えます。
enum Phase
{
## レベルのプレイ開始直前のフェーズです。
LevelReady,
## レベルプレイ中のフェーズです。ボールを失うと GameOver に移行します。
Playing,
## レベルをクリアした直後のフェーズです。
## 次の面がなければすぐに GameClear に移行します。
## 次の面があれば、 Next ボタンをクリック後、次の面があれば StageStart に移行します。
LevelClear,
## ゲームオーバーのフェースです。タイトルボタンをクリックすると Title に移行します。
GameOver,
## ゲームクリアのフェーズです。タイトルボタンをクリックすると Title に移行します。
GameClear,
}
## 現在のゲームの進行段階、フェーズを表します。
var current_phase = Phase.LevelReady
## Called when the node enters the scene tree for the first time.
## ノードが初めてシーン ツリーに入るときに呼び出されます。
func _ready():
# ボールの初期位置を保存します。
ball_start_position = $Ball.global_position
# 現在のレベルシーンを設定します。(仮組として直接シーンに配置した Layout1 ノードを割り当てます)
current_level_scene = $Layout1
return
## Called every frame. 'delta' is the elapsed time since the previous frame.
## フレームごとに呼び出されます。 delta は、前のフレームからの経過時間です。
## delta を使用しない場合は warning が出ないように _delta とリネームします。
func _process(_delta):
# プレイ中
if current_phase == Phase.Playing:
# レベルシーンの持つ子ノード(ブロック)が全て消えたらレベルクリアに移ります。
if current_level_scene.get_child_count() < 1:
on_level_clear()
# Enter / Space キー / マウス左ボタン(クリック) が押された直後の場合
if Input.is_action_just_pressed("ui_accept") or Input.is_action_just_pressed("ui_click"):
#if Input.is_action_just_pressed("ui_accept") or Input.is_action_just_pressed("ui_right") or Input.is_action_just_pressed("ui_left"):
# ゲームの進行状況によって、入力があった際の挙動を変えます。
match current_phase:
Phase.LevelReady:
# プレイ前の状態で入力されたら、ボールを動かして、プレイを開始します。
on_playing()
Phase.Playing:
# プレイ中はクリックされても反応しません。
pass
_:
# 上記以外
printerr("想定していない Phase の列挙子の値です。")
# TODO: Ball が下に落ちた場合の処理を追加
## 現在のレベルのプレイ開始時に呼び出されます。
func on_playing():
# ゲームの進行状況を更新します。
current_phase = Phase.Playing
print("current_phase = Phase.Playing")
# ボールの一時停止を解除します。
$Ball.is_pause = false
return
## 現在のレベルをクリアした際に呼び出されます。
func on_level_clear():
# ゲームの進行状況を更新します。
current_phase = Phase.LevelClear
print("current_phase = Phase.LevelClear")
# ボールを一時停止します。
$Ball.is_pause = true
return
テスト
F6 キーで、開いているステージのシーンを実行し、スペースキー(クリックや Enter キーでも可)を押すとボールが動き出し、エディタの下パネルの出力に、スクリプトの on_playing 関数の print 文の “current_phase = Phase.Playing” が出力されました。
その後、ブロックを全て消した直後に on_level_clear 関数の print 文の “current_phase = Phase.LevelClear” が出力され、クリア判定が正しく行われたことを確認できました。
![Godot ビッグカツブロック崩し 全てのブロックが消えるとクリア判定されました.SS1](https://compota-soft.work/wp1/wp-content/uploads/2024/12/Godot-ビッグカツブロック崩し-全てのブロックが消えるとクリア判定されました.SS1_.png)
![Godot ビッグカツブロック崩し 全てのブロックが消えるとクリア判定されました.SS2](https://compota-soft.work/wp1/wp-content/uploads/2024/12/Godot-ビッグカツブロック崩し-全てのブロックが消えるとクリア判定されました.SS2_.png)
まとめ
「ビッグカツブロック崩し」作成の第15回では、ボールがぶつかった際に消されるブロック群を配置して、そのブロック群が全て消えたらそのレベルをクリアしたと判定するスクリプト例を紹介しました。
ノードは、下位に子ノードを追加でき、その子ノードの個数を数えられる機能を利用しました。
参照サイト Thank You!
- Godot Engine – Free and open source 2D and 3D game engine
- Xユーザーのビッグカツといか姿フライのすぐる【公式】さん: 「使いどころは思いつきませんが、フリー素材としてどうぞご自由にお使いくださいませ! https://t.co/8F9q3hS02b」 / X
- しょかきうたげ【フリーフォント版あり】 – ぼんのう堂 – BOOTH
- Node — Godot Engine (4.x)の日本語のドキュメント #method-get-child-count
記事一覧 → Compota-Soft-Press
コメント