物理挙動 基本的な使い方
目次
はじめに
hgimg4では、ノードに対して物理挙動を簡単に設定できます。 内部的には、Bullet Physics Library( https://pybullet.org/wordpress/ ) が使用されているので、困ったら Bullet(バレット) 関連のサイトを当たるといいかもしれませんね。
使い方も簡単で、付属サンプル(\sample\hgimg4)の、test11.hsp、test13.hsp を参考にするといいと思います。HSP3公式資料はこちらです。
21.物理挙動の設定 - HGIMG4プログラミングガイド
https://www.onionsoft.net/hsp/v36/doclib/hgimg4.html#PHYSICS
gppbind
命令である程度の初期値が設定されるので、結果に合わせて適当に微調整すればいいと思います。
物理的な正確さよりも、一番気持ちいいところを探して調整してください。ゲーム的にはそれが正解で全てです。
これで物理関係の説明は終わりです。
とはいえ物理挙動とは異なる、若干の注意点があるので少し調査してみました。
物理設定をサンプル真似して書いてみた
空中に箱を出現させて、床面まで落下させてみます。 見やすくするためテクスチャを貼り付けています。resフォルダにqbox.pngを準備してください。ファイルは、hgimg4のサンプルの中にあります。
#include "hgimg4.as"
title "HGIMG4"
; 物理エンジンテスト
randomize
; シーン作成
gpreset
setcls CLSMODE_SOLID, $808080 ; 画面クリア設定
; カメラを作成
setpos GPOBJ_CAMERA, 0,1,5 ; カメラ位置を設定
gplookat GPOBJ_CAMERA, 0,0.3,0 ; カメラから指定した座標を見る
; 箱を作成
gptexmat id_texmat, "res/qbox.png"
gpbox id_box, 0.5, -1, id_texmat ; 箱ノードを追加
setpos id_box, 0, 1, 0
gppbind id_box, 1, 0.5 ; 箱の物理設定を行なう
; 床を作成
gpfloor id_floor, 30,30, $404040 ; 床ノードを追加
gppbind id_floor, 0 ; 床の物理設定を行なう
*main
stick key,15
if key&128 : end
; 描画
redraw 0 ; 描画開始
gpdraw ; シーンの描画
color 255,255,255
pos 8,8:mes "HGIMG4 sample"
redraw 1 ; 描画終了
await 1000/60 ; 待ち時間
goto *main
実行すると空中の箱が床面に落下して少しだけバウンドします。
gptexmat id_texmat, "res/qbox.png"
gpbox id_box, 0.5, -1, id_texmat ; 箱ノードを追加
setpos id_box, 0, 1, 0
gppbind id_box, 1, 0.5 ; 箱の物理設定を行なう
gpbox
で1辺 0.5m の箱ノードを追加後、setposで初期位置(0,1,0)に配置したらgppbind
で物理設定を行います。
1kgの質量と実体を持つ箱が出来上がりました。
gpfloor id_floor, 30,30, $404040 ; 床ノードを追加
gppbind id_floor, 0 ; 床の物理設定を行なう
床がないと箱は落下し続けるので、床を作ります。床も物理設定を行わないと、箱は床をすり抜けます。
物理設定は、箱、床、板、gpbモデルノードに指定できます。マニュアルには「ヌルノード」は書かれていませんね。機会があったら試してみようかな。
物理設定したノードのsetposとsetang
HDLでのgppbind
の説明には次のように記述されています。
物理設定を行なったノードオブジェクトは、それ以降自立して動作するようになり、setpos
などの座標変更は無効となります。
物理設定を行った後の物体の操作は、gppapply
で物体に力を加えたり物体同士の衝突などを使って行います。
それはそうでしょうね。setpos
で座標を直接指定するなら物理挙動を設定する意味がありませんから。
本当に無効になるのか確認してみました。
#include "hgimg4.as"
title "HGIMG4 setpos"
; 物理エンジンテスト
; setpos
;
randomize
; シーン作成
gpreset
setcls CLSMODE_SOLID, $808080 ; 画面クリア設定
; カメラを作成
setpos GPOBJ_CAMERA, 0,1,5 ; カメラ位置を設定
gplookat GPOBJ_CAMERA, 0,0.3,0 ; カメラから指定した座標を見る
; 箱を作成
gptexmat id_texmat, "res/qbox.png"
gpbox id_box, 0.5, -1, id_texmat ; 箱ノードを追加
setpos id_box, 0, 1, 0
gppbind id_box, 1, 0.5 ; 箱の物理設定を行なう
; 無効になる機能
; 物理挙動をOFFにするとsetposとsetangは使用できます。
;gppset id_box, GPPSET_ENABLE, 0
; 物理特性を設定した後では、setposは使用できなくなります。
setpos id_box, 1, 1, 1
; setangも使用できなくなります。
setang id_box, 0,0,deg2rad(40)
; 物理挙動をON
;gppset id_box, GPPSET_ENABLE, 1
;これは設定できる。
;setscale id_box, 0.5,0.5,0.5
; 床を作成
gpfloor id_floor, 30,30, $404040 ; 床ノードを追加
gppbind id_floor, 0 ; 床の物理設定を行なう
*main
stick key,15
if key&128 : end
; setposが適用される条件
; 床などに設置して動きがなくなるとsetposが適用できるようになります。
; setposを使用後は、gppbindを再度適用するまで物理挙動を行いません。
posx0 = posx
posy0 = posy
posz0 = posz
getpos id_box, posx,posy,posz
; 移動量を計算
x = posx - posx0
y = posy - posy0
z = posz - posz0
; ある程度動きが小さくなると、移動量がゼロにリセットされるようです。
;if (x=0.0) & (y=0.0) & (z=0.0) {
; 動いていなければsetposが適用できてしまいます。
setpos id_box, 0, 2, 0
setang id_box, 0,0,deg2rad(40)
; setposが実行できてしまった後は、物理挙動が無効になります。
; gppset id_box, GPPSET_ENABLE, 1 ; 物理挙動をONにするだけでは、物理挙動は有効になりません。
; gppbind id_box, 1, 0.5 ; 再度物理特性を設定する必要があります。
;}
; 描画
redraw 0 ; 描画開始
gpdraw ; シーンの描画
color 255,255,255
pos 8,8:mes "HGIMG4 sample"
mes strf("移動量 (%f, %f, %f)", x,y,z)
redraw 1 ; 描画終了
await 1000/60 ; 待ち時間
goto *main
実行すると箱が床に落下します。しばらく待って箱が静止すると、setpos
とsetang
で指定した場所に移動して物理設定が無効になります。
; 物理特性を設定した後では、setposは使用できなくなります。
setpos id_box, 1, 1, 1
; setangも使用できなくなります。
setang id_box, 0,0,deg2rad(40)
gppbind
で物理設定直後にsetpos
とsetang
を実行していますが、結果には反映されていません。
確かに物理設定を行った後は、setpos
とsetang
が無効になりました。
; ある程度動きが小さくなると、移動量がゼロにリセットされるようです。
;if (x=0.0) & (y=0.0) & (z=0.0) {
; 動いていなければsetposが適用できてしまいます。
setpos id_box, 0, 2, 0
setang id_box, 0,0,deg2rad(45)
; setposが実行できてしまった後は、物理挙動が無効になります。
; gppset id_box, GPPSET_ENABLE, 1 ; 物理挙動をONにするだけでは、物理挙動は有効になりません。
; gppbind id_box, 1, 0.5 ; 再度物理特性を設定する必要があります。
;}
しかし移動量が(0,0,0)になると、setpos
とsetang
が設定できるようになりました。
しかも物理設定が無効になってしまいました。再度gppbind
を実行するまで物理設定は有効にできません。
物理設定が削除されているのか、GPPSET_ENABLE による物理挙動ONでは有効にできませんでした。
問題として、次のようなケースが考えられます。
gppbind
で物理設定を行った後は、getpos
は絶対に適用されることがない。
と過信して物理設定後もgetpos
を実行する処理をスキップしないようにしていた場合、思わぬところでgetpos
が有効に動作して物理設定もOFFになってしまう。
ということがあるかもしれません。
自分が意図しないところで物理挙動が無効にされないようsetpos
とsetang
の扱いは注意したほうが良さそうです。
意図的に物理設定を削除したい場合は有効なテクニックかもしれませんが、実際にはそういった状況はないと思います。 物理挙動を設定した後に設置座標や向きを変更したい場合は、次のように設定します。
; 物理挙動をOFFにするとsetposとsetangは使用できます。
gppset id_box, GPPSET_ENABLE, 0
setpos id_box, 1, 1, 1
setang id_box, 0,0,deg2rad(40)
; 物理挙動をON
gppset id_box, GPPSET_ENABLE, 1
この方法ならgppbind
で質量や摩擦係数を再設定する必要がありません。
まとめ
gppbind
を適用すると物理挙動するようになる。- 物理設定をしたら、
setpos
とsetang
は使わない。 - 物理設定をしていても
setpos
とsetang
が使えてしまう場合がある。この場合は物理設定も解除される。 - 物理設定をした後に
setpos
とsetang
いたい場合は、GPPSET_ENABLEで一旦物理挙動をOFFにする。
今回のまとめは、こんな感じでしょうか。物理的な意味を考えたら、setpos
とsetang
が使えないのは納得です。
使えてしまう場合があるのは問題ですね。どういうケースを想定してるんだろう?