Godot4 宝箱をクリックしたらコインが飛び出す実装例

2D / 3D ゲームを作成できる無料・オープンソースの軽快なゲームエンジン「Godot Engine 4」で、コイン画像を表示・物理演算するシーンを作成して、そのシーンを別のシーンのスクリプトから動的に子ノードとして作成・配置して、物理関数で指定した方向・力で飛ばす手順を紹介します。

※この記事は、サンプルアプリ TapTheTakarabako の開発のパート3でもあります。
※ GodotEngine のバージョンは 4.1.2 です。 .NET 版ではありません

※「いらすとや」様の画像を使用しています。
※「ふい字」フォントを使用しています。

※記事で紹介するスクリプト / プログラム / コードは自己責任で使用してください。

コイン画像のプロジェクトへの追加

コイン画像のファイルのコピーをプロジェクトへ追加するには、エクスプローラの画像ファイルファイルシステムドックのツリー上にドラッグ&ドロップします。
フォルダを変えたい場合は、再度ツリー上でドラッグ&ドロップして移動しましょう。

Godot4 コイン画像ファイルをドラッグ&ドロップしてプロジェクトに追加します...

コイン画像は「草コインのイラスト | かわいいフリー素材集 いらすとや」を使用しました。

コイン画像を表示するシーンを作成

メニュー「シーン」→「新規シーン」を選択してから、シーンドックで「その他のノード」を選択します。
表示された「Node を新規作成」ダイアログで RigidBody2D を選択してルートノードを作成します。

Godot4 放出されるコインのシーンのルートノードは RigidBody2D で作成します...

下位ノードに画像を表示する Sprite2D クラスのノードと、当たり判定領域を設定する CollsionShape2D クラスのノードを追加します。

RigidBody2D
  +--- Sprite2D
  +--- CollisionShape2D(shape=CircleShape2D)

下位ノードを追加するには、シーンドックでルートノードを右クリックして表示される「子ノードを追加」メニューを押します。
表示されたダイアログで、Sprite2D, CollisionShape2D クラスを選択して「作成」ボタンを押して追加しましょう。

Godot4 放出されるコインのシーンのルートノードに子ノード Sprite2D と CollisionShape2D を追加します....

CollisionShape2D 子ノードを選択して、インスペクターノードで Shape プロパティの▼ボタンを押してリストを表示して「新規 CircleShape2D」を選択して割り当てます。

Godot4 コインの当たり判定領域に円形を割り当てます.

Sprite2D 子ノードを選択して、先ほどプロジェクトに追加したコインの画像ファイルファイルシステムドックから、インスペクタードックの Texture プロパティにドラッグ&ドロップして設定します。

Godot4 コインの画像を表示する Sprite2D クラスの Texture に画像ファイルをD&Dで割り当てます..

ルートノードを RigidBody2D から名前をシーンと同じものに変更します。
例では OtakaraCoin に変更しました。

ノードを設定したら、シーンを保存しましょう。
Ctrl+S などで保存ダイアログを表示して、シーンファイル名を snake_case 表記の otakara_coin と入力して「保存」ボタンを押します。

Godot4 コインのシーンのルートノードをリネームしてからシーンを保存します...

F6 キーを押すと、現在のシーンが再生されて、左上にコイン画像の右下が表示されました。
これは、左上原点に配置しているためです。
他のシーンで子ノードと使う際に原点に配置してあるほうが便利なので、位置は変更しません。

Godot4 コイン画像のシーンを作成後、F6キーを押した結果...

サイズSprite2D ノードを選択して、インスペクタードックの Node2DScale変更することで調整できます。
※ 2D ビューで丸いハンドルをドラッグすることでも変更できます。

Godot4 TapTheTakarabako コインなどのスプライト画像をbase解像度に合わせてサイズ調整します.

今回は無効にするので調整の必要はありませんが、CollisionShape2D ノードを選択してから 2D ビューハンドルドラッグすることで当たり判定領域を調整できます。

Godot4 TapTheTakarabako 当たり判定の領域は 2D ビューでハンドルをドラッグして調整できます..

当たり判定をする必要がない場合は、 CollisionShape2D ノードを選択して、インスペクタードックで Disabledチェックします。

Godot4 TapTheTakarabako 当たり判定は Disalbed をオンにすることで無効にできます...

当たり判定を有効にした状態でも後述のスクリプトでコインを飛ばすことはできますが、他のコインとぶつかりあってスムーズに飛びませんでした。

同じコインのシーンのノード同士だけ当たり判定をしないように RigidBody2D ノードの継承元の CollisionObject2DCollisionMask1 のボタンをクリックして他と同じくうす暗くすると、Layer で選択した自身が属する衝突判定のグループと当たり判定を行わないようにできます。
今回は一切の当たり判定を行わないので、前述のように CollisionShape2D ノードの Disable をチェックしました。

Godot4 Collsion のレイヤーとマスクで自身と同じグループのものと当たり判定をしない設定もできます.

RigidBody2D をルートノードにした理由

RigidBody2D をルードノードにしない以下の構成にすると RigidBody2D の 物理関数apply_impulse を呼び出してもコイン画像が動きも落下もせずただ表示されるだけでした。
※失敗例なのでスキップして構いません。

Sprite2D
  +--- RigidBody2D
       +--- CollisionShape2D(shape=CircleShape2D)

下位の RigidBody2D ノードの物理関数を呼び出した際の処理は以下です。

# CoinSprite ノードを生成するために必要な coin_sprite シーンを読み込んでおきます。
sceneCoinSprite = preload("res://coin_sprite.tscn")
# シーンから子ノードを作成します。
var nodeCoinSprite = sceneCoinSprite.instantiate()
# 下位の RigidBody2D という名前のノードを取得して、それが持つ物理関数を呼び出します。
nodeCoinSpirte.get_node("RigidBody2D").apply_impulse(impulse, apply_point)

コインを表示するシーンを子ノードとして動的に作成

作成したコインを表示する otakara_coin シーンを GD スクリプトで読み込むことで、複製を子ノードとして配置できます。

Godot4 TapTheTakarabako preload 関数でノードを作成する対象のシーンを読み込みます...
# コイン画像を表示するシーンを子ノードとして生成する際に用います。
var scene_otakara_coin

# Called when the node enters the scene tree for the first time.
func _ready():
	# otakara_coin ノードを生成するために必要な otakara_coin シーンを読み込んでおきます。
	scene_otakara_coin = preload("res://otakara_coin.tscn")

読み込んだ PackedSceneinstantiate 関数を呼び出すことで、そのシーンを子ノードとして作成できます。

	# scene_otakara_coin シーンから、インスタンスを作成します。
	var nodeOtakara:RigidBody2D = scene_otakara_coin.instantiate()

作成した後は、メンバ変数などを設定してから、シーンに追加します。
今回は実行中のシーンのルートノードの下位に配置します。

今回は、実行されるシーンのルートノードのスクリプトではなく、宝箱を表示するシーンのスクリプトでノードを作成して配置しています。
そのため、 get_root() でルートノードを得て、ルートノードの下位に作成したノードを配置しています。
そうしないとこのスクリプトを割り当てている宝箱のノードの下位に配置されてしまい、宝箱のノードの位置が基準になってしまいます。

Godot4 TapTheTakarabako 宝箱の下位にノードを配置すると宝箱を基準とした相対座標で配置されクリック位置からずれます....
	node_otakara.position = position # 上位ノードの相対座標で設定します。そのため配置先はルートの下位にします。
	get_tree().get_root().add_child(node_otakara) # シーンのルートノードの下位に作成した子ノードを追加します。

GD スクリプトから動的にシーンを子ノードとして作成・配置する手順については、以下の記事を参照してください。

作成したコインを物理関数で飛ばす

以下のスクリプトを用いて、シーンファイルから子ノードを動的に作成して一定範囲のランダムな向きと力で飛ばします。

前述したノードの作成とシーンへの配置をした後に、その RigidBody2D のノード自身に瞬間的に力を加える物理関数 apply_impulse を呼び出しています。

指定した範囲内で方向と力をランダムに決定して、そのベクトルを apply_impulse に与えることで、瞬間的に指定した方向に指定した勢いで RigidBody2D ノードを飛ばします

# お宝を飛ばす際の勢いの下限値です。
var otakara_impulse_power_min = 500
# お宝を飛ばす際の勢いの上限値です。
var otakara_impulse_power_max = 1000

# お宝を飛ばす際の角度の下限値です。
var otakara_vector_degree_min = 95
# お宝を飛ばす際の角度の上限値です。
var otakara_vector_degree_max = 165

# お宝の子ノードを動的に作成して、それを飛ばします。
# position : お宝の子ノードの初期位置です。
func spawn_otakara(position:Vector2):
	# coin_sprite シーンから、インスタンスを作成します。
	var node_otakara = scene_otakara_coin.instantiate()
	
	node_otakara.position = position # 上位ノードの相対座標で設定します。そのため配置先はルートの下位にします。
	get_tree().get_root().add_child(node_otakara) # シーンのルートノードの下位に作成した子ノードを追加します。
	
	# お宝が飛ぶ勢いをランダムに決定します。
	var power = randf_range(otakara_impulse_power_min, otakara_impulse_power_max)
	# お宝が飛ぶ方向をランダムに決定します。
	var degree = randf_range(otakara_vector_degree_min, otakara_vector_degree_max)
	# degree に応じた単位円のベクトルを作成します。180 度足して反対側に力を加えることで指定した方向に飛ばします。
	var direction = Vector2()
	direction.x = cos(deg_to_rad(degree))
	direction.y = sin(deg_to_rad(degree)) * -1
	
	# 物理関数 apply_impulse 渡す、加える力の値を、範囲内でランダムに決定した向きと力を掛け合わせて設定します。
	var impulse = direction * power

	# お宝の中心に方向をもった力を加えて飛ばします。
	node_otakara.apply_impulse(impulse)#, apply_point)
	return

物を飛ばす際の物理関数については以下の記事を参照してください。

宝箱をクリックしたときにコインを出す処理

宝箱をクリックした際の処理で、前述の SpawnOtakara 関数を呼び出します。

# 当たり判定の領域にマウスオーバーした際のシグナル input_event と接続した受信側メソッドです。
func _on_area_2d_input_event(viewport, event, shape_idx):
	# マウス左ボタンを離した直後の場合
	if Input.is_action_just_released("ClickOrTap"):
		spawn_otakara(event.position)
	return

ClickOrTap アクションについては「Godot4 クリック/タップしたイベントの検知と座標のログ出力」の「クリック / タップの入力アクションの作成」を参照してください。

テスト

F6 キーで現在開いているメインのシーンを実行して、宝箱をクリックすると SpawnOtakara 関数が呼び出して、コインのノードを作成して物理関数で飛ばすことが出来ました。

※この動画を撮影した際は、コインの Sprite2D の Scale は 1.0 の状態です。

まとめ

今回は、2D / 3D ゲームを作成できる無料・オープンソースの軽快なゲームエンジン「Godot Engine 4」で、コイン画像を表示・物理演算するシーンを作成して、そのシーンを別のシーンのスクリプトから動的に子ノードとして作成・配置して、物理関数で指定した方向・力で飛ばす手順を紹介しました。

参照サイト Thank You!

記事一覧 → Compota-Soft-Press

コメント

Ads Blocker Image Powered by Code Help Pro

お願い - Ads Blocker Detected

このサイトは広告を掲載して運営しています。

ポップアップを閉じて閲覧できますが、よろしければ

このサイト内の広告を非表示にする拡張機能をオフにしていただけませんか?

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

We have detected that you are using extensions to block ads. Please support us by disabling these ads blocker.

タイトルとURLをコピーしました