※この連載の全ての記事は、タグ「ビッグカツ」の検索一覧から探すことができます。
※この連載で作ったゲームは「BigBreakOut(ゲームの作り方の記事付き) | フリーゲーム投稿サイト GodotPlayer」でプレイできます。
昔から人気の駄菓子「ビッグカツ」のフリー素材画像が公開されたので、無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 を使って、ビッグカツ画像を使ったブロック崩しを作成します。
「ビッグカツブロック崩し」作成の第8回では、前回までに作成した壁(左側・上側・右側)・パドル(バー)・ボールのそれぞれの物理演算による衝突を発生させるかどうかを、コリジョンレイヤーマスクで設定し、ボールはパドルに衝突するけど、そのときパドルはボールの衝突を受けないという一見矛盾したような実装例を紹介します。
※ GodotEngine 4.3 を使用しています。.NET 版ではありません。
※スクリプトは自己責任でご使用ください。
前回の記事
前回は、ぶつかると向きを変えて移動し続けるスクリプトを割り当てたボールのシーンを作成して、ステージシーンに追加しました。
ボールの衝撃でパドルが飛ばされてしまう問題
等速で移動するボールが上から下に移動してきてパドル(バー)に衝突した際に、横にだけ移動するべきパドルがその衝突の影響で下側に移動してしまいました。
今回は、壁とは衝突するけれどボールとは衝突しないパドルと、パドルと衝突するボールという、一見矛盾しているような関係を、 Collision Layer / Mask の設定で作成します。
他に試行した対策方法
以下は、試したけど、あまりうまくいかなかった対策です。
Y 軸の座標を固定
パドルの y 座標をいつも固定しておく方法もありますが、ボールが斜め下方向に移動してパドルの横の側面と衝突した場合に対処できません。
また、今後、斜め方向に動くリフトなどを実装する際に応用もききません。
StaticBody2D で動かない剛体としてパドルを実装
パドルを CharacterBody2D クラスから StaticBody2D クラスに変えて、動かない剛体にして、position を入力に応じて変更する方式は、指定した速度で衝突などの物理演算を行いながら移動できる便利なメンバ関数 move_and_collide が使えないため、壁との衝突判定などを自前で行う必要があり面倒で、バグも発生しやすくなると思いました。
Do not use together with PhysicsBody2D.move_and_collide.
PhysicsBody2D.move_and_collide と一緒に使用しないでください。
AnimatableBody2D — Godot Engine (4.x)の日本語のドキュメント と Google 翻訳
※ AnimatableBody2D クラスは StaticBody2D クラスの派生です。
Collision Layer / Mask とは
Area2D, CharacterBody2D, StaticBody2D などの当たり判定を行うクラスは CollisionObject2D から派生しています。
その CollisionObject2D クラスには collision_layer と collision_mask というプロパティがあり、それぞれ 32 個のレイヤーの ON / OFF をノードごとに設定できます。
collision_layer では、自身が所属する 1 ~ 32 のレイヤー番号を個別に ON/OFF します。
※複数を ON にすることも、すべてを OFF にすることもできます。
collision_mask で ON にしたレイヤーに所属しているノード群を対象に衝突したかどうかを判定します。
次の章では、この collision_layer と collision_mask の使用例を紹介します。
物理の紹介 — Godot Engine (4.x)の日本語のドキュメント
- collision_layerこれは、オブジェクトが in で表示されるレイヤーを記述します。デフォルトでは、すべてのボディはレイヤー
1
上にあります。- collision_maskこれは、ボディが衝突を スキャン するレイヤーを記述します。オブジェクトがマスクレイヤーのいずれかにない場合、ボディはそれを無視します。デフォルトでは、すべてのボディがレイヤー
1
をスキャンします。
以下は、 collision_layer, collision_mask プロパティの説明の引用です。
The physics layers this CollisionObject2D is in. Collision objects can exist in one or more of 32 different layers. See also collision_mask.
Note: Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See Collision layers and masks in the documentation for more information.
この CollisionObject2D が含まれる物理レイヤー。衝突オブジェクトは 32 の異なるレイヤーのうち 1 つ以上に存在できます。 「衝突マスク」も参照してください。 注: オブジェクト A がスキャンするレイヤーのいずれかにオブジェクト B が存在する場合にのみ、オブジェクト A はオブジェクト B との接触を検出できます。詳細については、ドキュメントの衝突レイヤーとマスクを参照してください。CollisionObject2D — Godot Engine (4.x)の日本語のドキュメント #property-collision-layer と Google 翻訳
The physics layers this CollisionObject2D scans. Collision objects can scan one or more of 32 different layers. See also collision_layer.
Note: Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See Collision layers and masks in the documentation for more information.
この CollisionObject2D がスキャンする物理層。衝突オブジェクトは、32 の異なるレイヤーのうち 1 つ以上をスキャンできます。 「collision_layer」も参照してください。 注: オブジェクト A がスキャンするレイヤーのいずれかにオブジェクト B が存在する場合にのみ、オブジェクト A はオブジェクト B との接触を検出できます。詳細については、ドキュメントの衝突レイヤーとマスクを参照してください。CollisionObject2D — Godot Engine (4.x)の日本語のドキュメント #property-collision-mask と Google 翻訳
衝突判定の Layer, Mask の設定で、動くけど衝突の影響を受けない設定
CollisionObject2D クラスの collision_layer, collision_mask のレイヤー番号の ON/OFF を行うには、 Area2D, CharacterBody2D, StaticBody2D などの CollisionObject2D 派生クラスのノードをシーンドックで選択してから、インスペクタードックの CollisionObject2D クラスの Collision セクションを展開して、表示されたレイヤー番号の書かれたマスをクリックします。
以下は、ブロック崩しの壁とパドルとボールのコリジョンレイヤーマスクの設定例です。
実装の方法にもよりますが、今回は、ボールは壁とパドルに自身から衝突、パドルは壁にだけ自身から衝突、壁は自身からはどこにも衝突しない設定です。
以下に、 Mask と Layer の設定から見たそれぞれのノードの衝突する対象について説明します。
Mask は自身が衝突する相手の Layer 番号を ON/OFF する
ボールは、 Mask の 1, 2 が ON になっているので、 Layer 1 または 2 が ON になっているノード、例では壁とパドルどちらにも衝突します。
パドルは、 Mask の 1 だけが ON になっているので、 Layer 1 が ON になっているノード、例では壁にだけ衝突します。
3つの壁は、自身からは衝突をしないので Mask は全て OFF です。
Layer は自身が所属する番号を ON/OFF する
ボールは、Layer は全てオフです。
これは、ボール自身が壁やパドルと衝突することで処理が完結し、他のノードからの衝突が必要ないからです。
仮に、ボールが複数移動している場合も、どの collision layer にも所属していないので、ボール同士の衝突すらおきません。
※もしも、ボールに衝突させるノードを追加する場合は Layer の 3 などを ON にして、その相手のノードの Mask の 3 を ON にしましょう。
パドルは、 Layer の 2 が ON になっています。
これは、ボールが壁とパドルに衝突するためですが、壁と異なる Layer の番号を設定したのは、壁とは衝突するけれど、ボールとは衝突しないからです。
ボールはパドルに衝突する設定ですが、パドルからのボールへの衝突は物理演算しません。
これにより、ボールがパドルに衝突して向きを変えても、パドルはボールとの衝突の影響がなく押されません。
壁は、Layer の 1 が ON になっています。
これは、パドルとことなる番号を ON にしてパドルと壁との所属を分けつつ、ボールは壁とパドルどちらにも衝突するためです。
テスト
F5 キーなどで Stage シーンを実行すると、ボールが 45 度の角度で移動して壁・パドルにぶつかると向きを変えています。
ボールがパドルの上側や右側に衝突しても、パドルはボールとの衝突を物理演算しない設定なので、ボールだけが衝突して向きを変え、パドルは一切影響を受けません。
今回のコリジョンレイヤーマスクの設定により、ボール側は衝突を検出するけど、パドル側は衝突を検知しない設定のおかげで、動いて壁にぶつかるけどボールと接触しても揺れないパドルができました。
追記:Grounded から Floating に変更するとパドルが落下しませんでした
壁・ボール・パドルのコリジョンレイヤー・マスクの設定を初期値の 1, 1 に戻して、 Paddle ノードの CharacterBody2D の Motion Mode を Grounded から Floating に変更すると、ボールと衝突しても下に移動(落下?)しませんでした。
Floating を選ぶと「スライドする際の速度が一定になる」点が影響しているかもしれません。
MotionMode MOTION_MODE_GROUNDED =
0
Apply when notions of walls, ceiling and floor are relevant. In this mode the body motion will react to slopes (acceleration/slowdown). This mode is suitable for sided games like platformers.
壁、天井、床の概念が関連する場合に適用します。このモードでは、車体の動きが坂道(加速/減速)に反応します。このモードは、プラットフォーマーなどのサイド ゲームに適しています。MotionMode MOTION_MODE_FLOATING =
1
Apply when there is no notion of floor or ceiling. All collisions will be reported as
on_wall
. In this mode, when you slide, the speed will always be constant. This mode is suitable for top-down games.床や天井の概念がない場合に適用します。すべての衝突は on_wall として報告されます。このモードでは、スライドするときの速度は常に一定になります。このモードはトップダウン ゲームに適しています。CharacterBody2D — Godot Engine (4.x)の日本語のドキュメント と Google 翻訳
しかし、横スクロール型のアクションの浮遊して左右に移動するリフトなどを実装する際は、 Grounded を選ぶと思うので、その際には、今回のコリジョンレイヤー・マスクの設定が有用です。
まとめ
「ビッグカツブロック崩し」作成の第8回では、前回までに作成した壁(左側・上側・右側)・パドル(バー)・ボールのそれぞれの物理演算による衝突を発生させるかどうかを、コリジョンレイヤーマスクで設定し、ボールはパドルに衝突するけど、そのときパドルはボールの衝突を受けないという一見矛盾したような実装例を紹介しました。
参照サイト Thank You!
- Godot Engine – Free and open source 2D and 3D game engine
- Xユーザーのビッグカツといか姿フライのすぐる【公式】さん: 「使いどころは思いつきませんが、フリー素材としてどうぞご自由にお使いくださいませ! https://t.co/8F9q3hS02b」 / X
- しょかきうたげ【フリーフォント版あり】 – ぼんのう堂 – BOOTH
- CharacterBody2D — Godot Engine (4.x)の日本語のドキュメント
- StaticBody2D — Godot Engine (4.x)の日本語のドキュメント
- CollisionShape2D — Godot Engine (4.x)の日本語のドキュメント
- AnimatableBody2D — Godot Engine (4.x)の日本語のドキュメント
- PhysicsBody2D — Godot Engine (4.x)の日本語のドキュメント #method-move-and-collide
- CollisionObject2D — Godot Engine (4.x)の日本語のドキュメント
- CollisionObject2D — Godot Engine (4.x)の日本語のドキュメント #property-collision-layer
- CollisionObject2D — Godot Engine (4.x)の日本語のドキュメント #property-collision-mask
- 物理の紹介 — Godot Engine (4.x)の日本語のドキュメント
- CharacterBody2D — Godot Engine (4.x)の日本語のドキュメント
記事一覧 → Compota-Soft-Press
コメント