2024/12/22(日) [n年前の日記]
#1 [godot] OBになった時の処理をどうするか考え中
_昨日
に続き、Windows10 x64 22H2 + Godot Engine 4.3 64bit でゴルフゲームっぽいものが作れないものかなと試してる。
OBになった時の処理をどうするかで悩んでる。ボールを打った時の座標と、ボールが着地してOBになった時の座標を結んで直線を作って、OBの境界線との交点を求めないとその後の処理ができないのかもしれないな、とか考え始めてしまって…。
ボールを打った点を始点にして、かつ、ボールの着地点を終点にして、その2つの座標のちょうど真ん中の座標で地面の種類をチェックしてみて、そこがOBなら始点側を、OBじゃなければ終点側を対象にして、更に中点の座標を求めてチェックしてみて…。それを延々繰り返せばOBとの境界が見つけられるかな、でもそれって処理が重くならないか、とか考え始めていたのだけど。
そこでふと閃いた。ボールが飛んでいく時の座標をずっと記録しておけば、その座標を逆に辿っていくうちに、いつかはOB以外の場所に出るのではないか。そこがOBとの境界、ということでもいいのでは…。
となると、ボールの座標を記録し続ける処理を書かないといけない。せっかくだから、その座標群を元にして何かを表示すればボールの軌跡が表示できるのでは…。
そんなわけで、ボールの軌跡を表示する処理のほうを先に書き始めてしまった。Sprite3Dを使って、軌跡っぽいものは一応表示できた。
しかし、そこで不安になって、改めてゴルフのOBのルールを調べてみたら…。
OBになった時は打数を+1して、打った場所からもう一度打ち直しをするのが競技ルール、と書いてあって。OBとの境界を求める必要はなかった…。
いやまあ、たしか池に入ったときは、池の手前から打ち直すことになっていた気もするし、どのみちどこかで境界を求める処理が必要になるんだろうけど。少なくともOBについては、OBになった → 打ち直し、で済ませてしまって良さそうだなと…。
もっとも、競技ルールということならそれで済むけれど。ローカルルールとやらでは、やり方が全然変わるようでもあり。色んなパターンがあって、それぞれに対応させようとしたら結構大変なことになりそうだなと…。
_OBの新ルールを図解|どこからプレーできる?処置と救済は? | Honda GOLF | Honda公式サイト
_ゴルフルール改正で最低限知っておきたい 新ルール。バンカーやOBなど厳選5つをおさらい!|初心者ゴルフナビ
_ゴルフのOB、数え方をスッキリ解決! 新ルールや1ペナとの違いも解説【2024年版】 - ゴルフ総合サイト ALBA Net
_OBにはラインとゾーンがある | ルールについて | パークゴルフについて | 公益社団法人日本パークゴルフ協会
解説図を見てもよく分からなかった…。OBの境界線上の位置とピンまでの距離で円を描いたその線がフェアウェイの境界と重なった場所が打ち直し場所、ということでいいのだろうか…。それってフェアウェイと重ならなかったらどうなるんだ? ややこしいな…。
まあ、今回はローカルルールには非対応でいいんじゃないかと…。それ以前に実装しなきゃいけないところがたくさんあるし…。
OBになった時の処理をどうするかで悩んでる。ボールを打った時の座標と、ボールが着地してOBになった時の座標を結んで直線を作って、OBの境界線との交点を求めないとその後の処理ができないのかもしれないな、とか考え始めてしまって…。
ボールを打った点を始点にして、かつ、ボールの着地点を終点にして、その2つの座標のちょうど真ん中の座標で地面の種類をチェックしてみて、そこがOBなら始点側を、OBじゃなければ終点側を対象にして、更に中点の座標を求めてチェックしてみて…。それを延々繰り返せばOBとの境界が見つけられるかな、でもそれって処理が重くならないか、とか考え始めていたのだけど。
そこでふと閃いた。ボールが飛んでいく時の座標をずっと記録しておけば、その座標を逆に辿っていくうちに、いつかはOB以外の場所に出るのではないか。そこがOBとの境界、ということでもいいのでは…。
となると、ボールの座標を記録し続ける処理を書かないといけない。せっかくだから、その座標群を元にして何かを表示すればボールの軌跡が表示できるのでは…。
そんなわけで、ボールの軌跡を表示する処理のほうを先に書き始めてしまった。Sprite3Dを使って、軌跡っぽいものは一応表示できた。
しかし、そこで不安になって、改めてゴルフのOBのルールを調べてみたら…。
OBになった時は打数を+1して、打った場所からもう一度打ち直しをするのが競技ルール、と書いてあって。OBとの境界を求める必要はなかった…。
いやまあ、たしか池に入ったときは、池の手前から打ち直すことになっていた気もするし、どのみちどこかで境界を求める処理が必要になるんだろうけど。少なくともOBについては、OBになった → 打ち直し、で済ませてしまって良さそうだなと…。
もっとも、競技ルールということならそれで済むけれど。ローカルルールとやらでは、やり方が全然変わるようでもあり。色んなパターンがあって、それぞれに対応させようとしたら結構大変なことになりそうだなと…。
_OBの新ルールを図解|どこからプレーできる?処置と救済は? | Honda GOLF | Honda公式サイト
_ゴルフルール改正で最低限知っておきたい 新ルール。バンカーやOBなど厳選5つをおさらい!|初心者ゴルフナビ
_ゴルフのOB、数え方をスッキリ解決! 新ルールや1ペナとの違いも解説【2024年版】 - ゴルフ総合サイト ALBA Net
_OBにはラインとゾーンがある | ルールについて | パークゴルフについて | 公益社団法人日本パークゴルフ協会
解説図を見てもよく分からなかった…。OBの境界線上の位置とピンまでの距離で円を描いたその線がフェアウェイの境界と重なった場所が打ち直し場所、ということでいいのだろうか…。それってフェアウェイと重ならなかったらどうなるんだ? ややこしいな…。
まあ、今回はローカルルールには非対応でいいんじゃないかと…。それ以前に実装しなきゃいけないところがたくさんあるし…。
◎ 配列の宣言がよく分からなかった :
Godot Engine の GDScript で、型を指定しながら配列を宣言するあたりの書き方が分からなくてググってた。
以下のような感じでいいのかな…?
試しに新規プロジェクトを作成して、この書き方でいいのか試してみた。別途作った、Node3D + Sprite3D のシーンを読み込んで、64個複製(?)して毎フレーム座標値を変更する処理。複製したシーン(オブジェクト)を覚えておくために配列を使う。
ちなみに上記は、動かすとこんな感じの見た目になる。
以下のような感じでいいのかな…?
var ary: Array[Node3D] = []
試しに新規プロジェクトを作成して、この書き方でいいのか試してみた。別途作った、Node3D + Sprite3D のシーンを読み込んで、64個複製(?)して毎フレーム座標値を変更する処理。複製したシーン(オブジェクト)を覚えておくために配列を使う。
extends Node3D const ghost_ball = preload("res://ghost_ball.tscn") const BALL_NUM = 64 var ghost_balls: Array[Node3D] = [] var timer = 0 func _ready(): var ghost_node: Node3D = get_node("ghost_balls") for i in range(BALL_NUM): var obj: Node3D = ghost_ball.instantiate() obj.global_position = Vector3.ZERO ghost_node.add_child(obj) ghost_balls.append(obj) func _process(delta): var a = timer * 180.0 for i in range(ghost_balls.size()): var x: float = (i - (BALL_NUM / 2)) * 0.25 var y: float = 2 * sin(deg_to_rad(a + 10 * i)) var z: float = -0.2 * i var obj: Node3D = ghost_balls[i] obj.global_position = Vector3(x, y + 2.5, z) timer += delta
- preload() で、別途作ったシーンを読み込めるようではある。
- 別途作ったシーンのインスタンスを作るには、.instantiate() を使う。
- インスタンスを、.add_child() を使って、既にあるノードの子ノードとして追加しないと表示されないので注意。この一行を書き忘れて、「表示されないな…おかしいな…」とハマってしまった。
- 配列への追加は、.append() を使う。
ちなみに上記は、動かすとこんな感じの見た目になる。
[ ツッコむ ]
以上、1 日分です。