2020/11/17(火) [n年前の日記]
#3 [godot] Godot Engineでプレイヤーが画面端を超えないように補正
Godot Engine 3.2.3 x64 を使って3D表示の簡単なシューティングゲームっぽいものを作る。
今回は、プレイヤーキャラが画面端を超えて移動しないように補正する処理を追加してみる。
Player のスクリプトファイル、res://scripts/Player.gd を修正。追記した内容は以下。
_Player.gd
何をやっているのかというと…。
カメラから見えている範囲のx,z座標を求めるあたりで、なんだか計算が面倒臭いことになっている。
ただ、Godot Engine のことだから、もっと簡単に値を求める機能が既に用意されてそうな気もする。ググってもそのものズバリの情報が出てこなくて、こんな処理を書いてしまったけれど…。もっと良い方法・便利なメソッドがあったら誰か教えてください。みたいな。
おそらく結構ダサいことをしている気もするけれど、何にせよ、これでプレイヤーが画面外に出ない状態になった。
次回は、3DCGソフトの blender で作成した飛行機モデルデータ、敵モデルデータをインポートして、ゲーム画面の見栄えを改善したい。
今回は、プレイヤーキャラが画面端を超えて移動しないように補正する処理を追加してみる。
Player のスクリプトファイル、res://scripts/Player.gd を修正。追記した内容は以下。
_Player.gd
# ... export var padding = 1.7 var camera:Camera var disparea = Vector2() var btopleft = Vector3() var bbottomright = Vector3() func _ready(): # ... init_adjust_work() # ... func _physics_process(delta): # ... adjust_pos(padding) # ... # ... func init_adjust_work(): disparea = get_disp_area() camera = get_tree().root.get_node("Main/Camera") calc_move_area(camera, disparea.x, disparea.y) # get project display width and height func get_disp_area(): var w = ProjectSettings.get_setting("display/window/size/width") var h = ProjectSettings.get_setting("display/window/size/height") return Vector2(w, h) func adjust_pos(padding): if translation.z < btopleft.z + padding: translation.z = btopleft.z + padding if translation.z > bbottomright.z - padding: translation.z = bbottomright.z - padding var zd = btopleft.z - bbottomright.z var lz = translation.z - bbottomright.z var x = lz * (-btopleft.x - bbottomright.x) / zd + bbottomright.x if translation.x > x - padding: translation.x = x - padding if translation.x < -x + padding: translation.x = -x + padding func calc_move_area(camera:Camera, w, h): var cpos:Vector3 = camera.translation var crot:Vector3 = camera.rotation_degrees var fov = camera.fov var d = (h/2) / tan(deg2rad(fov/2)) var p1 = Vector3(-w/2, h/2, -d) var p2 = Vector3(w/2, -h/2, -d) var q1:Vector3 = _get_border(p1, -crot.x, -cpos.y, cpos.z) var q2:Vector3 = _get_border(p2, -crot.x, -cpos.y, cpos.z) btopleft = q1 bbottomright = q2 if false: print("topleft = (%f, %f, %f)" % [q1.x, q1.y, q1.z]) print("bottomright = (%f, %f, %f)" % [q2.x, q2.y, q2.z]) func _get_border(p:Vector3, rotx, y, cz): var v2:Vector2 = _get_rot_pos(p.z, p.y, rotx) var pr = Vector3(p.x, v2.y, v2.x) var x = y * pr.x / pr.y var z = y * pr.z / pr.y + cz return Vector3(x, 0, z) func _get_rot_pos(x, y, ang): var a = deg2rad(ang) var xr = x * cos(a) - y * sin(a) var yr = x * sin(a) + y * cos(a) return Vector2(xr, yr)
何をやっているのかというと…。
- カメラの情報と、プロジェクト設定内のゲームウインドウサイズを取得。(init_adjust_work(), get_disp_area())
- y = 0 の平面上でカメラから見えている範囲を計算。ゲームウインドウ左上の x,z 値と、右下の x,z値を得る。(calc_move_area(camera:Camera, w, h))
- プレイヤーの座標がゲームウインドウ左上・右上の x,z値を超えていたら、超えないような座標値に補正する。(adjust_pos(padding))
カメラから見えている範囲のx,z座標を求めるあたりで、なんだか計算が面倒臭いことになっている。
ただ、Godot Engine のことだから、もっと簡単に値を求める機能が既に用意されてそうな気もする。ググってもそのものズバリの情報が出てこなくて、こんな処理を書いてしまったけれど…。もっと良い方法・便利なメソッドがあったら誰か教えてください。みたいな。
おそらく結構ダサいことをしている気もするけれど、何にせよ、これでプレイヤーが画面外に出ない状態になった。
次回は、3DCGソフトの blender で作成した飛行機モデルデータ、敵モデルデータをインポートして、ゲーム画面の見栄えを改善したい。
◎ 関連ページ。 :
以前このあたりの処理で悩んでいた際に書き残したメモへのリンクも貼っておく。
_mieki256's diary - カメラ情報から自機の移動範囲を求めるソレを考えてるところ
_mieki256's diary - カメラ情報から自機の移動範囲を求めるソレがたぶんできた気がする
_mieki256's diary - カメラ情報から自機の移動範囲を求めるソレを考えてるところ
_mieki256's diary - カメラ情報から自機の移動範囲を求めるソレがたぶんできた気がする
◎ 余談。 :
Godot Engine には、3D空間内の座標が、カメラから見えている範囲の中にあるか、外にあるかを調べるメソッドが用意されているので、それを使って範囲外なら補正する処理を試したこともあったのだけど。
_mieki256's diary - 自機が画面外に行かないようにしたい
そのやり方だと、画面の端でプレイヤーを斜め移動させた時にガタガタした移動になっちゃって、このやり方ではダメだなと諦めた記憶が…。まあ、見た目は酷いけれど、画面外に出さない処理をそういうやり方でやれないこともない…と、一応メモしておきます。
他にも、画面の端に壁相当のオブジェクトを配置しておいて、その壁オブジェクトとプレイヤーでアタリ判定・衝突判定をして、画面外に出ないようにしてしまう、という方法もありそう。ただ、カメラの各プロパティをちょっと修正するたびに、壁オブジェクトの配置についても修正する手間が増えるであろう予感も…。
_mieki256's diary - 自機が画面外に行かないようにしたい
そのやり方だと、画面の端でプレイヤーを斜め移動させた時にガタガタした移動になっちゃって、このやり方ではダメだなと諦めた記憶が…。まあ、見た目は酷いけれど、画面外に出さない処理をそういうやり方でやれないこともない…と、一応メモしておきます。
他にも、画面の端に壁相当のオブジェクトを配置しておいて、その壁オブジェクトとプレイヤーでアタリ判定・衝突判定をして、画面外に出ないようにしてしまう、という方法もありそう。ただ、カメラの各プロパティをちょっと修正するたびに、壁オブジェクトの配置についても修正する手間が増えるであろう予感も…。
[ ツッコむ ]
以上です。