物理挙動への制約

目次

はじめに

 物理挙動は設定するだけで、物体に自然な動きをさせることができます。 しかし箱の山を作っただけでは、ゲームに使うには少し不便です。

 タイヤが付いた乗り物のように移動方向が制約された物体や 回転扉のように回転だけしかしない物体など、一部の動きが制約された物体がゲームには必要になってきます。 setpossetangなどで直接数値を指定して制御することもできますが、とても面倒です。また何より、せっかくの物理挙動を活かすことができません。

 hgimg4では物理挙動を設定した物体に対して、gppset命令で加えられた力に対する動きに制約(動きにくくする)を設定することができます。 正確には外力をそのまま物体に与えるのではなく、方向ごとに重み付け(部分的に弱く)した結果を物体に入力する方法です。 まずは「ある方向にだけ動かなくできる」と理解しておくとわかりやすいと思います。

回転

 つまりどういうことかというと…とりあえず例を見てください。


; 回転方向に制約を付けるサンプル
#include "hgimg4.as"

title "HGIMG4"

	;	物理エンジンテスト
	randomize

	;	シーン作成
	gpreset
	setcls CLSMODE_SOLID, $808080		; 画面クリア設定

	;	カメラを作成
	setpos GPOBJ_CAMERA, 0,1,8			; カメラ位置を設定
	gplookat GPOBJ_CAMERA, 0,0.3,0		; カメラから指定した座標を見る

	;	箱を作成
	gptexmat id_texmat, "res/qbox.png"
	gpbox   id_box,  1, -1, id_texmat		; 箱ノードを追加
	setpos  id_box,	-3, 0, 0
	gppbind id_box, 1						; 箱の物理設定を行なう
	gppset id_box, GPPSET_GRAVITY,  0, 0, 0	; 重力なし
	gppset id_box, GPPSET_DAMPING,  0, 0	; 減衰なし
	
	;	箱(クローン)を作成
	dim pos_boxc, 3
	repeat 3
		gpclone id_boxc(cnt), id_box			; 箱をクローン
		setpos  id_boxc(cnt), 2.0 * (cnt + 1) - 3, 0, 0
		gppbind id_boxc(cnt), 1
		gppset id_boxc(cnt), GPPSET_GRAVITY, 0,0,0	; 重力なし
		gppset id_boxc(cnt), GPPSET_DAMPING,  0, 0	; 減衰なし
	loop
	
	;	Constraints(制約)
	; 動かせる方向にConstraints(制約)を付けることができます。
	; 1を指定した場合、特に制約を受けることなく回転します。
	; 0を指定した方向には、物理的外力を加えても回転しなくなります。
	;
	; 正確には外部から入力されたトルクに対して、指定した値を掛け算しているようです。
	; 例えば10を指定すると10倍回転しやすくなりますし、-1を指定すると逆回転します。
	; UnityのConstraintのWeightが同じような機能らしいです。
	gppset id_boxc(0), GPPSET_ANGULAR_FACTOR, 1, 0, 0	; X軸周りにのみ回転
	gppset id_boxc(1), GPPSET_ANGULAR_FACTOR, 0, 1, 0	; Y軸周りにのみ回転
	gppset id_boxc(2), GPPSET_ANGULAR_FACTOR, 0, 0, 1	; Z軸周りにのみ回転

	;	回転を設定
	; GPPSET_ANGULAR_FACTORで制約を設定しても、gppsetで直接値を指定した場合は
	; Constraintsを無視して回転します。
	; 「if 1」に書き換えると挙動を確認できます。
	if 0 {
		gppset id_box, GPPSET_ANGULAR_VELOCITY, 1,1,1
		repeat 3
			gppset id_boxc(cnt), GPPSET_ANGULAR_VELOCITY, 1,1,1
		loop
	}



*main
	stick key,15
	key_x0 = key_x
	key_y0 = key_y
	key_z0 = key_z
	getkey key_x, 'X'
	getkey key_y, 'Y'
	getkey key_z, 'Z'
	
	if key&128 : end
	if key&16 {
		; 回転トルク+衝撃を追加
		gppapply id_box, GPPAPPLY_TORQUE_IMPULSE, 1,1,1
		repeat 3
			gppapply id_boxc(cnt), GPPAPPLY_TORQUE_IMPULSE, 1,1,1
		loop
	}
	if (key_x = 1) & (key_x0 = 0) {
		; X 回転トルク+衝撃を追加
		gppapply id_box, GPPAPPLY_TORQUE_IMPULSE, 1,0,0
		repeat 3
			gppapply id_boxc(cnt), GPPAPPLY_TORQUE_IMPULSE, 1,0,0
		loop
	}
	if (key_y = 1) & (key_y0 = 0) {
		; Y 回転トルク+衝撃を追加
		gppapply id_box, GPPAPPLY_TORQUE_IMPULSE, 0,1,0
		repeat 3
			gppapply id_boxc(cnt), GPPAPPLY_TORQUE_IMPULSE, 0,1,0
		loop
	}
	if (key_z = 1) & (key_z0 = 0) {
		; Z 回転トルク+衝撃を追加
		gppapply id_box, GPPAPPLY_TORQUE_IMPULSE, 0,0,1
		repeat 3
			gppapply id_boxc(cnt), GPPAPPLY_TORQUE_IMPULSE, 0,0,1
		loop
	}


	;	描画
	redraw 0			; 描画開始
		gpdraw				; シーンの描画
	
		color 255,255,255
		pos 8,8:mes "HGIMG4 sample"
		mes "スペース:X,Y,Z軸方向に回転加速"
		mes "       X:X 軸方向に回転加速"
		mes "       Y:Y 軸方向に回転加速"
		mes "       Z:Z 軸方向に回転加速"

		gpcnvaxis x,y,z, -3, -0.8, 0.5, 0 : pos x-16*2,y : mes "制約なし"
		gpcnvaxis x,y,z, -1, -0.8, 0.5, 0 : pos x-16*2,y : mes "YZ軸制約\nX軸のみ回転"
		gpcnvaxis x,y,z,  1, -0.8, 0.5, 0 : pos x-16*2,y : mes "XZ軸制約\nY軸のみ回転"
		gpcnvaxis x,y,z,  3, -0.8, 0.5, 0 : pos x-16*2,y : mes "XY軸制約\nZ軸のみ回転"

	redraw 1			; 描画終了
	await 1000/60			; 待ち時間

	goto *main

 実行すると、箱が4つ現れます。箱の下に、動きに制約をかけている方向が書いてあります。 左上の説明通りにキーを押すと、箱に対して指定の方向へトルク(GPPAPPLY_TORQUE_IMPULSE)が与えられます。4つの箱すべて同時に同じ大きさのトルクを与えます。

 一番左の箱は何も制約がないので、トルクを与えられればその方向に回転します。他の箱には、回らない方向が設定してあるので、回る方向にしか回りません。 適当に触っていただければ、どういうことかすぐにわかると思います。

 HSP3で回転方向への制約(Constraints)を設定する場合、次のように記述します。X軸周りにのみ回転するようにする例です。


gppset id, GPPSET_ANGULAR_FACTOR, 1, 0, 0

 0を指定するとその方向に回転しなくなります。1を設定しておけば、その方向へは通常通り回転します。

 そしてさらに-1を設定すると、与えられたトルクと反対方向に回転します。 そうです。この機能は動く方向をON/OFFするものではなく、力に対する重み(weight)を指定するものです。 ですので、0.5なども指定できます。

 この方法は、外部から入力されたトルクに対して重みを掛け算してから物体にトルクを入力しています。 例えば10を指定すると10倍回転しやすくなりますし、-1を指定すると逆回転します。 UnityのConstraintのWeightが同じような機能らしいです。

移動

 移動方向についても、制約(正確には重み)を設定することができます。

 次のように記述すると、X方向にだけ移動するようになります。(YZ方向に動かなくなる。)


gppset id, GPPSET_LINEAR_FACTOR, 1, 0, 0

 移動の場合も回転同様に、動く方向をON/OFFするものではなく、力に対する重み(weight)を指定するものです。 ですので、0.5なども指定できます。

 挙動については、サンプルで確認してください。


; 動きに制限をつけるサンプル
;
; 次の設定をテストするサンプルです。
;
;	GPPSET_LINEAR_FACTOR  ベクトルに沿った移動の設定
;	GPPSET_ANGULAR_FACTOR ベクトルに沿った回転の設定
;
; 体当たりで押したり、床から落としたりして動きを確認してください。
;
#include "hgimg4.as"

title "HGIMG4 Test"

	;	物理エンジンテスト
	;	カーソルキーで箱を動かすことができます
	;
	randomize
	gpreset
	setcls CLSMODE_SOLID, $808080		; 画面クリア設定
	setpos GPOBJ_CAMERA, 0,2,5		; カメラ位置を設定

	; 箱ノードを追加
	gptexmat id_texmat, "res/qbox.png"
	gpbox id_box, 0.5, -1, id_texmat
	setpos id_box,	0, 3, 0
	gppbind id_box, 1, 0.5				; 箱の物理設定を行なう

	; 床ノードを追加
	gpfloor id_floor, 10,5, $404040
	gppbind id_floor, 0				; 床の物理設定を行なう

	;	箱を追加
	dz = 2.0
	dim id_boxc, 8
	repeat 8
		gpclone id_boxc(cnt), id_box
		dx = 1.0 * cnt - 4.0
		setpos  id_boxc(cnt), dx, 0.6, dz
		gppbind id_boxc(cnt), 1, 0.5
	loop
	; 移動を固定
	gppset id_boxc(0), GPPSET_LINEAR_FACTOR, 1,0,0	; x方向のみ動く
	gppset id_boxc(1), GPPSET_LINEAR_FACTOR, 0,1,0	; y方向のみ動く
	gppset id_boxc(2), GPPSET_LINEAR_FACTOR, 0,0,1	; z方向のみ動く
	gppset id_boxc(3), GPPSET_LINEAR_FACTOR, 0,0,0	; 移動を固定
	; 回転を固定	
	gppset id_boxc(4), GPPSET_ANGULAR_FACTOR, 1,0,0	; x軸方向の回転のみ動く
	gppset id_boxc(5), GPPSET_ANGULAR_FACTOR, 0,1,0	; y軸方向の回転のみ動く
	gppset id_boxc(6), GPPSET_ANGULAR_FACTOR, 0,0,1	; z軸方向の回転のみ動く
	gppset id_boxc(7), GPPSET_ANGULAR_FACTOR, 0,0,0	; 回転を固定


repeat
	stick key,15
	if key&128 : end

	;	カーソルキーで箱を動かす
	if key&1 : gppapply id_box,GPPAPPLY_IMPULSE, -0.1, 0, 0
	if key&4 : gppapply id_box,GPPAPPLY_IMPULSE, 0.1, 0, 0
	if key&8 : gppapply id_box,GPPAPPLY_IMPULSE, 0,0, 0.1
	if key&2 : gppapply id_box,GPPAPPLY_IMPULSE, 0,0, -0.1

	getpos id_box,dx,dy,dz
	gplookat GPOBJ_CAMERA, dx,dy,dz		; カメラから指定した座標を見る

	redraw 0			; 描画開始

	gpdraw				; シーンの描画

	color 255,255,255
	pos 8,8:mes "HGIMG4 sample"

	redraw 1			; 描画終了
	await 1000/60			; 待ち時間

loop

 左半分が移動を制約したもの。右半分が回転を制約しています。 押したり落としたりして挙動を確認してください。

 Y軸方向にしか回転しないようにした箱は、少し不思議な動きをしています。箱の中心を軸に回転していませんね。 箱はX,Y軸方向に回転しないため、常に面同士で床と接触した状態です。そのために、回転中心が計算の優先順位等で決まってしまっているのかもしれません。 原因はわかりませんが、平面に置いた箱のX,Z軸方向を固定してしまうと角に限らず予期しない点を中心に回転してしまうことがあります。

 さて、GPPSET_ANGULAR_FACTORGPPSET_LINEAR_FACTORで指定する値は、係数として使用されるだけなので1.0以上やマイナス値も指定することもできます。 物理的な意味を理解した上で必要であれば、0.0~1.0以外の値を指定するのもいいと思います。 しかし、実際に指定してみると挙動が不自然なものになるので、基本的には0.0~1.0の間で指定するようにした方がいいようです。0.0~1.0の範囲外の値を指定すると、計算結果が正しいのかもちょっと怪しい動きをします。検証していないので断言できませんが避けた方がいいでしょう。

摩擦

 gppsetを使うと、摩擦も方向に対して制約をつけることができます。

 次のように記述すると、X方向の摩擦だけがなくなります。(YZ方向の摩擦はそのまま。)


gppset id, GPPSET_ANISOTROPIC_FRICTION, 0,1,1

 摩擦の場合も移動同様に、摩擦力をON/OFFするものではなく、摩擦力に対する重み(weight)を指定するものです。 ですので、0.5なども指定できます。

 摩擦も基本的には0.0~1.0を指定した方がいいようです。 摩擦を大きくしたい場合は、GPPSET_FRICTION を使って全体の摩擦を大きくしてください。 GPPSET_ANISOTROPIC_FRICTIONで1.0以上を設定した場合と、GPPSET_FRICTIONで1.0以上を設定した場合とでは動作結果が異なります。 どうやら単純に摩擦が大きくなるわけではなさそうです。

 サンプルを用意しました。回転するとわかりにくいので、回転は止めています。


; 動きに制限をつけるサンプル
;
; 次の設定をテストするサンプルです。
;
;	GPPSET_LINEAR_FACTOR  ベクトルに沿った移動の設定
;	GPPSET_ANGULAR_FACTOR ベクトルに沿った回転の設定
;
; 体当たりで押したり、床から落としたりして動きを確認してください。
;
#include "hgimg4.as"

title "HGIMG4 Test"

	;	物理エンジンテスト
	;	カーソルキーで箱を動かすことができます
	;
	randomize
	gpreset
	setcls CLSMODE_SOLID, $808080		; 画面クリア設定
	setpos GPOBJ_CAMERA, 0,2,5		; カメラ位置を設定

	; 箱ノードを追加
	gptexmat id_texmat, "res/qbox.png"
	gpbox   id_box, 0.5, -1, id_texmat
	setpos  id_box,	0, 3, 0
	gppbind id_box, 1, 0.5				; 箱の物理設定を行なう
	gppset  id_box, GPPSET_ANGULAR_FACTOR, 0,0,0	; 回転を固定

	; 床ノードを追加
	gpfloor id_floor, 30,30, $404040
	gppbind id_floor, 0				; 床の物理設定を行なう

	;	箱を追加
	dz = 2.0
	dim id_boxc, 5
	repeat 5
		gpclone id_boxc(cnt), id_box
		dx = 1.0 * cnt - 2.0
		setpos  id_boxc(cnt), dx, 0.6, dz
		gppbind id_boxc(cnt), 1, 0.5
		gppset  id_boxc(cnt), GPPSET_FRICTION, 30	; 摩擦を大きくする
	loop
	; 移動を固定
	gppset id_boxc(0), GPPSET_ANISOTROPIC_FRICTION, 1,0,0	; x方向以外の摩擦を0にする
	gppset id_boxc(1), GPPSET_ANISOTROPIC_FRICTION, 0,1,0	; y方向以外の摩擦を0にする
	gppset id_boxc(2), GPPSET_ANISOTROPIC_FRICTION, 0,0,1	; z方向以外の摩擦を0にする
	gppset id_boxc(3), GPPSET_ANISOTROPIC_FRICTION, 0,0,0	; すべての摩擦を0にする


repeat
	stick key,15
	if key&128 : end

	;	カーソルキーで箱を動かす
	if key&1 : gppapply id_box,GPPAPPLY_IMPULSE, -0.1, 0, 0
	if key&4 : gppapply id_box,GPPAPPLY_IMPULSE, 0.1, 0, 0
	if key&8 : gppapply id_box,GPPAPPLY_IMPULSE, 0,0, 0.1
	if key&2 : gppapply id_box,GPPAPPLY_IMPULSE, 0,0, -0.1

	getpos id_box,dx,dy,dz
	gplookat GPOBJ_CAMERA, dx,dy,dz		; カメラから指定した座標を見る

	redraw 0			; 描画開始

	gpdraw				; シーンの描画

	color 255,255,255
	pos 8,8:mes "HGIMG4 sample"

	redraw 1			; 描画終了
	await 1000/60			; 待ち時間

loop

 乗り物系とか作れそうですね。

シーソーとすり抜け

 では、これらの方法を応用して、身近で手軽に出来る物理おもちゃ「シーソー」を作ってみます。 公園に設置してあったり、天秤ばかりやテコの原理でもおなじみです。 ゲームにも使えそうですね。

 では作ってみます。箱を細長く作って、 GPPSET_LINEAR_FACTOR, 0,0,0 で移動を止めて、 GPPSET_ANGULAR_FACTOR, 0,0,1 で回転を1方向にだけ動くように制約すれば完成です。 簡単ですね。 では、サンプルを見てみます。

 サンプルは、シーソーの上に乗っている箱をカーソルキーで移動できます。 左右に動かしてシーソーを動かしてみてください。


#include "hgimg4.as"

title "HGIMG4 トルク"

	;	物理エンジンテスト
	;	シーソー
	
	;	シーン作成
	gpreset
	setcls CLSMODE_SOLID, $808080

	;	カメラを作成
	setpos   GPOBJ_CAMERA, 0, 3, 10
	gplookat GPOBJ_CAMERA, 0, 0.3, 0

	;	床を作成
	gpfloor id_floor, 30,30, $404040
	setpos  id_floor, 0, 0, 0
	gppbind id_floor, 0

	;	マットを追加
	; 「if 1」を「if 0」に書き換えるとマットを消せます。
	if 1 {
		gpbox    id_mat, 0.5, $0055AA
		setscale id_mat, 30, 0.1, 30
		setpos   id_mat, 0, 0.05, 0
		gppbind  id_mat, 1e10
		; gppset   id_mat, GPPSET_KINEMATIC, 1	; 大丈夫
		; gppbind  id_mat, 0	; すり抜ける
	}

	;	シーソーを作成
	gptexmat id_texmat, "res/qbox.png"
	gpbox    id_s, 1, -1, id_texmat
	setscale id_s, 10, 0.2, 1
	setpos   id_s, 0, 1, 0
	gppbind  id_s, 1
	gppset   id_s, GPPSET_ANGULAR_FACTOR, 0,0,1	; 回転を固定
	gppset   id_s, GPPSET_LINEAR_FACTOR,  0,0,0	; 移動を固定
	; gppset   id_s, GPPSET_LINEAR_FACTOR,  0, 0, 1e-10	; 移動を固定

	; 箱ノードを追加
	gpbox   id_box, 0.5, -1, id_texmat
	setpos  id_box,	0, 3, 0
	gppbind id_box, 1, 0.5
	gppset  id_box, GPPSET_LINEAR_FACTOR,  1,1,0	; 移動を固定
	gppset  id_box, GPPSET_ANGULAR_FACTOR, 1,0,1	; 回転を固定


*main
	stick key,15
	if key&128 : end

	;	カーソルキーで箱を動かす
	if key&1 : gppapply id_box,GPPAPPLY_IMPULSE, -0.1, 0, 0
	if key&4 : gppapply id_box,GPPAPPLY_IMPULSE, 0.1, 0, 0

	getpos id_box,dx,dy,dz
	gplookat GPOBJ_CAMERA, dx,dy,dz		; カメラから指定した座標を見る


	;	描画
	redraw 0			; 描画開始
		gpdraw				; シーンの描画
	
		color 255,255,255
		pos 8,8:mes "HGIMG4 sample"

	redraw 1			; 描画終了
	await 1000/60			; 待ち時間

	goto *main

サンプルを実行した結果の画像。青い床の上に右に傾いたシーソーがある。

 ちゃんと左右に傾くシーソーができていますね。 シーソーから落ちたら戻れないのでEscキーを押して終了してください。

 え、青い床が気になりますか。そうですか。 青いマットは「マットを追加」の「if 1」を「if 0」に書き換えると消すことができます。

青い床を消した実行結果。シーソーが床にめり込んでいる。

 シーソーが床に突き刺さりました。 どういうわけかシーソーを作ると、普段は衝突するものでも衝突しなくなる条件があるようです。バグかな?調査してみました。

 すり抜ける物体

  • 質量0の静的剛体
  • GPPSET_LINEAR_FACTORでどの方向にも完全に移動しないように設定した物体

 すり抜けない対策(いずれか一つを対策すればOK)

  • 床には質量がある物体を使用する。(サンプルで使用している方法)
  • 床の固定には静的剛体ではなく、Kinematic設定を使用する。
  • シーソー自体の移動を完全に固定しないようにする。
    例:gppset id_s, GPPSET_LINEAR_FACTOR, 0, 0, 1e-10

 このサンプルでは、物理設定だけ行った薄い板を床に敷いています。 軽いと跳ねたり動いたりしてしまうので、質量には大きな値を設定しています。

 おそらく、GPPSET_LINEAR_FACTORでの制約を全方向ゼロにしちゃうと、hgimg4内部での物理計算する際の処理方法が変わってしまうのだと思います。 移動は完全に固定せずに。どれか1方向だけでも影響がない程度の小さい値を設定するのが正解なのかなと思います。

シーソーのを元の姿勢に戻す

 作ったシーソーは重心で支持されているので、上に物が乗っていなければ摩擦で止まったときの状態で静止してしまいます。 ゲーム的には元の姿勢に戻ってほしいですね。 物理設定を一時的に解除して、setangで戻すのもいいのですが動きが不連続になるので不自然です。 また、「キャラクターがシーソーを離れた」などの条件分岐をその都度考えなければいけないのも面倒です。

 シーソーには勝手に元の水平姿勢に戻ってもらいましょう。


#include "hgimg4.as"

title "HGIMG4 トルク"

	;	物理エンジンテスト
	;	シーソー
	;元に戻す機構
	
	;	シーン作成
	gpreset
	setcls CLSMODE_SOLID, $808080

	;	カメラを作成
	setpos   GPOBJ_CAMERA, 0, 3, 10
	gplookat GPOBJ_CAMERA, 0, 0.3, 0

	;	床を作成
	gpfloor id_floor, 30,30, $404040
	setpos  id_floor, 0, 0, 0
	gppbind id_floor, 0

	;	シーソーを作成
	gptexmat id_texmat, "res/qbox.png"
	gpbox    id_s, 1, -1, id_texmat
	setscale id_s, 10, 0.2, 1
	setpos   id_s, 0, 1, 0
	gppbind  id_s, 5
	gppset   id_s, GPPSET_ANGULAR_FACTOR, 0,0,1	; 回転を固定
	gppset   id_s, GPPSET_LINEAR_FACTOR,  0, 0, 1e-10	; 移動を固定

	; 箱ノードを追加
	gpbox   id_box, 0.5, -1, id_texmat
	setpos  id_box,	0, 3, 0
	gppbind id_box, 1, 0.5
	gppset  id_box, GPPSET_LINEAR_FACTOR,  1,1,0	; 移動を固定
	gppset  id_box, GPPSET_ANGULAR_FACTOR, 1,0,1	; 回転を固定

	; 台
	gpclone  id, id_box
	setscale id, 2, 2.5, 1
	setpos   id, 5.6, 0.6, 0
	gppbind  id, 0

	gpclone  id, id_box
	setscale id, 1, 8, 1
	setpos   id, 6.5, 2, 0
	gppbind  id, 0

	gpclone  id, id_box
	setscale id, 2, 2.5, 1
	setpos   id, -5.6, 0.6, 0
	gppbind  id, 0

	gpclone  id, id_box
	setscale id, 1, 8, 1
	setpos   id, -6.5, 2, 0
	gppbind  id, 0


*main
	stick key,15
	if key&128 : end

	;	カーソルキーで箱を動かす
	if key&1 : gppapply id_box,GPPAPPLY_IMPULSE, -0.2, 0, 0
	if key&4 : gppapply id_box,GPPAPPLY_IMPULSE, 0.2, 0, 0

	getpos id_box,dx,dy,dz
	gplookat GPOBJ_CAMERA, dx,dy,dz		; カメラから指定した座標を見る

	;	シーソーを戻す
	; シーソーの真下に重りを固定しているような状態を作っています。
	getang id_s, x,y,z
	gppapply id_s, GPPAPPLY_TORQUE, 0, 0, -80.0 * sin(z)


	;	描画
	redraw 0			; 描画開始
		gpdraw				; シーンの描画
	
		color 255,255,255
		pos 8,8:mes "HGIMG4 sample"

	redraw 1			; 描画終了
	await 1000/60			; 待ち時間

	goto *main

 箱をシーソーから降ろしてみてください。シーソーがゆっくり水平に戻りましたね。 仕組みは簡単で、シーソーの下に重りを固定しています。正確には重りが固定されているかのようなトルクをシーソーに入力しています。 図にするとこのような感じです。

シーソーとおもりの位置を示した図

 プログラム上では、このように実装しています。


getang id_s, x,y,z
gppapply id_s, GPPAPPLY_TORQUE, 0, 0, -80.0 * sin(z)

 シーソーが傾く角度に応じて、元の姿勢に戻る方向のトルクを与えています。sinなので、シーソーの傾きが0度の時はトルクもゼロ、90度のときにトルクは最大になりますね。 この実装例の場合、シーソーの下に1mの棒を伸ばしてその先端におよそ8.1kgの重りをつけている状態です。
80N = 8.1kg * 9.8m/s^2 (青い矢印)
重心周りの力(赤い矢印)は、次のような式。
80N * sin(傾き角度)
サンプルで80と設定している係数に根拠はありません。様子を見ながら適当に調整しました。

 全く同じ要領で水平以外の角度に戻るようなものも作ることができますね。

まとめ

  • GPPSET_LINEAR_FACTOR 移動する力を受ける大きさを方向ごとに変更。数値は0~1の係数。
  • GPPSET_ANGULAR_FACTOR 回転する力を受ける大きさを軸方向ごとに変更。数値は0~1の係数。
  • GPPSET_ANISOTROPIC_FRICTION 摩擦を受ける強さを方向ごとに変更。数値は0~1の係数。
  • GPPSET_LINEAR_FACTORで移動を全方向完全に止めてしまうとすり抜けが発生することがある。移動を完全に止めなければ大丈夫。

 方向ごとに差がある性質を与えることができるようになると、箱型形状だけでも出来ることが増えます。 ステージ上に配置するギミックも楽しいものが作れるようになります。

関連記事

  1. 物理挙動 基本的な使い方 はじめに 物理設定をサンプル真似して書いてみた 物理設定したノードのsetposとsetang まと...
  2. 物理挙動 単位と力 はじめに 重力加速度と単位 gppapply 力 gppapply 力積 まとめ  hgimg4では...
  3. 物理挙動 回転 はじめに gppapply 力のモーメント・トルク 静的剛体とKinematic剛体 gppappl...
  4. 浮力表現  ゲームフィールド内の通行禁止領域どうしよう? 見えない壁というのも、通れるように見えて通れないのは...