はかせのラボ

私の頭の中を書いていく雑記ブログです

DirectX ボム実装④

あいさつ

どうも、はかせです。
今日も今日とて体調は優れません。
相変わらず体がだるいですし頭が回ってない気がします。

ただもうこの状態になって約一週間。
さすがに慣れました。
そして慣れて多少どうにかなるということは
致命的な何かではないということだと思います。

ということでようやく続きです。

進捗

昨日はなぜか衝突が取れないという話をしました。
ただよくよく見て探ってみるとただのアホだったのが浮き彫りになってきました。

私のプログラムでは衝突は以下の手順で処理します。
①タグごとにグルーピングしたコライダー配列作成
②各配列同士で衝突判定
③衝突しているもののみ衝突応答を行う

昨日衝突が行えなかった理由それは・・・・

アイテムタグでグルーピングしたコライダー配列を作成していなかったから

・・・・皆さんが思っていることは何となくわかります。

いけしゃあしゃあと仕組みを説明して、
しかもその仕組みを作ったのは自分で誰よりもわかっているはずなのに、
そいつが処理始めるための前提準備を忘れるとか、
馬鹿かと。アホかと。いっぺん〇んでくればと。
そう思っていることでしょう。
実際私が気づいたとき自分自身に対してそう思いましたから。

ただ昨日はそんなことにさえ気づけないほど頭が回っていなかったんだということでこの話は終えたいと思います。
(これ以上は精神的ダメージがでかすぎるので許してくださいorz)

実装方法

さて、気を取り直していつもどおりいけしゃあしゃあと説明していきます。
まずボムはプレイヤーには当たってほしいけど、弾には当たってほしくない。
それでいて当たった時プレイヤーにダメージを与えてほしくはない。

ということで今までのキャラクターのコライダー配列、
もしくは弾のコライダー配列に入れてやると
管理がめんどくさそう色々不都合や不必要な比較が行われそうだったので
別のアイテムのコライダー配列を作成し管理することにしました。(前回の問題解決)

とはいっても特別なことをするわけではなく今まで無視してたアイテムタグの付いたコライダーを
格納してキャラクターとのみ衝突判定を行うようしただけです。

void CollisionManager::SetGameObjects(std::vector<DXGameObject*> gameObjects)
{
	//各コライダー配列をクリア
	mShooterColliderList.clear();
	mItemColliderList.clear();
	mBulletColliderList.clear();
	for(auto game:gameObjects)
	{
		//アクティブでなければ無視
		if (!game->GetEnable()) continue;
		auto com = game->GetComponent<Collider2D>();
		//コライダーがなければ無視する
		if (com == nullptr) continue;
		//コライダーがアクティブでなければ無視
		if (!com->GetEnable()) continue;
		auto shooter = game->GetTag();
		//キャラクター
		if (shooter == PlayerTag || shooter == EnemyTag)
		{
			mShooterColliderList.push_back(com);
		}
		//弾
		else if (shooter == PlayerBullet || shooter == EnemyBullet)
		{
			mBulletColliderList.push_back(com);
		}
		//アイテム←new!
		else if(shooter == Item)
		{
			mItemColliderList.push_back(com);
		}
	}
}

void CollisionManager::Collision()
{
	//当たり判定
	for (auto shooter : mShooterColliderList)
	{
		auto shooterTag = shooter->GetTag();
		//キャラクター同士の当たり判定
		for (auto shooter2 : mShooterColliderList)
		{
			auto shooter2Tag = shooter2->GetTag();
			if (!IsCollisionJudge(shooterTag, shooter2Tag)) continue;
			shooter->IsCollision(shooter2);
			shooter2->IsCollision(shooter);
		}
		//キャラクターとアイテムの当たり判定
		for(auto item:mItemColliderList)
		{
			auto itemTag = item->GetTag();
			if (!IsCollisionJudge(shooterTag, itemTag)) continue;
			shooter->IsCollision(item);
			item->IsCollision(shooter);
		}
		//キャラクターと弾の当たり判定
		for (auto bullet : mBulletColliderList)
		{
			auto bulletTag = bullet->GetTag();
			if (!IsCollisionJudge(shooterTag, bulletTag)) continue;
			shooter->IsCollision(bullet);
			bullet->IsCollision(shooter);
		}
	}

	//キャラクターの衝突応答
	for (auto shooter : mShooterColliderList)
	{
		//衝突していたら
		if (shooter->IsCollided()) shooter->OnCollision();
	}
	//アイテムの衝突応答←new!
	for(auto item:mItemColliderList)
	{
		//衝突していたら
		if (item->IsCollided()) item->OnCollision();
	}
	//弾の衝突応答
	for (auto bullet : mBulletColliderList)
	{
		//衝突していたら
		if (bullet->IsCollided()) bullet->OnCollision();
	}
}

今までのコードに埋め込んだだけですね。
これで衝突処理が出来ます。(本当に昨日の私はポンコツだったなぁ)

あとはアイテム側の実装ですね。
基本としては
①衝突
②衝突相手がプレイヤーか判断
③プレイヤーならば処理行う

となります。

今回③処理はプレイヤー側に受け口を作ってそれを呼び出しています。

void Bomb::OnCollisionEnter2D(Collider2D * col)
{
	auto game = col->GetGameObject();
	auto player = game->GetComponent<Player>();
	if (player == nullptr) return;
	player->AddBomb();
	mGameObject->SetEnable(false);
}

/*プレイヤーの受け口*/
//ボムを追加
void AddBomb() 
{
	mBombNum++;
	if (mBombNum >= mMaxBombNum) mBombNum = mMaxBombNum;
}
//パワーアップ
void PowerUp()
{
	mPower++;
	if (mPower >= mMaxPower) mPower = mMaxPower;
}

ついでに出来そうだったのでパワーアップも作ってみました。
では久しぶりの動画です。
youtu.be

Bがボム、Pがパワーアップです。
Pを取ったら弾数が増えてます。
またBを取らないとボムは使えません。

あとがき

ボム実装+αでした。
前回あまりにもポンコツでなにもなかったのでいつも以上に頑張りました。
なんでいつも以上に疲れました。
終わります。
それでは今回はこの辺でノシ