2020/11/14(土) [n年前の日記]
#4 [godot] Godot Engineでプレイヤーの弾を撃つ
Godot Engine 3.2.3 x64 を使って3D表示の簡単なシューティングゲームっぽいものを作る。
今回はプレイヤーの弾を撃ってみる。
今回はプレイヤーの弾を撃ってみる。
◎ プレイヤーの弾のシーンを作成。 :
プレイヤーの弾のシーン res://asets/PlayerBullet.tscn を作成する。
ルートノードに Area、その下に表示モデルを担当する Spatial、MeshInstance と、アタリ範囲を担当する CollisionShape を追加する。
Areaノードは、表示モデルとアタリ範囲を持って、かつ、物理法則に従わない動きをする物体に使うノードらしい。
MeshInstance の Mesh に割り当てた Material で、Emission(発光)を有効にしておく。これで、画面に表示されたときに光ってる感じになって少しは目立つはず。
ルートノードを PlayerBullet にリネーム。
res://assets/ の下に PlayerBullet.tscn として保存。
ルートノードに Area、その下に表示モデルを担当する Spatial、MeshInstance と、アタリ範囲を担当する CollisionShape を追加する。
Area ├─ Spatial │ ├─ MeshInstance │ └─ MeshInstance └─ CollisionShape
Areaノードは、表示モデルとアタリ範囲を持って、かつ、物理法則に従わない動きをする物体に使うノードらしい。
MeshInstance の Mesh に割り当てた Material で、Emission(発光)を有効にしておく。これで、画面に表示されたときに光ってる感じになって少しは目立つはず。
ルートノードを PlayerBullet にリネーム。
res://assets/ の下に PlayerBullet.tscn として保存。
◎ スクリプトファイルを追加。 :
◎ タイマーノードを追加。 :
本来なら、弾が画面外に出たら自分を消去する処理を作りたいけれど、画面外かどうかを判別する方法が分からない…。
とりあえずの簡易処理として、弾が出現して一定時間が経過したら自分自身を消去するようにしてみる。そのために Timerノードを追加。
Timerノードのプロパティを設定。
Timerノードの timeoutシグナルにメソッドを接続。ノードタブをクリック → timeout を選択して右クリック → 「接続」。
PlayerBullet を選択して「接続」。
スクリプトファイル PlayerBullet.gd に、_on_Timer_timeout() が追加された。自分自身を消去するメソッド、queue_free() を追記する。
これで、PlayerBullet が画面に出現すると Timer が自動実行されて、指定時間が来たら自分を消去、という処理になる。
とりあえずの簡易処理として、弾が出現して一定時間が経過したら自分自身を消去するようにしてみる。そのために Timerノードを追加。
Timerノードのプロパティを設定。
- Wait Time を 2 に。
- One Shot にチェックを入れて有効化。
- Autostart にチェックを入れて有効化。
Timerノードの timeoutシグナルにメソッドを接続。ノードタブをクリック → timeout を選択して右クリック → 「接続」。
PlayerBullet を選択して「接続」。
スクリプトファイル PlayerBullet.gd に、_on_Timer_timeout() が追加された。自分自身を消去するメソッド、queue_free() を追記する。
これで、PlayerBullet が画面に出現すると Timer が自動実行されて、指定時間が来たら自分を消去、という処理になる。
◎ 弾の移動処理を追加。 :
プレイヤーの弾のスクリプトファイル res://scripts/PlayerBullet.gd に、弾の移動処理を追加する。以下を記述。
_PlayerBullet.gd
translate(velocity * speed * delta) で、現在座標を (velocity * speed * delta) 分変化させている。
_PlayerBullet.gd
extends Area var velocity = Vector3() var speed = 90 func _ready(): velocity = Vector3(0, 0, -1) #func _process(delta): # pass func _physics_process(delta): translate(velocity * speed * delta) func _on_Timer_timeout(): queue_free()
translate(velocity * speed * delta) で、現在座標を (velocity * speed * delta) 分変化させている。
◎ プレイヤーの弾を登録するノードを用意。 :
Mainシーンに、発生させたプレイヤーの弾を登録していくためのノード、PlayerBullets を用意する。
Mainシーンを開いて Spatial ノードを追加。
PlayerBullets にリネーム。
Mainシーンを開いて Spatial ノードを追加。
PlayerBullets にリネーム。
◎ プレイヤーから弾を発生させる。 :
プレイヤーキャラから弾を発生させる。今回はショットボタンを押さなくても自動・一定間隔で弾を次々に発射するようにしてみる。
プレイヤーのシーン、Player.tscn を開いて、Timerノードを追加。ShotTimer にリネーム。このタイマーを使って弾の発生処理をさせる。
ShotTimerのプロパティを設定。
timeoutシグナルにメソッドを接続。ノードタブをクリック → timeout を選択して右クリック → 「接続」。
Player を選択して「接続」。
Playerのスクリプトファイル、res://scripts/Player.gd に、_on_ShotTimer_timeout() というメソッドが追加された。ShotTimer で設定した時間間隔で、このメソッドが呼び出される。
Player.gd に以下を記述。
_Player.gd
Playerシーンのプロパティ Player Bullet に、PlayerBulletシーンを設定する。Playerノードを選択して、Player Bullet の横の「空」をクリックして「読込み」。
res://assets/PlayerBullet.tscn を選択して「開く」。これで、Player Bullet にプレイヤーの弾のシーンを設定できた。
プレイヤーのシーン、Player.tscn を開いて、Timerノードを追加。ShotTimer にリネーム。このタイマーを使って弾の発生処理をさせる。
ShotTimerのプロパティを設定。
- Wait Time は 0.065 に。高橋名人が1秒間に16連射していたらしいので、それに近い値を指定してみたつもり。
- Autostart にチェックを入れて有効化。
timeoutシグナルにメソッドを接続。ノードタブをクリック → timeout を選択して右クリック → 「接続」。
Player を選択して「接続」。
Playerのスクリプトファイル、res://scripts/Player.gd に、_on_ShotTimer_timeout() というメソッドが追加された。ShotTimer で設定した時間間隔で、このメソッドが呼び出される。
Player.gd に以下を記述。
_Player.gd
extends KinematicBody export (PackedScene) var PlayerBullet const SPEED = 32 var velocity = Vector3() func _ready(): pass # Replace with function body. #func _process(delta): # pass func _physics_process(delta): # move velocity = Vector3() if Input.is_action_pressed("ui_right"): velocity.x = 1 elif Input.is_action_pressed("ui_left"): velocity.x = -1 if Input.is_action_pressed("ui_down"): velocity.z = 1 elif Input.is_action_pressed("ui_up"): velocity.z = -1 # Do not multiply by delta when using move_and_slide() velocity = velocity.normalized() * SPEED move_and_slide(velocity) func _on_ShotTimer_timeout(): var bullet = PlayerBullet.instance() bullet.translation = Vector3(translation.x, translation.y, translation.z - 1.0) get_tree().root.get_node("Main/PlayerBullets").add_child(bullet)
- 最初のほうで、export (PackedScene) var PlayerBullet を書いて、PlayerBulletシーンを入れておく変数 PlayerBullet を用意する。
- _on_ShotTimer_timeout() の中でプレイヤーの弾の発生処理をする。PlayerBullet のインスタンスを生成、座標を Player のちょっと前に設定してから、Mainシーンの PlayerBulletsノードに登録している。
Playerシーンのプロパティ Player Bullet に、PlayerBulletシーンを設定する。Playerノードを選択して、Player Bullet の横の「空」をクリックして「読込み」。
res://assets/PlayerBullet.tscn を選択して「開く」。これで、Player Bullet にプレイヤーの弾のシーンを設定できた。
◎ 動作確認。 :
Mainシーンを開いてF6キーを押して動作確認。
それっぽい感じで弾を撃ってくれるようになった。
次回は敵を作ってみる。
それっぽい感じで弾を撃ってくれるようになった。
次回は敵を作ってみる。
[ ツッコむ ]
以上です。