Box2dの天秤の傾き調整がうまくいかない
Box2dの天秤の傾き調整がうまくいかない
今Box2dのC++で天秤の皿に物質が乗った時に皿にかかる質量によって傾き方を調整したいのですが、
皿にどのくらいの質量がかかったか、求め方がわかりません。
主軸の画像と天秤皿を支えている横棒でジョイントをつないで、
そこのジョイント処理で傾き制限をしようと思っています。
目標としては下のサイトのような感じです
http://www.game-box.jp/~flashtown/link2 ... sattck.php
フラッシュゲームにするつもりではないので、それでもわかるというかたがいたらぜひ教えてください。
よろしくお願いします。
雑な作りの天秤画像になっておりますがそこら辺は勘弁してください。
皿にどのくらいの質量がかかったか、求め方がわかりません。
主軸の画像と天秤皿を支えている横棒でジョイントをつないで、
そこのジョイント処理で傾き制限をしようと思っています。
目標としては下のサイトのような感じです
http://www.game-box.jp/~flashtown/link2 ... sattck.php
フラッシュゲームにするつもりではないので、それでもわかるというかたがいたらぜひ教えてください。
よろしくお願いします。
雑な作りの天秤画像になっておりますがそこら辺は勘弁してください。
Re:Box2dの天秤の傾き調整がうまくいかない
> 皿にどのくらいの質量がかかったか、求め方がわかりません。
質量がかかったかではなく、重量がかかったかでは?
まあ、それはよいとして、どのような分銅? を載せるか、その方法を決めないことには先に進まないのではないでしょうか?
質量がかかったかではなく、重量がかかったかでは?
まあ、それはよいとして、どのような分銅? を載せるか、その方法を決めないことには先に進まないのではないでしょうか?
Re:Box2dの天秤の傾き調整がうまくいかない
>皿にどのくらいの質量がかかったか、求め方がわかりません
Box2dを使うなら b2Body::GetMass関数で取得できますので、
皿の上の全てのオブジェクトの値を足せば求まりますが。
リンク先の Flashが目標だとすると、このゲーム内での Box2Dは使いどころが難しいですね。
このゲームの肝であるバランス部分を真面目に物理演算してしまうと、
調整がかなり大変になりそうな気がします。
Box2dを使うなら b2Body::GetMass関数で取得できますので、
皿の上の全てのオブジェクトの値を足せば求まりますが。
リンク先の Flashが目標だとすると、このゲーム内での Box2Dは使いどころが難しいですね。
このゲームの肝であるバランス部分を真面目に物理演算してしまうと、
調整がかなり大変になりそうな気がします。
Re:Box2dの天秤の傾き調整がうまくいかない
GetMassですね。
わかりました。試してみます。
またわからないことがあったら質問をしますので
後ほどよろしくお願いします。
わかりました。試してみます。
またわからないことがあったら質問をしますので
後ほどよろしくお願いします。
Re:Box2dの天秤の傾き調整がうまくいかない
傾きとは別の質問ですが、
左の皿に触れた、右の皿にのった触れたの判定でGetMassを利用して足そうとしているのですが、
皿に触れたときに判定をすると、皿に触れないで物の上に乗ったときに
皿に触れていないものをどうやって判定するかが
わからなくて詰まっています。
別のやり方があるのだと思うのですが、どういう風にプログラムしていいかわからないのです。
わかるかた教えてください。
左の皿に触れた、右の皿にのった触れたの判定でGetMassを利用して足そうとしているのですが、
皿に触れたときに判定をすると、皿に触れないで物の上に乗ったときに
皿に触れていないものをどうやって判定するかが
わからなくて詰まっています。
別のやり方があるのだと思うのですが、どういう風にプログラムしていいかわからないのです。
わかるかた教えてください。
Re:Box2dの天秤の傾き調整がうまくいかない
>皿に触れたときに判定をすると、皿に触れないで物の上に乗ったときに
>皿に触れていないものをどうやって判定するかがわからなくて
b2Body::GetContactList()でその b2Bodyと接触しているオブジェクトの情報が取得できますので、
皿の b2Bodyから接触しているものを辿って、さらにそのオブジェクトの接触リストを、と
全てを調べていけばなんとかなるかな、と思います。
でも、動作的に Flashと同じものを作るのであれば、そんなことしなくても
事前にそれぞれの皿にあるオブジェクトリストを作っておいて、全てのオブジェクトが
静止状態に入ってから、2つのリストをそれぞれ辿って調べればいいのでは?
>皿に触れていないものをどうやって判定するかがわからなくて
b2Body::GetContactList()でその b2Bodyと接触しているオブジェクトの情報が取得できますので、
皿の b2Bodyから接触しているものを辿って、さらにそのオブジェクトの接触リストを、と
全てを調べていけばなんとかなるかな、と思います。
でも、動作的に Flashと同じものを作るのであれば、そんなことしなくても
事前にそれぞれの皿にあるオブジェクトリストを作っておいて、全てのオブジェクトが
静止状態に入ってから、2つのリストをそれぞれ辿って調べればいいのでは?
Re:Box2dの天秤の傾き調整がうまくいかない
以前Box2Dのプログラムに関して質問したるーといいます。
ブロックをマウスを使って動かすプログラムをJustyさんに作ってもらいました。
あれから返事を出せず本当に申し訳ありません。
で、実はこのスレの質問者のみなかさんと僕は共同でプログラムを作っています。
僕もやり方が分からずに困っています。
プログラムを上げてみますので、見てやって下さい。
そして、ご指導の程お願いします。
理想として、同じ密度のブロックを両かごに入れたら、
すぐに天秤が釣り合うようなプログラムにしたいのですが、
よろしくお願いします。
ブロックをマウスを使って動かすプログラムをJustyさんに作ってもらいました。
あれから返事を出せず本当に申し訳ありません。
で、実はこのスレの質問者のみなかさんと僕は共同でプログラムを作っています。
僕もやり方が分からずに困っています。
プログラムを上げてみますので、見てやって下さい。
そして、ご指導の程お願いします。
理想として、同じ密度のブロックを両かごに入れたら、
すぐに天秤が釣り合うようなプログラムにしたいのですが、
よろしくお願いします。

Re:Box2dの天秤の傾き調整がうまくいかない
>みなかさんと僕は共同でプログラムを作っています
あー、なるほど。ということは Box2Dは 2.0xということですね。
だとすると b2Body::GetContactList関数は存在しませんね。
基本的に天秤を物理計算している環境下で、モノをバスケットに載せても、
安定するまで時間がかかるのは実際の天秤でも同じです。
それを出来るだけ早く、且つある程度自然な形で安定させるには、無理矢理ジョイントで
押さえつけていいのですが、No:52079でも書きましたが調整が大変だと思います。
代替案としてはバーを固定(他のオブジェクトの影響を受けない)にして、
それぞれのバスケットに載っている重量を求め、比較、結果をバーの角度に反映、という方法です。
バスケットにかかる重量を簡単に求める為のメソッドは Box2Dにはありません。
(勿論、ライブラリの中から手を入れれば別ですが)
なのでバスケットに触れているオブジェクトをリストアップし全ての重量を計算します。
ではどうやってバスケットに触れているものをリストアップするか、ですが少し試してみました。
バスケットの b2Bodyが持っている接触リストから辿ってみましたが、このリストは
接触している可能性があるリストっぽく、オブジェクトとオブジェクトが近距離になると
リストに追加されるようで、確実に接触しているとは言い難いものでした。
(だから メソッドが存在しなかったのでしょうか……?)
そこで b2ContactListenerから拾ってみようとしましたが、こちらはこちらで跳ね返りなどで
細かく接触したり外れたりを繰り返していて安定しないことがあるようです。
とりあえず両方を併用する形で力技でなんとかしてみましたが、こんな感じを目指している、
ということでしょうか。
ttp://karinto2.jp/uploader/download/1274110200.zip
Pass : cx2CwuH3
注) 赤は緑の2倍の重さをもっています。
どう力技なのかというと……。
b2ContactListenerに過去 15フレーム分の接触した b2Bodyのペアリストを記憶するようにする(Persist)。
b2Bodyクラスにメンバ m_contactListを返す関数 GetContactListを追加。
バスケットにかかる重量を求める時に、GetContactList()を使ってバスケットから接触している b2Bodyを洗い出し、
接触しているものが見つかったら更にその接触リストを辿り芋づる式に接触しているだろう
オブジェクトを見つける。
見つけたオブジェクトは以下の条件を満たしていたら、重量を計算する。
・ 同一フレームでまだ調べていないオブジェクトである
・ 見つけたオブジェクトが USERDATA_BOX1か USERDATA_BOX2である。
・ b2ContactListenerのペアリストと照合し過去 15フレーム以内に接触している
・ バスケットより上にある(下からバスケットに接触されると困るので)
求めた重量を加算し、双方のバスケットで比較し、その差に応じて角度に変換する。
その際急激に変化しないよう加速度をつける。
とこんな感じです。
んー、なんかしっくりこないですけど、今はこれしか思いつかないですね。
もうちょっと考えてみます。
あー、なるほど。ということは Box2Dは 2.0xということですね。
だとすると b2Body::GetContactList関数は存在しませんね。
基本的に天秤を物理計算している環境下で、モノをバスケットに載せても、
安定するまで時間がかかるのは実際の天秤でも同じです。
それを出来るだけ早く、且つある程度自然な形で安定させるには、無理矢理ジョイントで
押さえつけていいのですが、No:52079でも書きましたが調整が大変だと思います。
代替案としてはバーを固定(他のオブジェクトの影響を受けない)にして、
それぞれのバスケットに載っている重量を求め、比較、結果をバーの角度に反映、という方法です。
バスケットにかかる重量を簡単に求める為のメソッドは Box2Dにはありません。
(勿論、ライブラリの中から手を入れれば別ですが)
なのでバスケットに触れているオブジェクトをリストアップし全ての重量を計算します。
ではどうやってバスケットに触れているものをリストアップするか、ですが少し試してみました。
バスケットの b2Bodyが持っている接触リストから辿ってみましたが、このリストは
接触している可能性があるリストっぽく、オブジェクトとオブジェクトが近距離になると
リストに追加されるようで、確実に接触しているとは言い難いものでした。
(だから メソッドが存在しなかったのでしょうか……?)
そこで b2ContactListenerから拾ってみようとしましたが、こちらはこちらで跳ね返りなどで
細かく接触したり外れたりを繰り返していて安定しないことがあるようです。
とりあえず両方を併用する形で力技でなんとかしてみましたが、こんな感じを目指している、
ということでしょうか。
ttp://karinto2.jp/uploader/download/1274110200.zip
Pass : cx2CwuH3
注) 赤は緑の2倍の重さをもっています。
どう力技なのかというと……。
b2ContactListenerに過去 15フレーム分の接触した b2Bodyのペアリストを記憶するようにする(Persist)。
b2Bodyクラスにメンバ m_contactListを返す関数 GetContactListを追加。
バスケットにかかる重量を求める時に、GetContactList()を使ってバスケットから接触している b2Bodyを洗い出し、
接触しているものが見つかったら更にその接触リストを辿り芋づる式に接触しているだろう
オブジェクトを見つける。
見つけたオブジェクトは以下の条件を満たしていたら、重量を計算する。
・ 同一フレームでまだ調べていないオブジェクトである
・ 見つけたオブジェクトが USERDATA_BOX1か USERDATA_BOX2である。
・ b2ContactListenerのペアリストと照合し過去 15フレーム以内に接触している
・ バスケットより上にある(下からバスケットに接触されると困るので)
求めた重量を加算し、双方のバスケットで比較し、その差に応じて角度に変換する。
その際急激に変化しないよう加速度をつける。
とこんな感じです。
んー、なんかしっくりこないですけど、今はこれしか思いつかないですね。
もうちょっと考えてみます。
Re:Box2dの天秤の傾き調整がうまくいかない
Box2dは良く知らない(使い始めて一週間程度)のですが
物理シミュレーションなら、ばねも再現できると思います(確認は出来てません)。
ばねじゃなくても物体の変位と比例した力はかけれるはずです。
両側の天秤に見えないばねをつければ、複雑な機構を組み込まないでも
重さの違いよって角度が変わるはずです。
制止するまでの時間が長ければジョイント部分の抵抗を大きくすればなんとかなると思います。
物理シミュレーションなら、ばねも再現できると思います(確認は出来てません)。
ばねじゃなくても物体の変位と比例した力はかけれるはずです。
両側の天秤に見えないばねをつければ、複雑な機構を組み込まないでも
重さの違いよって角度が変わるはずです。
制止するまでの時間が長ければジョイント部分の抵抗を大きくすればなんとかなると思います。
Re:Box2dの天秤の傾き調整がうまくいかない
Justyさん、組木紙織さん、ご指導ありがとうございます。
Justyさんのてんびん.exeのように作ってみたいと思います。
このexeファイルすごいですね。
こんな感じで作りたかったので、
Justyさん尊敬しまくりです。
私の頭はあまり良い方ではないので、申し訳なく思いますが、
Justyさんの説明で理解できないところもありますので、
分からないことがあったら聞くと思いますので、
その時は、またよろしくお願いしますね。
Justyさんのてんびん.exeのように作ってみたいと思います。
このexeファイルすごいですね。
こんな感じで作りたかったので、
Justyさん尊敬しまくりです。
私の頭はあまり良い方ではないので、申し訳なく思いますが、
Justyさんの説明で理解できないところもありますので、
分からないことがあったら聞くと思いますので、
その時は、またよろしくお願いしますね。
Re:Box2dの天秤の傾き調整がうまくいかない
@組木紙織さん
>両側の天秤に見えないばねをつければ
この天秤の2つのバスケットが重さで上下に動くだけならバーの重さを重くするとか
仰るようにバネを入れてもいいかな、と思ったんですが。
このバスケット、遊園地のバイキングみたいな感じで結構揺れるんですよ。
2つのバスケットがばらばらに揺れると、それぞれの遠心力によってバーを引っ張る向きが
変わりなかなか静止しない、というのが今の状態です。
なので、天秤にバネを入れてもちょっと厳しいかな、と判断したわけです。
ただ、バスケットの揺れができるだけ早く収束するようにさせた上でなら
効果はありそうな気がしてきました。
@みなかさん&るーさん
いくつか補足をしておきます。
一応 15フレームとって多少オブジェクトがバスケット等から離れても載っていることに
していますが、これでもダメなときはだめなようです(画面上は離れているようには見えないのに)。
必須ではないにしても、一度載ったオブジェクトはバスケット周辺から見た目で判るほど(1,2pixel以上)
離れたときのみ載っていない判定をした方がいいかもしれません。
>バスケットにかかる重量を簡単に求める為のメソッドは Box2Dにはありません。
と書きましたが、すみません、近いのがありました。
b2ContactListenerクラスの Resultメソッドに最終的に接触している Shapeの情報と
位置・力の方向と強さが来ています。
上に載ったオブジェクトの分も加味して計算してくれているようです。
これを上手く使ってバスケットとボックスの接触だけ拾い出せば、
接触リストを辿らなくても済むかもしれません。
>両側の天秤に見えないばねをつければ
この天秤の2つのバスケットが重さで上下に動くだけならバーの重さを重くするとか
仰るようにバネを入れてもいいかな、と思ったんですが。
このバスケット、遊園地のバイキングみたいな感じで結構揺れるんですよ。
2つのバスケットがばらばらに揺れると、それぞれの遠心力によってバーを引っ張る向きが
変わりなかなか静止しない、というのが今の状態です。
なので、天秤にバネを入れてもちょっと厳しいかな、と判断したわけです。
ただ、バスケットの揺れができるだけ早く収束するようにさせた上でなら
効果はありそうな気がしてきました。
@みなかさん&るーさん
いくつか補足をしておきます。
一応 15フレームとって多少オブジェクトがバスケット等から離れても載っていることに
していますが、これでもダメなときはだめなようです(画面上は離れているようには見えないのに)。
必須ではないにしても、一度載ったオブジェクトはバスケット周辺から見た目で判るほど(1,2pixel以上)
離れたときのみ載っていない判定をした方がいいかもしれません。
>バスケットにかかる重量を簡単に求める為のメソッドは Box2Dにはありません。
と書きましたが、すみません、近いのがありました。
b2ContactListenerクラスの Resultメソッドに最終的に接触している Shapeの情報と
位置・力の方向と強さが来ています。
上に載ったオブジェクトの分も加味して計算してくれているようです。
これを上手く使ってバスケットとボックスの接触だけ拾い出せば、
接触リストを辿らなくても済むかもしれません。
Re:Box2dの天秤の傾き調整がうまくいかない
色々試行錯誤しているのですが、
main.cppに
// 接触のリストに対する処理
for( b2ContactResultList::const_iterator it=ContactList.begin(), endit=ContactList.end(); it!=endit; ++it )
{
// この中で接触リストに対する処理を行う
//const b2ContactResult &contactResult = *it;:
}
とありますが、この中にGetMass()を使ってバスケットの重量、ブロックの重量を求め、
その重量を使ってバスケットの総重量を求めるような計算をしていけばいいのでしょうか?
火曜にJustyさんが答えて下さったレスに、
>>バスケットにかかる重量を求める時に、GetContactList()を使ってバスケットから接触している b2Bodyを洗い出し、
>>接触しているものが見つかったら更にその接触リストを辿り芋づる式に接触しているだろう
オブジェクトを見つける。
とあるんですけど、ここの部分をどうプログラミングしていけばいいのか分からないです。
2人ともかなり疲弊しており、頭がついていかない状態ですw
馬鹿共ですいませんが、以上のことについて詳しく教えて頂きたいです。
main.cppに
// 接触のリストに対する処理
for( b2ContactResultList::const_iterator it=ContactList.begin(), endit=ContactList.end(); it!=endit; ++it )
{
// この中で接触リストに対する処理を行う
//const b2ContactResult &contactResult = *it;:
}
とありますが、この中にGetMass()を使ってバスケットの重量、ブロックの重量を求め、
その重量を使ってバスケットの総重量を求めるような計算をしていけばいいのでしょうか?
火曜にJustyさんが答えて下さったレスに、
>>バスケットにかかる重量を求める時に、GetContactList()を使ってバスケットから接触している b2Bodyを洗い出し、
>>接触しているものが見つかったら更にその接触リストを辿り芋づる式に接触しているだろう
オブジェクトを見つける。
とあるんですけど、ここの部分をどうプログラミングしていけばいいのか分からないです。
2人ともかなり疲弊しており、頭がついていかない状態ですw
馬鹿共ですいませんが、以上のことについて詳しく教えて頂きたいです。
Re:Box2dの天秤の傾き調整がうまくいかない
どうしても解決できなければ、ソースを出してもいいですが、もう少し頑張って見ましょうか。
>その重量を使ってバスケットの総重量を求めるような計算をしていけばいいのでしょうか?
そこは全く使っていないです。
私が書いたコードでは事前に b2ContactListener::Persistの中で、どの b2Bodyと b2Bodyが接触しているのかを
全てリストアップしました(これをペアリストとします)。
これは Persistメソッドの引数から接触しているオブジェクトそれぞれの b2Shapeを取得し、
そこから b2Shape::GetBody()を呼べば b2Bodyが手に入ります。
この2つの b2Bodyをペアにしてリストに保存するわけです。
これを 15~30フレーム分保存しますのでリストは配列など複数用意して、毎フレーム別のリストに
格納します。
尚、後から検索するので各リストの中で重複するペアは入れる前に弾いておいた方がいいですね。
でペアリストが完成したら(b2Word::Stepが終ったら)重量を計算するときに、
・ std::vector<const b2Body*>のチェック済みリストを用意しておく。
・ バスケットの b2Body::GetContactList()の b2ContactEdge型のリストを辿ってバスケットに
接触している可能性があるボックスの b2Bodyを取り出す(b2ContactEdge::otherメンバ)。
(GetContactListメソッドは 2.0xにはないので、ヘッダを書き換えて作って下さい)
・ 取り出した b2Bodyが以下の条件を全て満たしているか
USERDATA_BOX1や USERDATA_BOX2である
ペアリストを調べて過去Xフレーム以内にバスケットの b2Bodyと接触している・いたかどうか
位置がバスケットよりも上にある
チェック済みリストに入っていない
・ 条件を全て満たしていたら、チェック済みリストに b2Bodyを追加し、重量を加算する
・ 続けて、その b2Bodyと接触している別の b2Bodyを b2Body::GetContactList()から洗い出し
同様に調べる。
>ここの部分をどうプログラミングしていけばいいのか分からないです
構造的には接触していた b2Bodyに接触していた別の b2Bodyを見つけ、それに接触していた
b2Bodyに接触していた……と次から次へと全ての連なりを全て調べますのでここは再帰構造となります。
イメージ的にはこんな感じです。
[color=#d0d0ff" face="monospace]
float GetTotalMassContactedBox(const b2Body *body, const b2Vec2 &basePos, std::vector<const b2Body*> &checkedList)
{
float totalMass = 0;
for (const b2ContactEdge *ce = body->GetContactList(); ce; ce = ce->next)
{
b2Body *ceOtherBody = ce->other;
...
条件に合った ceOtherBody(b2Body)を見つけたら、totalMassに加算し、
ceOtherBodyを第一引数にして GetTotalMassContactedBox()を呼び出し、totalMassに加算する
}
return totalMass;
}
float GetMassOnBasket(const b2Body *body)
{
const b2ContactEdge *contactList = body->GetContactList();
if(!contactList) return 0;
std::vector<const b2Body*> checkedList;
return GetTotalMassContactedBox(body, body->GetPosition()+b2Vec2(0, 15), checkedList);
}
[/color]
>その重量を使ってバスケットの総重量を求めるような計算をしていけばいいのでしょうか?
そこは全く使っていないです。
私が書いたコードでは事前に b2ContactListener::Persistの中で、どの b2Bodyと b2Bodyが接触しているのかを
全てリストアップしました(これをペアリストとします)。
これは Persistメソッドの引数から接触しているオブジェクトそれぞれの b2Shapeを取得し、
そこから b2Shape::GetBody()を呼べば b2Bodyが手に入ります。
この2つの b2Bodyをペアにしてリストに保存するわけです。
これを 15~30フレーム分保存しますのでリストは配列など複数用意して、毎フレーム別のリストに
格納します。
尚、後から検索するので各リストの中で重複するペアは入れる前に弾いておいた方がいいですね。
でペアリストが完成したら(b2Word::Stepが終ったら)重量を計算するときに、
・ std::vector<const b2Body*>のチェック済みリストを用意しておく。
・ バスケットの b2Body::GetContactList()の b2ContactEdge型のリストを辿ってバスケットに
接触している可能性があるボックスの b2Bodyを取り出す(b2ContactEdge::otherメンバ)。
(GetContactListメソッドは 2.0xにはないので、ヘッダを書き換えて作って下さい)
・ 取り出した b2Bodyが以下の条件を全て満たしているか
USERDATA_BOX1や USERDATA_BOX2である
ペアリストを調べて過去Xフレーム以内にバスケットの b2Bodyと接触している・いたかどうか
位置がバスケットよりも上にある
チェック済みリストに入っていない
・ 条件を全て満たしていたら、チェック済みリストに b2Bodyを追加し、重量を加算する
・ 続けて、その b2Bodyと接触している別の b2Bodyを b2Body::GetContactList()から洗い出し
同様に調べる。
>ここの部分をどうプログラミングしていけばいいのか分からないです
構造的には接触していた b2Bodyに接触していた別の b2Bodyを見つけ、それに接触していた
b2Bodyに接触していた……と次から次へと全ての連なりを全て調べますのでここは再帰構造となります。
イメージ的にはこんな感じです。
[color=#d0d0ff" face="monospace]
float GetTotalMassContactedBox(const b2Body *body, const b2Vec2 &basePos, std::vector<const b2Body*> &checkedList)
{
float totalMass = 0;
for (const b2ContactEdge *ce = body->GetContactList(); ce; ce = ce->next)
{
b2Body *ceOtherBody = ce->other;
...
条件に合った ceOtherBody(b2Body)を見つけたら、totalMassに加算し、
ceOtherBodyを第一引数にして GetTotalMassContactedBox()を呼び出し、totalMassに加算する
}
return totalMass;
}
float GetMassOnBasket(const b2Body *body)
{
const b2ContactEdge *contactList = body->GetContactList();
if(!contactList) return 0;
std::vector<const b2Body*> checkedList;
return GetTotalMassContactedBox(body, body->GetPosition()+b2Vec2(0, 15), checkedList);
}
[/color]

Re:Box2dの天秤の傾き調整がうまくいかない
>イメージ的にはこんな感じです。
プログラムを記述していただいたのにまったくもって申し訳ないのですが、
どこに記述していこうか迷ったり、
void Persist(const b2ContactPoint* point)
の場所や
for(b2ContactResultList::const_iterator it=ContactList.begin(), endit=ContactList.end(); it!=endit; ++it)
の場所に記述してもローカル関数の定義がただしくないとか
識別子がないなどのエラーが出ます。
>私が書いたコードでは事前に b2ContactListener::Persistの中で
>どの b2Bodyと b2Bodyが接触しているのか
この場所でいざやろうとしてもどう記述していけば良いのか、
わからなくるー共々わからず切羽詰まっております。
No:52261の
>バーを固定(他のオブジェクトの影響を受けない)
これは
b->SetMassFromShapes(); // 形状から当たり判定情報の作成
を消してみたのですがこれであっているのでしょうか?
Justyさん頼りでやっていって記述してもらったものを書いて、
進めている向上心があるのかないのかわからない馬鹿な奴等ですが、
申し訳ないのです。
今週中には仕上げたいので、
また救い手差し伸べてくれないでしょうか。
お願いします。
プログラムを記述していただいたのにまったくもって申し訳ないのですが、
どこに記述していこうか迷ったり、
void Persist(const b2ContactPoint* point)
の場所や
for(b2ContactResultList::const_iterator it=ContactList.begin(), endit=ContactList.end(); it!=endit; ++it)
の場所に記述してもローカル関数の定義がただしくないとか
識別子がないなどのエラーが出ます。
>私が書いたコードでは事前に b2ContactListener::Persistの中で
>どの b2Bodyと b2Bodyが接触しているのか
この場所でいざやろうとしてもどう記述していけば良いのか、
わからなくるー共々わからず切羽詰まっております。
No:52261の
>バーを固定(他のオブジェクトの影響を受けない)
これは
b->SetMassFromShapes(); // 形状から当たり判定情報の作成
を消してみたのですがこれであっているのでしょうか?
Justyさん頼りでやっていって記述してもらったものを書いて、
進めている向上心があるのかないのかわからない馬鹿な奴等ですが、
申し訳ないのです。
今週中には仕上げたいので、
また救い手差し伸べてくれないでしょうか。
お願いします。
Re:Box2dの天秤の傾き調整がうまくいかない
>識別子がないなどのエラーが出ます
根本的におかしな状態になっていますね。
関数の中に関数を記述することは出来ませんよ。普通の関数として、適当なところに書いてください。
プログラムの流れをまとめましょうか。大きなところで書くと
1) マウスによる移動
2) b2World::Step実行 → MyContactListener::Presents(Result?)での接触情報収集
3) 接触情報を元にした重量計算 → バランス決定
4) 表示
となります。
前に「イメージ」と書いたコード GetMassOnBasket関数は指定した b2Bodyに連なるオブジェクトの
重量の合計を求めるものなので、3)に相当します。
従って、b2World::Step内で実行される Persistの中で処理するものではなく、b2World::Stepの後で実行するものです。
又、「そこは全く使っていないです」と書いたとおり、for(b2ContactResultList……も使って居ません。
単純に2つの重量を求めて比較する為の(例えば UpdateBarBalanceという名前の)関数を1つ用意して、
その中で LeftBasketと RightBasketの重量を GetMassOnBasket()でそれぞれ調べて比較し、
バランス(角度)を調整しています。
この UpdateBarBalance関数を b2World::Step()の後で呼んで、その後結果に基づいて Barの姿勢を設定・表示をしています。
>この場所でいざやろうとしてもどう記述していけば良いのか
具体的にどこで詰まっていますか?
No:52410で結構具体的に書いているのですが……。
Persistの引数 pointは接触情報 そのものなので
[color=#d0d0ff" face="monospace]
point->shape1->GetBody();
point->shape2->GetBody();
[/color]
で接触している2つの b2Bodyが手に入ります。
この2つの b2Bodyをペアにしてリストに保存しています。
参考までにこのペアリストを保存しているMyContactListenerメンバ変数の型はこんな感じです。
[color=#d0d0ff" face="monospace]
typedef std::tr1::tuple<const b2Body *, const b2Body *> b2BodyPair; // ペア情報
typedef std::vector<b2BodyPair> b2BodyPairList; // ペアリスト
static const int MaxFramePairBodyList = 30; // 30フレーム分記憶
b2BodyPairList m_PairBodyList[MaxFramePairBodyList]; // ペアリスト 30フレーム分
[/color]
※ std::tr1::tupleが使えなければ std::pairでも代用できるはずです。
で、このペアリストを先の重量比較関数である UpdateBarBalanceの中で辿り、バスケットがもっている
接触しているかもしれないリストと照合して、本当に接触しているかどうかをペアリストを使って
確認しています。
あぁ、一応 b2World::Step直前で、最も古いフレームのペアリストはクリアしておく必要があります。
そうしないといつまでも残ってしまいますので。
実際のところ、UpdateBarBalanceの中で本当に接触しているかどうかさえ確認できればいいので
このケースでは ContactListを使わずに独自のペアリストを構築しましたが、ContactListを使っても
接触している b2Body2つを持っているので確認はできるはずです。
>バーを固定
>を消してみたのですがこれであっているのでしょうか
一応それでもいいとは思います。b2PolygonDef::densityを 0にしても同様になるはずです。
根本的におかしな状態になっていますね。
関数の中に関数を記述することは出来ませんよ。普通の関数として、適当なところに書いてください。
プログラムの流れをまとめましょうか。大きなところで書くと
1) マウスによる移動
2) b2World::Step実行 → MyContactListener::Presents(Result?)での接触情報収集
3) 接触情報を元にした重量計算 → バランス決定
4) 表示
となります。
前に「イメージ」と書いたコード GetMassOnBasket関数は指定した b2Bodyに連なるオブジェクトの
重量の合計を求めるものなので、3)に相当します。
従って、b2World::Step内で実行される Persistの中で処理するものではなく、b2World::Stepの後で実行するものです。
又、「そこは全く使っていないです」と書いたとおり、for(b2ContactResultList……も使って居ません。
単純に2つの重量を求めて比較する為の(例えば UpdateBarBalanceという名前の)関数を1つ用意して、
その中で LeftBasketと RightBasketの重量を GetMassOnBasket()でそれぞれ調べて比較し、
バランス(角度)を調整しています。
この UpdateBarBalance関数を b2World::Step()の後で呼んで、その後結果に基づいて Barの姿勢を設定・表示をしています。
>この場所でいざやろうとしてもどう記述していけば良いのか
具体的にどこで詰まっていますか?
No:52410で結構具体的に書いているのですが……。
Persistの引数 pointは接触情報 そのものなので
[color=#d0d0ff" face="monospace]
point->shape1->GetBody();
point->shape2->GetBody();
[/color]
で接触している2つの b2Bodyが手に入ります。
この2つの b2Bodyをペアにしてリストに保存しています。
参考までにこのペアリストを保存しているMyContactListenerメンバ変数の型はこんな感じです。
[color=#d0d0ff" face="monospace]
typedef std::tr1::tuple<const b2Body *, const b2Body *> b2BodyPair; // ペア情報
typedef std::vector<b2BodyPair> b2BodyPairList; // ペアリスト
static const int MaxFramePairBodyList = 30; // 30フレーム分記憶
b2BodyPairList m_PairBodyList[MaxFramePairBodyList]; // ペアリスト 30フレーム分
[/color]
※ std::tr1::tupleが使えなければ std::pairでも代用できるはずです。
で、このペアリストを先の重量比較関数である UpdateBarBalanceの中で辿り、バスケットがもっている
接触しているかもしれないリストと照合して、本当に接触しているかどうかをペアリストを使って
確認しています。
あぁ、一応 b2World::Step直前で、最も古いフレームのペアリストはクリアしておく必要があります。
そうしないといつまでも残ってしまいますので。
実際のところ、UpdateBarBalanceの中で本当に接触しているかどうかさえ確認できればいいので
このケースでは ContactListを使わずに独自のペアリストを構築しましたが、ContactListを使っても
接触している b2Body2つを持っているので確認はできるはずです。
>バーを固定
>を消してみたのですがこれであっているのでしょうか
一応それでもいいとは思います。b2PolygonDef::densityを 0にしても同様になるはずです。
Re:Box2dの天秤の傾き調整がうまくいかない
>具体的にどこで詰まっていますか?
b2ContactListener::Persistがなかったので、
たぶんvoid Persist(const b2ContactPoint* point)の中に記述するのかなと思い
b2Shape::GetBody()を呼び出したのは良いのですが、
( 'b2Shape::GetBody' : 静的でないメンバ関数の呼び出しが正しくありません)
と出てきました。これって記述場所があってないのでしょうか?
それとも根本的にどこかに何か宣言などしなければいけないのでしょうか?
>typedef std::tr1::tuple<const b2Body *, const b2Body *> b2BodyPair; //ペア情報
>typedef std::vector<b2BodyPair> b2BodyPairList;//ペアリスト
>static const int MaxFramePairBodyList = 30; //30フレーム分記憶
>b2BodyPairList m_PairBodyList[MaxFramePairBodyList]; //ペアリスト 30フレーム分
はMyContactListener.cppに記述すればあっているのでしょうか?
すみませんがそこらへんを詳しく書いていただくと助かります。
今さらなのですがNo:52261で言っていたGetContactListの追加なのですが
b2ContactEdge* GetContactList();
inline b2ContactEdge* b2Body::GetContactList()
{
return m_contactList;
}
とBox2D\Source\Dynamics\\b2Body.hに追加したのですがあっているのか自信がありません。
これで良いのでしょうか?
>普通の関数として、適当なところに書いてください。
記述してみましたが、
'b2Body::GetContactList' : 'const b2Body' から 'b2Body &' へ 'this' ポインタを変換できません。
が2つ出ました。
これはまだ値を入れてないからでしょうか?
馬鹿でめちゃくちゃ質問してすみません。
またご助言をお願いします。
b2ContactListener::Persistがなかったので、
たぶんvoid Persist(const b2ContactPoint* point)の中に記述するのかなと思い
b2Shape::GetBody()を呼び出したのは良いのですが、
( 'b2Shape::GetBody' : 静的でないメンバ関数の呼び出しが正しくありません)
と出てきました。これって記述場所があってないのでしょうか?
それとも根本的にどこかに何か宣言などしなければいけないのでしょうか?
>typedef std::tr1::tuple<const b2Body *, const b2Body *> b2BodyPair; //ペア情報
>typedef std::vector<b2BodyPair> b2BodyPairList;//ペアリスト
>static const int MaxFramePairBodyList = 30; //30フレーム分記憶
>b2BodyPairList m_PairBodyList[MaxFramePairBodyList]; //ペアリスト 30フレーム分
はMyContactListener.cppに記述すればあっているのでしょうか?
すみませんがそこらへんを詳しく書いていただくと助かります。
今さらなのですがNo:52261で言っていたGetContactListの追加なのですが
b2ContactEdge* GetContactList();
inline b2ContactEdge* b2Body::GetContactList()
{
return m_contactList;
}
とBox2D\Source\Dynamics\\b2Body.hに追加したのですがあっているのか自信がありません。
これで良いのでしょうか?
>普通の関数として、適当なところに書いてください。
記述してみましたが、
'b2Body::GetContactList' : 'const b2Body' から 'b2Body &' へ 'this' ポインタを変換できません。
が2つ出ました。
これはまだ値を入れてないからでしょうか?
馬鹿でめちゃくちゃ質問してすみません。
またご助言をお願いします。
Re:Box2dの天秤の傾き調整がうまくいかない
>これって記述場所があってないのでしょうか?
いや、それ静的メンバじゃないですよ。インスタンスから呼び出す関数です。
あんまり C++に明るくない、といった感じでしょうか。
というか、No:52715で Persistの引数 pointを使って point->shape1->GetBody(); と書いてますよね?
>Box2D\Source\Dynamics\\b2Body.hに追加したのですがあっているのか自信がありません。
>これで良いのでしょうか?
クラスの publicメンバになっていれば問題ありません。
>'b2Body::GetContactList' : 'const b2Body' から 'b2Body &' へ 'this' ポインタを変換できません。
>が2つ出ました。
>これはまだ値を入れてないからでしょうか?
その記述はイメージと書いた通り、実情に合わせて適当に修正が必要だと思うんですが。
うちの b2Body::GetContactListは
[color=#d0d0ff" face="monospace]
const b2ContactEdge* GetContactList() const;
[/color]
としています。
これに合わせてみてください。
とりえあず、こちらにソースを貼っておきます。VS2008Sp1で動きます。
いや、それ静的メンバじゃないですよ。インスタンスから呼び出す関数です。
あんまり C++に明るくない、といった感じでしょうか。
というか、No:52715で Persistの引数 pointを使って point->shape1->GetBody(); と書いてますよね?
>Box2D\Source\Dynamics\\b2Body.hに追加したのですがあっているのか自信がありません。
>これで良いのでしょうか?
クラスの publicメンバになっていれば問題ありません。
>'b2Body::GetContactList' : 'const b2Body' から 'b2Body &' へ 'this' ポインタを変換できません。
>が2つ出ました。
>これはまだ値を入れてないからでしょうか?
その記述はイメージと書いた通り、実情に合わせて適当に修正が必要だと思うんですが。
うちの b2Body::GetContactListは
[color=#d0d0ff" face="monospace]
const b2ContactEdge* GetContactList() const;
[/color]
としています。
これに合わせてみてください。
とりえあず、こちらにソースを貼っておきます。VS2008Sp1で動きます。
Re:Box2dの天秤の傾き調整がうまくいかない
>ソースを貼っておきます
ありがとうございます。感謝です。
>VS2008Sp1
とはVS2008のバージョンアップされたものなのでしょうか?
だとすると自分は持っていないので動かせません。
ためしに
VS2005でやってみましたが
include ファイルを開けません。'tuple': No such file or directory
となり
VS2008でやってみると
include ファイルを開けません。'Box2D.h': No such file or directory
になりました。
何か対策はないのでしょうか?
よろしくお願いします。
ありがとうございます。感謝です。
>VS2008Sp1
とはVS2008のバージョンアップされたものなのでしょうか?
だとすると自分は持っていないので動かせません。
ためしに
VS2005でやってみましたが
include ファイルを開けません。'tuple': No such file or directory
となり
VS2008でやってみると
include ファイルを開けません。'Box2D.h': No such file or directory
になりました。
何か対策はないのでしょうか?
よろしくお願いします。
Re:Box2dの天秤の傾き調整がうまくいかない
>VS2008のバージョンアップされたものなのでしょうか?
バフフィックス + αされたものです。
2008無印を使っているならアップデートしておいた方がいいですね。
>include ファイルを開けません。'tuple': No such file or directory
調べればわかると思いますが、2つしか要素はないので std::tr1::tupleは std::pairで代用できるかと。
それに合わせて、std::tr1::make_tupleを std::make_pairにする等、適宜修正してください。
>include ファイルを開けません。'Box2D.h': No such file or directory
そのあたりは環境に合わせて適宜修正してください。
こちらではわかりません。
というか No:52235で、るーさんが貼ったソースでは普通にインクルードしているようですが。
同じ設定すれば問題ないのでは?
バフフィックス + αされたものです。
2008無印を使っているならアップデートしておいた方がいいですね。
>include ファイルを開けません。'tuple': No such file or directory
調べればわかると思いますが、2つしか要素はないので std::tr1::tupleは std::pairで代用できるかと。
それに合わせて、std::tr1::make_tupleを std::make_pairにする等、適宜修正してください。
>include ファイルを開けません。'Box2D.h': No such file or directory
そのあたりは環境に合わせて適宜修正してください。
こちらではわかりません。
というか No:52235で、るーさんが貼ったソースでは普通にインクルードしているようですが。
同じ設定すれば問題ないのでは?
Re:Box2dの天秤の傾き調整がうまくいかない
>2008無印を使っているならアップデートしておいた方がいいですね。
すみません。
学校からVS2008をもらってあまりいじりたくないのでアップデートはしたくありません。
威圧してくる先生がたまにいるので。
でもソースありがとうございます。
そのうちVS2008のバックアップが取れたらアップデートしてみます。
天秤の傾き調整なのですが
るーさんが天秤ゲームができないので
全く違うものに代案してきたので
この質問は一時的に解決扱いさせてもらいます。
ご協力していただいた皆様方に感謝です。
個人的には、作ったのにもったいないと感じるので
その時にまた質問を再開させていただきます。
その時はまたよろしくお願いします。
すみません。
学校からVS2008をもらってあまりいじりたくないのでアップデートはしたくありません。
威圧してくる先生がたまにいるので。
でもソースありがとうございます。
そのうちVS2008のバックアップが取れたらアップデートしてみます。
天秤の傾き調整なのですが
るーさんが天秤ゲームができないので
全く違うものに代案してきたので
この質問は一時的に解決扱いさせてもらいます。
ご協力していただいた皆様方に感謝です。
個人的には、作ったのにもったいないと感じるので
その時にまた質問を再開させていただきます。
その時はまたよろしくお願いします。