🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

DXライブラリ

DXライブラリとは、DirectXを使ったWindowsソフトの開発に必ず付いて回るDirectXやWindows関連のプログラムを使い易くまとめた形で利用できるようにしたC++言語用のゲームライブラリです。

Q&A

解決済

2回答

2607閲覧

2Dゲームでマップ上の近いものだけ判定する方法。

退会済みユーザー

退会済みユーザー

総合スコア0

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

DXライブラリ

DXライブラリとは、DirectXを使ったWindowsソフトの開発に必ず付いて回るDirectXやWindows関連のプログラムを使い易くまとめた形で利用できるようにしたC++言語用のゲームライブラリです。

0グッド

0クリップ

投稿2021/03/19 00:59

編集2021/03/19 01:14

提示コードですがmStageが一万要素ある為マップとプレイヤーやマップと敵などを最初から当たり判定していると負荷が大きく処理が重たいのですがどうすればマップ上でプレイヤーに近いものだけを当たり判定出来るのでしょうか? 提示画像のようなゲームの場合左上から当たり判定をしていると。1万要素のベクターを当たり判定していると重たくなるので近いものだけを判定させたいです。

質問内容 [ 近いものだけど判定する場合どういった手法で行えばいいのか? ]

イメージ説明

cpp

1 std::shared_ptr<Stage> stage; //ステージ

cpp

1 2//エネミーとの当たり判定 3void Stage::ColEnemy(std::shared_ptr<Enemy_Mng> enemy) 4{ 5 //MapChip chip; 6 for (std::vector<MapChip>::iterator itr = mStage->begin(); itr != mStage->end(); itr++) 7 { 8 //chip = *itr; 9 for (std::vector<Enemy>::iterator it = enemy->getEnemy()->begin(); it != enemy->getEnemy()->end(); it++) 10 { 11 //交差判定 12 if (Box_Collision::Intersect(*itr->mCol, it->mCol) == true ) 13 { 14 switch (itr->mCol->getObjectType()) 15 { 16 //ブロック 17 case StageObjectType::Block: 18 { 19 glm::ivec2 pos = itr->mCol->getPosition(); 20 it->FixPos(pos); //座標を修正 21 it->setMove_Rand(); //乱数を再設定 22 it->setMovePixel(); //移動量をリセット 23 }break; 24 25 //レンガ 26 case StageObjectType::Brick: 27 { 28 glm::ivec2 pos = itr->mCol->getPosition(); 29 it->FixPos(pos); //座標を修正 30 it->setMove_Rand(); //乱数を再設定 31 it->setMovePixel(); //移動量をリセット 32 33 }break; 34 35 36 } 37 } 38 } 39 } 40} 41 42

cpp

1 2//エネミーのバレットとの当たり判定 3void Stage::ColEnemy_Bullet(std::shared_ptr<Enemy_Mng> enemy) 4{ 5 //ステージ 6 for (std::vector<MapChip>::iterator st = mStage->begin(); st != mStage->end(); st++) 7 { 8 //エネミー 9 for (std::vector<Enemy>::iterator itr = enemy->getEnemy()->begin(); itr != enemy->getEnemy()->end(); itr++) 10 { 11 //バレット 12 for (std::vector<Bullet>::iterator b = itr->getBullet()->begin(); b != itr->getBullet()->end(); b++) 13 { 14 //交差判定 15 if (Box_Collision::Intersect(b->mCol, *st->mCol) == true) 16 { 17 b->setPosition(b->getPosition()); 18 b->mIsMapHit = true; 19 } 20 } 21 } 22 } 23} 24 25

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/03/19 01:14

提示文章を修正しました。
退会済みユーザー

退会済みユーザー

2021/03/19 02:38

以前の質問の回答にも書きましたが、リリースビルドで問題ない速度になることから、1万件の判定自体が問題ではありません。 それでも、自、敵、それぞれの弾と計4回、1万件のループ回すなどは筋が悪い方法だと思います。 加えて、当たり判定のIntersectの箇所なども、getPosition、getSizeの呼び出しが多く、 コピーが多く発生するため、修正するほうがベターです。 あとはScrollも重かったので、1万件回している中の処理を見直すほうがいいと思います。
fana

2021/03/19 03:15

入れ子のforの順番に関して, mStage に関するループを一番内側に入れるべきではないかな.
guest

回答2

0

もしMapChipがすべて等間隔で並んでいるなら、BulletEnemy の座標周辺のMapChipを簡単に取り出せるはずです。その周辺MapChipとだけ当たり判定すればよいのでは。
(画像から等間隔だと判断しましたが、そういうのは前提条件として質問文に書くべきです。)

たとえばMapChipMAP_CHIP_SIZE 四方のサイズで、ステージが 100x100 で構成されているなら、座標 (x, y) の MapChip(*mStage)[floor(x / MAP_CHIP_SIZE) + floor(y / MAP_CHIP_SIZE) * 100] ですよねたぶん。

投稿2021/03/19 01:45

int32_t

総合スコア21679

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

どうすればマップ上でプレイヤーに近いものだけを当たり判定出来るのでしょうか? 提示画像のようなゲームの場合左上から当たり判定をしていると。1万要素のベクターを当たり判定していると重たくなるので近いものだけを判定させたいです。

「近い物」を列挙できるようなデータ構造なりを用意すれば良い,という話にしかならないような気がします.

マップの地形(ブロックみたいなの)の配置が2次元グリッド座標的であるならば,単純にはマップの地形を2次元の配列のような形で表現することもできるでしょう.
そのようなマップ情報のデータを,例えば

C

1//横6 x 縦4 マスのマップ地形情報 2const unsigned char Map[4][6] = { ... };

みたく保持しているとすれば,
ある対象に関する判定を行う際に,6x4=24マス全てをチェックせずとも,
「近い」範囲を絞り込んで,その範囲内のマスだけをチェックすることは簡単です.

C

1//マップの一部分(x0~x1, y0~y1)だけを走査 2for( int y=y0; y<=y1; ++y ) 3{ 4 for( int x=x0; x<=x1; ++x ) 5 { 6 Map[y][x]に関する判定 7 } 8}

この場合,提示画像の戦車のようなサイズのキャラクターであれば,最大2x2=4マス程度の範囲だけのチェックで済むのかもしれません.

投稿2021/03/19 01:36

編集2021/03/19 01:37
fana

総合スコア11985

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/03/19 01:39

ベクターを二次元にして今の座標割ることの画面のチップサイズである64で割って。その数字をの場所とその数字の周りの数を比較すれば行けるのでしょうか?
fana

2021/03/19 02:07 編集

> ベクターを二次元にして 実際に2次元のデータ構造にせずともvectorの要素の走査範囲を絞り込むことはできるんじゃないかと想像しますが, まぁそこはやりやすい形にすれば良いかと. 割ってどうのこうのという部分に関しては,意味合いはそんな話です.(具体的な算数部分はご自身で確認してください.)
fana

2021/03/19 02:09

動的に場所が移動するオブジェクト間の判定(例えば,戦車と砲弾の当たり判定とか)に関しては,個数次第では総当たりでも速度的には問題ないかもしれませんが, 総当たりだと大量すぎて同様に重い!とかいう場合には,同じような考え方で判定を減らせばよいです. (ゲーム全体の空間を適当に細かく区切って,各時刻で各オブジェクトがどの小空間にいるか,みたいな話.互いに遠く離れた小空間に属するオブジェクト間の判定はしなくていい)
退会済みユーザー

退会済みユーザー

2021/03/19 02:14

> 実際に2次元のデータ構造にせずともvectorの要素の走査範囲を絞り込むことはできるんじゃないかと想像しますが, どういった情報をもとに行うのでしょうか?想像がつきません。
fana

2021/03/19 03:11 編集

vetorが1次元だとして,その中の要素の順序というのは,しっちゃかめっちゃかではなく,何らかのまともな順序になっているでしょうから,それに基づいて決定できますよね. おそらく, > //マップの一部分(x0~x1, y0~y1)だけを走査 することを考えたとき, ・y = y0 ・x = x0 ~ x1 に相当する vectorのindexの範囲というのが算出できるでしょう. 同様に, ・y = y0+1 ・x = x0 ~ x1 に相当する vectorのindexの範囲も算出できる… … ・y = y1 ・x = x0 ~ x1 に相当する vectorのindexの範囲も算出できる といった感じに.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問