はじめに
Godot初心者が簡単なミニゲームを作って勉強する
環境
- Godot4.4
クリア条件
- ブロックをすべて破壊する
仕様
- 等速運動するボールが一つポップする
- 壁、ブロック、バーに当たると反転する
- ブロックに当たると角度が変わる - バーは左右に動かせる
- 画面下部に落ちるとゲームオーバー
素材
-
美咲フォント
※画像類はすべてAI生成
成果物
https://geekman4040.itch.io/demoapp
(Game3をクリックして起動)
実装
ボールのスクリプト
次のパラメータを使い分けて実装
- start: ゲーム起動判定
- velocity: 衝突後のベクトル
- new_position: ボールを移動させるときのポジション
func _integrate_forces(state : PhysicsDirectBodyState2D) -> void:
if new_position != null:
state.transform.origin = new_position
new_position = null
func _physics_process(delta: float) -> void:
if start:
# 物理演算ステップでボールを動かす
set_linear_velocity(velocity)
else:
# ゲームが終了している場合、速度をゼロにする
set_linear_velocity(Vector2.ZERO)
func _on_body_entered(body: Node) -> void:
if body.is_in_group("wall_side"):
# 横の壁に当たったらX軸を反転
velocity.x *= -1
elif body.is_in_group("wall_upper"):
# 上の壁に当たったらY軸を反転
velocity.y *= -1
elif body.is_in_group("wall_down"):
_game_over()
Global._over()
game_over.emit()
elif body.is_in_group("bar"):
velocity.y *= -1
else:
# それ以外の物体(例:プレイヤーのバー)に当たった場合
var direction_of_impact = (global_position - body.global_position).normalized()
velocity = velocity.bounce(direction_of_impact)
# 速度を一定に保つ
velocity = velocity.normalized() * speed
使ったノードたち
- Area2D: ブロックに使用
- StaticBody2D: バーに使用
- RigidBody2D: ボールに使用
所要時間
5時間
※素材収集、エクスポート作業を除く
課題
Physic Material Overrideが悪さをして任意の角度変換ができない
当初はGodotの物理エンジンに衝突や反転処理を委譲しようとPhysic Material Overrideを利用していましたが、細かい角度変更の制御(ブロックの当たる場所で角度を変えたい)を加えると想定外の挙動を示すように。
泣く泣くPhysic Material Overrideを消してRigidBody2Dにアタッチしたスクリプトで制御するように変更
RigidBody2DのPosition変更ができない
ゲーム初期化時にボールの初期値に移動させるもなぜか変更できず。
調べたところ_integrate_forcesメソッドで位置を固定する必要があるようでした。
処理順序をしっかり理解しないとダメですね
https://www.reddit.com/r/godot/comments/1hkl23o/set_position_of_a_rigidbody/
シグナルを外部シーンから発信してキャッチできない
ブロックを別シーンにして読み込む実装にしたところ、ブロック側からシグナルを発信してルートノードでキャッチできないことが判明。グローバルスクリプトで回避したものの、別シーンにしないほうが良かった。
感想
むずかしすぎ。
ゲームの始祖ともいえるブロック崩しを実装するだけでこの難易度。
- Area2D
- RigidBody2D
- StaticBody2D
この三つは早急に慣れていきたい