Box2Dを導入してプログラミングしているのですが、
マウスカーソルの座標を取得して、画面に出してあるボックスをマウス座標に合わせ、
マウスを動かせば、そのボックスがついてくるようにしたいのです。
用は↓の方のような処理を施したいのです(ただしこれはフラッシュのプログラミング)。
ttp://arthur87.sakura.ne.jp/item/16/catid/6
そうするために、Box2Dのマウスジョイントというのものがあるので、
それを利用して作ってみることにしました。
しかし、マウスジョイントに関して色々調べていたんですが、
Box2Dに関するサイトのほとんどがフラッシュに関するプログラミングで、
C言語に対応したサイトが見つかりません。
もし、皆様方の中でBox2Dに詳しい方がいらっしゃいましたら教えて頂けませんでしょうか。
Box2Dのマウスジョイントについて
Re:Box2Dのマウスジョイントについて
Box2Dはちょっと前に インターフェースの修正があったので今でも通用するかどうかわかりませんが、
マウスが押されたら
1) b2MouseJointDefに必要な情報を設定する
メンバ body1 / body2 (b2World::GetGroundBodyと引っ張りたいオブジェクト)
targetマウスの位置
maxForce 質量
2) b2World::CreateJointを呼んで b2MouseJointオブジェクトを生成する
ドラッグ中は
3) マウスの位置を b2MouseJoint::SetTarget()で(毎フレーム)設定する
マウスが離されたら
4) マウスの位置を b2World::DestroyJoint()でb2MouseJointオブジェクトを破棄する
これでいけると思います。
あと、b2DestructionListenerを継承したクラスで SayGoodbye(b2Joint*)を実装して
b2MouseJointオブジェクトが来ていたときの処理を入れておく必要があります。
このあたりはライブラリのサンプル Examples\TestBed\Framework\Test.cppにありますので、
見てみて下さい。
マウスが押されたら
1) b2MouseJointDefに必要な情報を設定する
メンバ body1 / body2 (b2World::GetGroundBodyと引っ張りたいオブジェクト)
targetマウスの位置
maxForce 質量
2) b2World::CreateJointを呼んで b2MouseJointオブジェクトを生成する
ドラッグ中は
3) マウスの位置を b2MouseJoint::SetTarget()で(毎フレーム)設定する
マウスが離されたら
4) マウスの位置を b2World::DestroyJoint()でb2MouseJointオブジェクトを破棄する
これでいけると思います。
あと、b2DestructionListenerを継承したクラスで SayGoodbye(b2Joint*)を実装して
b2MouseJointオブジェクトが来ていたときの処理を入れておく必要があります。
このあたりはライブラリのサンプル Examples\TestBed\Framework\Test.cppにありますので、
見てみて下さい。
Re:Box2Dのマウスジョイントについて
>Justyさん
返信ありがとうございます。
アドバイス通りやってみます。
が、必ずつまずくと思うので、
また質問すると思います(笑)
そのときはまたアドバイスして下さると嬉しいです。
返信ありがとうございます。
アドバイス通りやってみます。
が、必ずつまずくと思うので、
また質問すると思います(笑)
そのときはまたアドバイスして下さると嬉しいです。
Re:Box2Dのマウスジョイントについて
昨日質問したるーです。
返信を参考にして悪戦苦闘しながら打っていたらこんな感じになりました。
エラーはないもののうまく動作せず、脱力しています(笑)。
>あと、b2DestructionListenerを継承したクラスで SayGoodbye(b2Joint*)を実装して
>b2MouseJointオブジェクトが来ていたときの処理を入れておく必要があります。
>このあたりはライブラリのサンプル Examples\TestBed\Framework\Test.cppにありますので、
>見てみて下さい。
単純にプログラミングがミスってるのと、
Justyさんの返信に書いてあった上記のことができていない(というか書いていない)ので、
どういう風にしたらいいか指摘のほどをお願いします。
というか「ライブラリのサンプル Examples\TestBed\Framework\Test.cpp」というのは、
どこのことを仰ったのでしょう。
ちなみに↓のプログラミングはヘッダに書いたもので、それをメインで読みこんでいます。
また、全部書くと長くなるので必要個所だけ抜粋しています。
b2World *world; // 世界
b2Body* ground; // 地面
b2Body* Squear; // ボックス
b2MouseJoint * Joint6; // ジョイント
b2Body* CreateSquear( int x, int y );
b2MouseJoint * CreateDistanceJoint6( b2Body* body1, b2Body* body2, float length );
// 物理世界の初期化
void InitWorld()
{
//////////////////////////////////////////////////////////////////////////////////////////
//
// 仮想の物理世界の作成 ここは最初の境界の設定以外はほぼこのまま
//
// 物理世界の境界を設定、想定よりも大きめに
b2AABB worldAABB;
worldAABB.lowerBound.Set( -1000.0f, -1000.0f );
worldAABB.upperBound.Set( 7400.0f, 5800.0f );
// 重力設定用変数
b2Vec2 gravity( 0.0f, -50.0f );
// 物理計算を行うかどうかのフラグ
bool doSleep = false;
// 物理世界の作成
world = new b2World( worldAABB, gravity, doSleep );
world->SetContactListener( &myContactListener );
//////////////////////////////////////////////////////////////////////////////////////////
//
// 地面の作成 地面は動かない静的オブジェクト
// 地面の位置セット
b2BodyDef groundBodyDef;
groundBodyDef.position.Set( 320.0f, 10.0f );
groundBodyDef.userData = ( void* )USERDATA_GROUND; // ユーザ定義データ 地面 をセット
// 位置情報から地面オブジェクトの作成
ground = world->CreateBody( &groundBodyDef );
// 地面がもつ形状の設定 中心を基準に設定される
b2PolygonDef groundShapeDef;
groundShapeDef.SetAsBox( 500.0f, 10.0f ); // 横100*2 縦 10*2 の大きさ
ground->CreateShape( &groundShapeDef ); // 形状作成
// 地面に置いてあるボックス
Squear = CreateSquear( 100, 50 );
// ジョイントの作成 アンカーポイントを変更する
Joint6 = CreateDistanceJoint6( world->GetGroundBody(), Squear, 100 );
}
// マウス座標とのジョイント処理
b2MouseJoint * CreateDistanceJoint6( b2Body* body1, b2Body* body2, float length )
{
b2MouseJointDef mouse;
mouse.body1 = body1;
mouse.body2 = body2;
mouse.target = body2->GetWorldCenter();
mouse.maxForce = 25.0f;
mouse.timeStep = 1.0f / 60.f;
return ( b2MouseJoint* )world->CreateJoint( &mouse ); // ジョイント作成
}
// ボックス作成
b2Body* CreateSquear( int x, int y )
{
// 作業用変数
b2BodyDef bodyDef; // ボディ定義情報
b2PolygonDef shapeDef; // 形状定義情報
b2Body *b; // ボディ 形状追加するために使うだけなので、ここで定義
// ボックスの位置セット
bodyDef.position.Set( x, y ); // 座標セット
bodyDef.linearDamping = 0.0f; // ボディ単体の移動量減衰効果
bodyDef.angularDamping = 0.0f; // ボディ単体の角速度減衰効果
bodyDef.userData = ( void* )USERDATA_SQUEAR; // ユーザ定義データ BOX をセット
// 位置情報からボックスオブジェクトの作成
b = world->CreateBody( &bodyDef );
// ボックスがもつ形状の設定 中心を基準に設定される
shapeDef.SetAsBox( 30.0f, 30.0f ); // 横30*2 縦30*2 の大きさ
shapeDef.density = 1.0f; // 密度
shapeDef.friction = 0.1f; // 摩擦
shapeDef.restitution = 0.0f; // 弾性
b->CreateShape( &shapeDef); // 形状作成
b->SetMassFromShapes(); // 形状から当たり判定情報の作成
return b; // 今回作成したボディのポインタを返す
}
返信を参考にして悪戦苦闘しながら打っていたらこんな感じになりました。
エラーはないもののうまく動作せず、脱力しています(笑)。
>あと、b2DestructionListenerを継承したクラスで SayGoodbye(b2Joint*)を実装して
>b2MouseJointオブジェクトが来ていたときの処理を入れておく必要があります。
>このあたりはライブラリのサンプル Examples\TestBed\Framework\Test.cppにありますので、
>見てみて下さい。
単純にプログラミングがミスってるのと、
Justyさんの返信に書いてあった上記のことができていない(というか書いていない)ので、
どういう風にしたらいいか指摘のほどをお願いします。
というか「ライブラリのサンプル Examples\TestBed\Framework\Test.cpp」というのは、
どこのことを仰ったのでしょう。
ちなみに↓のプログラミングはヘッダに書いたもので、それをメインで読みこんでいます。
また、全部書くと長くなるので必要個所だけ抜粋しています。
b2World *world; // 世界
b2Body* ground; // 地面
b2Body* Squear; // ボックス
b2MouseJoint * Joint6; // ジョイント
b2Body* CreateSquear( int x, int y );
b2MouseJoint * CreateDistanceJoint6( b2Body* body1, b2Body* body2, float length );
// 物理世界の初期化
void InitWorld()
{
//////////////////////////////////////////////////////////////////////////////////////////
//
// 仮想の物理世界の作成 ここは最初の境界の設定以外はほぼこのまま
//
// 物理世界の境界を設定、想定よりも大きめに
b2AABB worldAABB;
worldAABB.lowerBound.Set( -1000.0f, -1000.0f );
worldAABB.upperBound.Set( 7400.0f, 5800.0f );
// 重力設定用変数
b2Vec2 gravity( 0.0f, -50.0f );
// 物理計算を行うかどうかのフラグ
bool doSleep = false;
// 物理世界の作成
world = new b2World( worldAABB, gravity, doSleep );
world->SetContactListener( &myContactListener );
//////////////////////////////////////////////////////////////////////////////////////////
//
// 地面の作成 地面は動かない静的オブジェクト
// 地面の位置セット
b2BodyDef groundBodyDef;
groundBodyDef.position.Set( 320.0f, 10.0f );
groundBodyDef.userData = ( void* )USERDATA_GROUND; // ユーザ定義データ 地面 をセット
// 位置情報から地面オブジェクトの作成
ground = world->CreateBody( &groundBodyDef );
// 地面がもつ形状の設定 中心を基準に設定される
b2PolygonDef groundShapeDef;
groundShapeDef.SetAsBox( 500.0f, 10.0f ); // 横100*2 縦 10*2 の大きさ
ground->CreateShape( &groundShapeDef ); // 形状作成
// 地面に置いてあるボックス
Squear = CreateSquear( 100, 50 );
// ジョイントの作成 アンカーポイントを変更する
Joint6 = CreateDistanceJoint6( world->GetGroundBody(), Squear, 100 );
}
// マウス座標とのジョイント処理
b2MouseJoint * CreateDistanceJoint6( b2Body* body1, b2Body* body2, float length )
{
b2MouseJointDef mouse;
mouse.body1 = body1;
mouse.body2 = body2;
mouse.target = body2->GetWorldCenter();
mouse.maxForce = 25.0f;
mouse.timeStep = 1.0f / 60.f;
return ( b2MouseJoint* )world->CreateJoint( &mouse ); // ジョイント作成
}
// ボックス作成
b2Body* CreateSquear( int x, int y )
{
// 作業用変数
b2BodyDef bodyDef; // ボディ定義情報
b2PolygonDef shapeDef; // 形状定義情報
b2Body *b; // ボディ 形状追加するために使うだけなので、ここで定義
// ボックスの位置セット
bodyDef.position.Set( x, y ); // 座標セット
bodyDef.linearDamping = 0.0f; // ボディ単体の移動量減衰効果
bodyDef.angularDamping = 0.0f; // ボディ単体の角速度減衰効果
bodyDef.userData = ( void* )USERDATA_SQUEAR; // ユーザ定義データ BOX をセット
// 位置情報からボックスオブジェクトの作成
b = world->CreateBody( &bodyDef );
// ボックスがもつ形状の設定 中心を基準に設定される
shapeDef.SetAsBox( 30.0f, 30.0f ); // 横30*2 縦30*2 の大きさ
shapeDef.density = 1.0f; // 密度
shapeDef.friction = 0.1f; // 摩擦
shapeDef.restitution = 0.0f; // 弾性
b->CreateShape( &shapeDef); // 形状作成
b->SetMassFromShapes(); // 形状から当たり判定情報の作成
return b; // 今回作成したボディのポインタを返す
}
Re:Box2Dのマウスジョイントについて
>Examples\TestBed\Framework\Test.cpp」というのはどこのことを仰ったのでしょう。
Box2Dに入っているサンプルです。
バージョンによっては多少パスが異なる可能性がありますが、それでも多分 Test.cppという
ファイル名は同じだと思います。
最新版の Test.cppは
https://box2dflash.svn.sourceforge.net/ ... ork/Test.h
https://box2dflash.svn.sourceforge.net/ ... k/Test.cpp
ですね。
>どういう風にしたらいいか指摘のほどをお願いします
これだけではちょっとどうにもなりません。
zipに固めてアップできますか?
Box2Dに入っているサンプルです。
バージョンによっては多少パスが異なる可能性がありますが、それでも多分 Test.cppという
ファイル名は同じだと思います。
最新版の Test.cppは
https://box2dflash.svn.sourceforge.net/ ... ork/Test.h
https://box2dflash.svn.sourceforge.net/ ... k/Test.cpp
ですね。
>どういう風にしたらいいか指摘のほどをお願いします
これだけではちょっとどうにもなりません。
zipに固めてアップできますか?
Re:Box2Dのマウスジョイントについて
アップしました。
ちなみにFPS以外はソースを一括にしてあります。
内容は至ってシンプルで、ワールド内に地面とボックスがあるだけです。
このボックスをマウスで動かせるようにしたいのです。
ちなみにFPS以外はソースを一括にしてあります。
内容は至ってシンプルで、ワールド内に地面とボックスがあるだけです。
このボックスをマウスで動かせるようにしたいのです。

Re:Box2Dのマウスジョイントについて
インターフェースからみて使用しているライブラリのバージョンは 2.0xでしょうか。
とりあえず動くように直してみました。
大枠の構造は元のままなのですぐに判るとおもいますが、マウスの制御は Mouseクラスに
集約してあります。
細かいところがどう変更したかは diffツールなどで調べて下さい。
main.cppは2通り(main1/main2)あります。
これらは同時にコンパイルせず排他で使用して下さい。
・ main1.cpp
箱を2つ表示して、マウスで動かせるようにしたもの。
・ main2.cpp
さらに多くの箱を出し、全体的に大きな値になってた位置などの値を 1/10にしたもの。
一応実行ファイルの方もアップしておきます。
10/04/25 03:10 リンクミスがあったので、リンク修正。ついでに昔作った昔のサンプルをいれておきました。
かりんとあぷろだ 2号.jp 372MB
http://karinto2.jp/uploader/
No3832 1272132517.zip
DL pass : oGTQlJ6w8Apq

とりあえず動くように直してみました。
大枠の構造は元のままなのですぐに判るとおもいますが、マウスの制御は Mouseクラスに
集約してあります。
細かいところがどう変更したかは diffツールなどで調べて下さい。
main.cppは2通り(main1/main2)あります。
これらは同時にコンパイルせず排他で使用して下さい。
・ main1.cpp
箱を2つ表示して、マウスで動かせるようにしたもの。
・ main2.cpp
さらに多くの箱を出し、全体的に大きな値になってた位置などの値を 1/10にしたもの。
一応実行ファイルの方もアップしておきます。
10/04/25 03:10 リンクミスがあったので、リンク修正。ついでに昔作った昔のサンプルをいれておきました。
かりんとあぷろだ 2号.jp 372MB
http://karinto2.jp/uploader/
No3832 1272132517.zip
DL pass : oGTQlJ6w8Apq

Re:Box2Dのマウスジョイントについて
ちなみに「全体的に大きな値になってた位置などの値を 1/10にした」としたのは
http://www.box2d.org/manual.html
の 1.7 Unitsの項目に書いてあることが理由です。
Box2Dは MKS単位……メートル・キログラム・秒で扱われるとあります。
つまり大きさ 10といったらそれは 10メートルということになります。
又、動く物体の大きさに関しても 0.1mから 10m程度のものをという記述があります。
なので、それに合わせてワールドを設計する必要があります。
当然スクリーン座標系と Box2Dの扱う座標系は異なるので、何らかの変換システムが必要になるわけですが、
今回の main2では単純に Box2D座標系を 10倍したものをスクリーン座標系としている、というわけです。
http://www.box2d.org/manual.html
の 1.7 Unitsの項目に書いてあることが理由です。
Box2Dは MKS単位……メートル・キログラム・秒で扱われるとあります。
つまり大きさ 10といったらそれは 10メートルということになります。
又、動く物体の大きさに関しても 0.1mから 10m程度のものをという記述があります。
なので、それに合わせてワールドを設計する必要があります。
当然スクリーン座標系と Box2Dの扱う座標系は異なるので、何らかの変換システムが必要になるわけですが、
今回の main2では単純に Box2D座標系を 10倍したものをスクリーン座標系としている、というわけです。
Re:Box2Dのマウスジョイントについて
返信遅れてしまって申し訳ありません
今確認しながらやっています。
既に質問したい箇所がありますが、とりあえず全部確認してからしてみたいと思います。
それから、ライブラリにバージョンがあったこと知りませんでした(笑)
わざわざ丁寧に教えて下さって感謝しています。
ただ、完全に理解しようとするにはまだまだ時間がかかりそうです。
今確認しながらやっています。
既に質問したい箇所がありますが、とりあえず全部確認してからしてみたいと思います。
それから、ライブラリにバージョンがあったこと知りませんでした(笑)
わざわざ丁寧に教えて下さって感謝しています。
ただ、完全に理解しようとするにはまだまだ時間がかかりそうです。