Home > C言語(Windows) > Box2D+DXライブラリによるマリオもどきのテスト その2

Box2D+DXライブラリによるマリオもどきのテスト その2

マリオもどきにモンスターを追加して、だいたいこんなもんかなという感じになりました。左右はカーソルキーで移動、Xキーでジャンプです。しゃがむことはできません。

WS001227

・画像をクリックするとYoutubeで再生

実行ファイルはここ、ソースコードはここにあります。ソースコードは要ユーザー登録ですが、書籍の購入者でなくともダウンロードできます。マップエディタも少しバージョンアップしました。

C言語VS2010編』のサンプルを元にしているので、キモとなる部分に絞って説明すると……


1.主人公のボディ

主人公のキャラクターは電車のような変な形になっていますが、大きい四角が胴体、下の2つの円が足、上の小さな四角が拳です。4つのフィクスチャで1つのボディを構成しています。
複数に分かれているのは、「敵に触れるとゲームオーバーになる部分」、「地面との接地、敵の踏みつぶしができる部分」、「ブロックを下から殴って壊す部分」を判定するためです。

void CreateHero(float sx, float sy){
	//ボディ定義
	b2BodyDef bodyDef;
	bodyDef.type = b2_dynamicBody;	//動的ボディ
	bodyDef.position.Set(PHS(sx), PHS(sy));
	//ボディ作成
	b2Body* body = g_world.CreateBody(&bodyDef);
	//胴体のフィクスチャ定義
	b2FixtureDef fixtureDef;
	b2PolygonShape box;
	box.SetAsBox(PHS(16.0f), PHS(10.0f));
	fixtureDef.shape = &box;
	fixtureDef.density = 1.0f;		 //密度
	fixtureDef.restitution = 0.1f;//反発力
	fixtureDef.friction = 0.3f;	//摩擦力
	fixtureDef.filter.categoryBits = 1;
	fixtureDef.filter.maskBits = 1+2;
	g_stage.hero_head =	body->CreateFixture(&fixtureDef);
	//拳
	box.SetAsBox(PHS(2.0f), PHS(3.0f),
		b2Vec2( 0.0f, -PHS(15.0f)), 0.0f);
	g_stage.hero_fist = body->CreateFixture(&fixtureDef);
	//下半身
	b2CircleShape circle;
	circle.m_radius = PHS(10.0f);
	circle.m_p = b2Vec2(PHS(6.0f), PHS(18.0f));//位置
	fixtureDef.shape = &circle;
	fixtureDef.friction = 0.8f;	//摩擦力
	g_stage.hero_reg1 = body->CreateFixture(&fixtureDef);
	circle.m_p = b2Vec2(-PHS(6.0f), PHS(18.0f));
	g_stage.hero_reg2 = body->CreateFixture(&fixtureDef);
	//キャラクター設定
    g_stage.hero.body = body;
	g_stage.hero.type = HERO_MARION;
	g_stage.hero.body->SetUserData(&g_stage.hero);
}

衝突判定を行うCollision関数の中で、ボディのどのフィクスチャが何と衝突しているのかを見て、処理を分けています。

//衝突判定
void Collision(){
	//接触確認ループ
	for(b2Contact* c = g_world.GetContactList(); c!=NULL;
		c = c->GetNext())
	{
		if(c->IsTouching() == false) continue;
		//接触しているボディを取り出す
		b2Body* bd[2];
		b2Fixture* fx[2];
		fx[0] = c->GetFixtureA();
		fx[1] = c->GetFixtureB();
		bd[0] = fx[0]->GetBody();
		bd[1] = fx[1]->GetBody();
		//ボディチェック
		for(int i=0; i<2; i++){
			b2Body *obd = bd[ (i+1) % 2];//衝突相手
			Character *ch = (Character *)bd[i]->GetUserData();
			Character *och = (Character *)obd->GetUserData();
			if(ch != NULL && och != NULL){
				//ヒーロー関連のチェック
				if(ch->type == HERO_MARION)
				{
					//接地チェック
					if( fx[i] == g_stage.hero_reg1 ||
						fx[i] == g_stage.hero_reg2)
					{
						g_stage.isontheground = true;
						//モンスター踏みつぶし
						if(och->type >= MAP_MONSTER_MASHROOM)
						{
							och->damage = 100.0f;
						}
					}
					//壊せる壁に拳が当たる
					if(fx[i] == g_stage.hero_fist){
						if(och->type == MAP_FRAGILE){
							och->damage = 100.0f;
						}
					}

2.モンスターの出現処理

モンスターの出現タイミングを設定するEvent構造体というものを作り、イベントの位置や主人公がどこまで近づいたら反応するかを決める距離(range)などを記録しておきます。

//イベント構造体
struct Event{
	int type;		//イベントの種類(モンスターの種類)
	bool used;		//使用中(発動前)フラグ
	float x,y;		//位置
	float range;	//範囲
};

後はEvent型配列変数を作っておき、主人公との距離を毎回チェックして、範囲内に来たらモンスターのキャラクターを新規作成します。一度出現させたらEventのusedをfalseにします。

3.壁に当たったモンスターの移動方向を反転する

前述のCollision関数の中で、typeがモンスターのキャラクターが居たら、そのマニフォルドを取得します。マニフォルドのlocalNormalが当たった方向を示すベクトルなのですが、これはモンスターのボディではなく衝突相手のボディが基準になるため、モンスターの進行方向とは逆になります。今回横方向だけ見ればいいので、2つのベクトルのx値の正負が逆であれば、進行方向を反転させます。

//モンスター左右方向転換
if(ch->type >= MAP_MONSTER_MASHROOM){
	b2Manifold *manifold = c->GetManifold();
	if(manifold->type == b2Manifold::e_faceA){
		//進行方向で衝突が起きていたら
		if( (manifold->localNormal.x < -0.2f &&
			ch->vecx > 0.0f) ||
			(manifold->localNormal.x > 0.2f &&
			ch->vecx < 0.0f) )
		{
			//移動方向を逆転
			ch->vecx = -ch->vecx;
		}
	}
}

4.マップエディタの小改良

キャラクターのサイズを少し小さめにしたかったので、マップサイズの設定ダイアログボックスにグリッドを設定するボックスを付けました。

WS001228

 

本物のマリオとは微妙に動きが違い、モンスターを踏んだ後よろめいたり、壁にぶらさがったり、よじのぼったりしますが、そのあたりはプログラムの作り方がまったく違うので、ご勘弁ください。Box2Dを使うと良くも悪くも動きが生っぽくなりますね。

Comments:0

Comment Form
Remember personal info

Trackbacks:5

Trackback URL for this entry
http://i-libro.net/wpmu/blog/archives/451/trackback
Listed below are links to weblogs that reference
Box2D+DXライブラリによるマリオもどきのテスト その2 from わくわくプログラミング自習室 Blogs
pingback from iPhone用のBox2Dを調べる | iPhoneアプリ開発日記 11-01-16 (日) 18:22

[...] これで解析終了。次はWindows用に作成したスーパーマリオ風アクションゲームを移植してみましょう。 [...]

pingback from ゲーム開始直後で即死亡 | iPhoneアプリ開発日記 11-02-07 (月) 19:59

[...] Windows用に作成したスーパーマリオ風アクションゲームを移植する計画はちょっとずつ進めており、昨夜ようやくすべてのビルドエラーが消えて実行可能な状態になりました。 [...]

pingback from わくわくプログラミング自習室 Blogs - 【DXライブラリ3D入門】アニメーションの切り替えを滑らかにする 11-02-28 (月) 22:35

[...] これで3Dグラフィックスを使った2Dゲームを作るために必要な知識は、一通り説明が終わりました。次の最終記事ではその実例として、1ヶ月ほど前に作ったマリオもどきのテストプログラムと今回のプログラムを組み合わせ、MMDモデルを使ったマリオ風ゲームを作成します。 [...]

pingback from わくわくプログラミング自習室 Blogs - 【DXライブラリ3D入門】MikuMikuDance風かつマリオブラザーズ風なゲームデモ公開 11-03-06 (日) 5:21

[...] ようやくマリオブラザーズ風のゲームデモができあがりました。元々2D前提で作ったものを3Dに変更したため、座標変換がややこしいことになってしまい、予想以上に手こずりました。取り急ぎソースコードと実行ファイルを公開しますが、解説はまた日を改めてとさせてください。 [...]

pingback from わくわくプログラミング自習室 Blogs - 【DXライブラリ3D入門】2Dに合わせて3Dグラフィックスを描画する その1 11-03-10 (木) 18:42

[...] 今回から数回に渡ってマリオブラザーズ風のゲームデモのグラフィックス処理について解説していきます。このゲームはもともと2D向けに作ったものです。ジャンプ処理のあたりを少し調整しましたが、基本的にはほとんど同じプログラムです。main.hの12行目にある定数B2D_DEBUG_DRAWのコメントを解除してから実行すると…… [...]

Home > C言語(Windows) > Box2D+DXライブラリによるマリオもどきのテスト その2

Amazonリンク

Return to page top