2020/11/14(土) [n年前の日記]
#6 [godot] Godot Engineで敵から弾を撃たせる
Godot Engine 3.2.3 x64 を使って3D表示の簡単なシューティングゲームっぽいものを作る。
今回は敵から弾を撃たせてみる。
今回は敵から弾を撃たせてみる。
◎ 敵弾シーンを作成。 :
敵弾用のシーン EnemyBullet.tscn を作成していく。「シーン」 → 「新規シーン」を選択。
ルートノードとしてAreaノードを登録して、その下に以下のノードを追加。
ルートノードをEnemyBulletにリネーム。Timer を KillTimer にリネーム。
MeshInstance の Meshプロパティで、新規 SphereMesh を選んで、球の形をしたモデルを設定。
Material で Emission を有効にして発光するようにした。
アタリ範囲(CollisionShapeが担当)は、Shape で SphereShape を指定。球の形でアタリ範囲を指定できる。
res://assets/EnemyBullet.tscn としてシーンを保存した。
ルートノードとしてAreaノードを登録して、その下に以下のノードを追加。
ルートノードをEnemyBulletにリネーム。Timer を KillTimer にリネーム。
EnemyBullet (Area) │ ├─ MeshInstance │ ├─ CollisonShape │ └─ KillTimer (Timer)
MeshInstance の Meshプロパティで、新規 SphereMesh を選んで、球の形をしたモデルを設定。
Material で Emission を有効にして発光するようにした。
アタリ範囲(CollisionShapeが担当)は、Shape で SphereShape を指定。球の形でアタリ範囲を指定できる。
res://assets/EnemyBullet.tscn としてシーンを保存した。
◎ スクリプトを追加。 :
EnemyBulletノードを選択してスクリプトファイルをアタッチ。res://scripts/EnemyBullet.gd として保存した。
◎ タイマーを設定。 :
本来なら、敵弾が画面外に出たかどうかを判別して、出ていたら自分(= 敵弾)を消去する、という処理をしたいけれど…。今回も、とりあえずの簡易処理として、一定時間が経過したら自分を消去、という処理にして誤魔化しておく。
KillTimer を設定。
timeoutシグナルにメソッドを接続する。ノードタブをクリック → timeout を選択して右クリック → 「接続」。
EnemyBullet を選択して「接続」すれば、EnemyBullet.gd に _on_KillTimer_timeout() というメソッドが追加される。自分を消去する queue_free() を追記。
KillTimer を設定。
- Wait Time を 3 に。
- Autostart を有効化。
timeoutシグナルにメソッドを接続する。ノードタブをクリック → timeout を選択して右クリック → 「接続」。
EnemyBullet を選択して「接続」すれば、EnemyBullet.gd に _on_KillTimer_timeout() というメソッドが追加される。自分を消去する queue_free() を追記。
◎ 移動処理を書く。 :
res://scripts/EnemyBullet.gd に移動処理を書く。内容は以下。
_EnemyBullet.gd
set_dir_and_speed(角度、速度)を呼ぶことで、敵弾が飛んでいく方向と移動速度について初期設定ができるようにした。
_EnemyBullet.gd
extends Area var velocity = Vector3() var direction = 0 var speed = 3 func _ready(): pass # Replace with function body. #func _process(delta): # pass func _physics_process(delta): translate(velocity * speed * 60 * delta) func set_dir_and_speed(angle, spd): direction = angle speed = spd var x = cos(deg2rad(angle)) var z = sin(deg2rad(angle)) velocity = Vector3(x, 0, z) func _on_KillTimer_timeout(): queue_free()
set_dir_and_speed(角度、速度)を呼ぶことで、敵弾が飛んでいく方向と移動速度について初期設定ができるようにした。
◎ 敵に敵弾の発生処理を追加。 :
敵に、敵弾の発生処理を追加していく。EnemyZako.tscn を開いて、以下を行う。
変数 enemybullet に、GUI操作で、敵弾シーン EnemyBullet.tscn を指定しておく。Enemybulletプロパティの横の「空」をクリックして「読込み」。
res://assets/EnemyBullet.tscn を選択して「開く」。
敵弾を発生させるタイマー、ShotTimer を設定。
timeoutシグナルにメソッドを接続。EnemyZako を選んで「接続」。
res://scripts/EnemyZako.gd の最後に、_on_ShotTimer_timeout() メソッドが追記される。この中に敵弾の発生処理を書いていけばいい。
EnemyZako.gd に、敵弾の発射処理を追加。以下の内容になる。ここでは敵弾を扇状に発射する処理を追加してる。
_EnemyZako.gd
- Timerノードを追加して、ShotTimer にリネーム。
- スクリプトファイル EnemyZako.gd の最初のあたりに、export (PackedScene) var enemybullet を追記。
変数 enemybullet に、GUI操作で、敵弾シーン EnemyBullet.tscn を指定しておく。Enemybulletプロパティの横の「空」をクリックして「読込み」。
res://assets/EnemyBullet.tscn を選択して「開く」。
敵弾を発生させるタイマー、ShotTimer を設定。
- Wait Time を 1 に。1秒毎に敵弾を発生させる。
- Autostart を有効化。
timeoutシグナルにメソッドを接続。EnemyZako を選んで「接続」。
res://scripts/EnemyZako.gd の最後に、_on_ShotTimer_timeout() メソッドが追記される。この中に敵弾の発生処理を書いていけばいい。
EnemyZako.gd に、敵弾の発射処理を追加。以下の内容になる。ここでは敵弾を扇状に発射する処理を追加してる。
_EnemyZako.gd
extends Area export (PackedScene) var enemybullet var base_pos = Vector3() var angle = 0 export var move_w = 22 export var move_h = 12 var bullets func _ready(): base_pos = translation angle = 0 bullets = get_tree().root.get_node("Main/EnemyBullets") #func _process(delta): # pass func _physics_process(delta): move(delta) func move(delta): angle += delta translation.x = base_pos.x + move_w * cos(deg2rad(angle * 90)) translation.z = base_pos.z + move_h * sin(deg2rad(angle * 70)) func _on_ShotTimer_timeout(): var angle_add = 12 var angle = 90 - angle_add * 3 var spd = 0.2 for i in range(7): _shot(translation, angle, spd) _shot(translation, angle, spd * 0.8) angle += angle_add func _shot(pos, angle, spd): var bullet = enemybullet.instance() bullet.translation = pos bullet.set_dir_and_speed(angle, spd) bullets.add_child(bullet)
◎ Mainシーンに敵弾用のノードを追加。 :
Mainシーンに、敵弾を登録していくためのノードを追加する。Main.tscn を開いて、Mainノードの下に Spatialノードを追加。
EnemyBullets にリネーム。
EnemyBullets にリネーム。
◎ 動作確認。 :
◎ 敵弾のサイズその他を調整。 :
考えてみたら、敵弾如きに奇麗で滑らかな球の3Dモデルは要らないなと思えてきた。サイズを調整するついでにポリゴン数をグンと減らして、ガクガクした感じの球のモデル(Mesh)にしてみた。どうせ小さく表示されるのだから分からないだろう…。
また、敵弾が自分で消滅するまでの時間が短すぎた気がする。まだ画面の中に表示されているのにどんどん消えていくので不自然極まりない。時間を長目に調整。EnemyBullet の KillTimer の Wait Time を5に変更。
動作確認。Mainシーンを開いてF6キーを押す。
それっぽく表示された。
次回は各オブジェクトのアタリ属性を設定していきたい。
- Radius で、球のモデルの半径を指定。
- Height で、球のモデルの高さを指定。
- Radial Segments と Rings で、球のモデルにどのくらいポリゴン数を使うかを指定。多ければ滑らかな球になるし、少なくすればガクガクした球になる。
また、敵弾が自分で消滅するまでの時間が短すぎた気がする。まだ画面の中に表示されているのにどんどん消えていくので不自然極まりない。時間を長目に調整。EnemyBullet の KillTimer の Wait Time を5に変更。
動作確認。Mainシーンを開いてF6キーを押す。
それっぽく表示された。
次回は各オブジェクトのアタリ属性を設定していきたい。
[ ツッコむ ]
以上です。