2020/04/02(木) [n年前の日記]
#1 [godot] Godot Engineで弾を撃つ
Godot Engine でプレイヤーの弾を撃つ処理をどう書けばいいのか悩んでいたのだけど。公式ドキュメントのFPS関連チュートリアル記事を眺めて、なんとなく分かってきた。環境は、Windows10 x64 1909 + Godot Engine 3.2.1 x64。
_パート2 - Godot Engine latest ドキュメント
とりあえず、プレイヤーの弾を担当するシーン、PlayerBullet.tscn を作成しておいて…。
プレイヤーキャラを担当するシーン、Player.tscn に割り当てたスクリプトの中で、以下のような感じで処理。ちなみにプレイヤーは、KinematicBody から作った。
var bullet = preload("res://assets/PlayerBullet.tscn") で、事前にプレイヤー弾のシーンを読み込んでおいて、bullet.instance() でインスタンスを作成。しかるべきノードに、add_child(clone) で、子ノードとして追加。これで一応画面上にプレイヤーの弾が次々に発生してくれた。
_パート2 - Godot Engine latest ドキュメント
とりあえず、プレイヤーの弾を担当するシーン、PlayerBullet.tscn を作成しておいて…。
プレイヤーキャラを担当するシーン、Player.tscn に割り当てたスクリプトの中で、以下のような感じで処理。ちなみにプレイヤーは、KinematicBody から作った。
extends KinematicBody var bullet = preload("res://assets/PlayerBullet.tscn") # ... var shot_counter = 0 func _ready(): shot_counter = 0 # ... func _physics_process(delta): # ... # born player bullets shot_counter += delta if shot_counter >= (4 * 1.0 / 60.0): shot_counter = 0 _born_player_bullet(translation) # ... func _born_player_bullet(pos): var clone = bullet.instance() clone.translation = pos clone.translation.z -= 2.5 var scene_root = get_tree().root.get_children()[0] scene_root.add_child(clone)
var bullet = preload("res://assets/PlayerBullet.tscn") で、事前にプレイヤー弾のシーンを読み込んでおいて、bullet.instance() でインスタンスを作成。しかるべきノードに、add_child(clone) で、子ノードとして追加。これで一応画面上にプレイヤーの弾が次々に発生してくれた。
◎ プレイヤーの弾の移動。 :
プレイヤーの弾は、画面奥へと飛んでいってほしい。そのあたりの処理を試したり。
プレイヤーの弾は、Area で用意した。
スクリプトは以下のような感じで。
translation の z に値を加算、というか減算してみたら、奥方向に移動していく感じで動いてくれた。
ただ、こういう動かし方でいいのか分からんけど…。KinematicBody の場合は move_and_slide() を呼んで動かしてたけど、Area の場合は move_and_slide() を呼ぼうとしても「そんなメソッドは無い」と言われてしまって。しかし、こんな動かし方をしてもいいのだろうか…。どうなんだろう…。
そのままだと、ずっとどこまでも飛んで残り続けてしまうので、時間を測って一定時間が経ったら自分を殺す、みたいな処理も一応入れた。本当は画面外に出たかどうかチェックして消すべきだろうけど、どうやってソレを調べればいいのか…。
プレイヤーの弾は、Area で用意した。
Area MeshInstance CollisionShape
スクリプトは以下のような感じで。
extends Area var counter = 0 export var kill_time = 2.0 export var speed = 1.5 var velocity = Vector3() func _ready(): counter = 0 func _physics_process(delta): counter += delta if counter >= kill_time: queue_free() return velocity = Vector3(0, 0, -speed * 60 * delta) translation += velocity
translation の z に値を加算、というか減算してみたら、奥方向に移動していく感じで動いてくれた。
ただ、こういう動かし方でいいのか分からんけど…。KinematicBody の場合は move_and_slide() を呼んで動かしてたけど、Area の場合は move_and_slide() を呼ぼうとしても「そんなメソッドは無い」と言われてしまって。しかし、こんな動かし方をしてもいいのだろうか…。どうなんだろう…。
そのままだと、ずっとどこまでも飛んで残り続けてしまうので、時間を測って一定時間が経ったら自分を殺す、みたいな処理も一応入れた。本当は画面外に出たかどうかチェックして消すべきだろうけど、どうやってソレを調べればいいのか…。
◎ 衝突判定で悩んだ。 :
プレイヤーの弾、及び、敵を、Area から作っていったのだけど。何かと衝突したら body_entered シグナルが発生するはず、と思って処理を書いたら無反応で悩んだり。
調べてみたら、body_entered は、xxxxBody と衝突した時にだけ発生するようで…。StaticBody とか、RigidBody とか、KinematicBody とか。
Area と Area が衝突した際は、area_entered が発生するらしい。
しかし、自分に何が当たったのかを、どうやって調べたらいいのか…。ググってみたら、どうやらグループというものが使えそうな気配。
プレイヤーの弾には「player_bullet」を、敵には「enemy」を、グループ登録しておいて…。例えば敵の側の area_entered と接続した関数内で、以下のように書けば…。
このあたり、レイヤーとマスクを使うことでも処理ができそうな気もするけれど、まだそこまで調べてなかったり。
調べてみたら、body_entered は、xxxxBody と衝突した時にだけ発生するようで…。StaticBody とか、RigidBody とか、KinematicBody とか。
Area と Area が衝突した際は、area_entered が発生するらしい。
しかし、自分に何が当たったのかを、どうやって調べたらいいのか…。ググってみたら、どうやらグループというものが使えそうな気配。
プレイヤーの弾には「player_bullet」を、敵には「enemy」を、グループ登録しておいて…。例えば敵の側の area_entered と接続した関数内で、以下のように書けば…。
func _on_EnemyZako_area_entered(area): if area.is_in_group("player_bullet"): # Collide with player bullets damage_timer = 0.3 hp -= area.attack_point print("Hit. My HP = " + String(hp)) if hp <= 0: queue_free() # I am dead.area.is_in_group("グループ名") で、当たった何かがそのグループなら、てな感じの処理が書ける。
このあたり、レイヤーとマスクを使うことでも処理ができそうな気もするけれど、まだそこまで調べてなかったり。
[ ツッコむ ]
#2 [pc] SocketAM4 M/Bが届いた
TSUKUMOに注文していたM/Bが届いた。
_GIGABYTE B450M S2H rev. 1.0。
税込7,300円、だった気がする。SocketAM4対応。AMD Ryzen CPU が載せられるはずのM/B。
箱には、Ryzen 3000番台に対応、とシールが貼ってあった。ということは、M/B の BIOS は比較的新しい…状態だったら助かるのだけど、さて。
まだ箱を開けてないけど、日本語マニュアルも同梱、と箱に書いてある…。マニュアルも何もついてこないよ、というレビュー記事を読んだ記憶があるけど、やっぱりつけるようになったのだろうか。ただ、GIGABYTEのサイトには、日本語マニュアルのPDFが無いんだよな…。どういうことだろう…。
箱には、Ryzen 3000番台に対応、とシールが貼ってあった。ということは、M/B の BIOS は比較的新しい…状態だったら助かるのだけど、さて。
まだ箱を開けてないけど、日本語マニュアルも同梱、と箱に書いてある…。マニュアルも何もついてこないよ、というレビュー記事を読んだ記憶があるけど、やっぱりつけるようになったのだろうか。ただ、GIGABYTEのサイトには、日本語マニュアルのPDFが無いんだよな…。どういうことだろう…。
◎ 2020/04/03追記。 :
箱を開けてみたら、日本語で書かれた紙が、底のほうに1枚入ってた。一応、M/B上のどこに何の端子があるのか、図で示してあるけれど、例えば、ケース側のLEDその他を繋ぐ F_PANEL のピン配置などは一切書かれてなかった。やはり、GIGABYTEのサイトから英語版のマニュアルPDFを入手して、必要なページを印刷するなりしておいてから作業を始めたほうが良さそうだなと…。
*1
*1: 徹底的にコスト削減したと謳ってる(?)製品なので、これはこれでOK。マニュアル冊子がついてない分お安くしましたよ、ということだろう…。
[ ツッコむ ]
以上、1 日分です。