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

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

詳細はこちら
C++

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

DXライブラリ

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

Q&A

解決済

1回答

1506閲覧

[Dxlib]素早く動かすと当たり判定がおかしくなる原因が知りたい。GitHub全ソースあり

退会済みユーザー

退会済みユーザー

総合スコア0

C++

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

DXライブラリ

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

0グッド

1クリップ

投稿2021/02/22 03:39

編集2021/02/22 11:18

提示コードの///コメント部内部のコードですが当たり判定が以下の画像のような挙動をしてしまい上手く実装出来ません。これはどうしたらいいのでしょうか?
「左側に衝突して補正されて左キーを離してすぐに下キーを押押すと二枚目のように少しめり込み、キーを離すと上に補正されてしまいます。」
これはどうしたらいいのでしょうか?おそらくコメント内部のコードが悪いと思うのですが何度見ても正しいです。どうすればいいのでしょうか?

試したこと
キー入力は問題りませんでした。

その他
ゆっくりと動かすと問題なのですが。 素早くキーを押し変えると問題が発生します。

Github: https://github.com/Shigurechan/ActionGame

イメージ説明
イメージ説明
イメージ説明

2Dアクションゲーム
#define CELL ((int)48)

cpp

1#include "Input.hpp" 2 3// コンストラクタ 4Input::Input() 5{ 6 //キー状態配列を初期化 7 for (int i = 0; i < 256; i++) 8 { 9 Key[i] = 0; 10 } 11} 12 13//キー入力状態を更新 14void Input::Update() 15{ 16 char tmpKey[256]; // 現在のキーの入力状態を格納する 17 GetHitKeyStateAll(tmpKey); // 全てのキーの入力状態を得る 18 for (int i = 0; i < 256; i++) { 19 if (tmpKey[i] != 0) { // i番のキーコードに対応するキーが押されていたら 20 Key[i]++; // 加算 21 } 22 else { 23 // 押されていなければ 24 Key[i] = 0; // 0にする 25 } 26 } 27} 28 29//キーを押した時だけ 30bool Input::getKeyDown(unsigned char KeyCode) 31{ 32 if (Key[KeyCode] == 1) 33 { 34 return true; 35 } 36 else 37 { 38 return false; 39 } 40} 41 42//キーを押している時 43int Input::getKeyDownHold(unsigned char KeyCode) 44{ 45 //printf("あああ\n"); 46 return Key[KeyCode]; 47} 48 49 50

cpp

1#include "Player.hpp" 2 3//コンストラクタ 4Player::Player(Entry* e) : Actor(e) 5{ 6 7} 8 9//座標を修正 10void Player::FixPos(glm::ivec2 pos) 11{ 12 if (mVector == VECTOR_UP) 13 { 14 printf("UP\n"); 15 mPosition.y = pos.y + CELL + CELL / 2; 16 } 17 else if (mVector == VECTOR_DOWN) 18 { 19 printf("DOWN\n"); 20 21 mPosition.y = pos.y - (CELL / 2); 22 } 23 else if (mVector == VECTOR_LEFT) 24 { 25 printf("LEFT\n"); 26 27 mPosition.x = pos.x + (CELL + CELL / 2); 28 } 29 else if (mVector == VECTOR_RIGHT) 30 { 31 printf("RIGHT\n"); 32 33 mPosition.x = pos.x - (CELL / 2); 34 } 35 else { 36 printf("None\n"); 37 } 38 39} 40 41 42 43 44//更新 45void Player::Update() 46{ 47 DrawFormatString(0,0,GetColor(0,255,0),"Position: %d , %d ",mPosition.x,mPosition.y); 48 49 50 51 //printf("%d\n",mSpeed_Max); 52 Bullet_Update(); //バレットを更新 53 Player_Update(); //プレイヤー更新 54} 55 56//ステータスを設定 57void Player::set_Bulid(ItemData data) 58{ 59 60 mSpeed_Max += data.mSpeed_Max; 61 62 HP_Max += data.HP_Max; 63 HP += data.HP_Rec; 64 HP_autoRec += data.HP_autoRec; 65 66 Attack += data.Attack; 67 68 Coin += data.Coin; 69 70} 71 72 73 74//キー入力部 75////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 76//プレイヤー 更新 77void Player::Player_Update() 78{ 79 //printf("いいいい\n"); 80 81 82 mSpeed = mSpeed_Max; 83 //キー入力 84 if (Owner->InputKey->getKeyDownHold(KEY_INPUT_LEFT) > 0) 85 { 86 mVector = VECTOR_LEFT; //方向 87 } 88 else if (Owner->InputKey->getKeyDownHold(KEY_INPUT_RIGHT) > 0) 89 { 90 mVector = VECTOR_RIGHT; //方向 91 } 92 else if (Owner->InputKey->getKeyDownHold(KEY_INPUT_UP) > 0) 93 { 94 mVector = VECTOR_UP; //方向 95 } 96 else if (Owner->InputKey->getKeyDownHold(KEY_INPUT_DOWN) > 0) 97 { 98 mVector = VECTOR_DOWN; //方向 99 } 100 else { 101 mSpeed = 0; 102 } 103 104 105 106 107 108 109 //当たり判定 110 111 //スプライトの中心からのため修正 112 glm::ivec2 pos = mPosition; 113 pos.x += -(CELL / 2); 114 pos.y += -(CELL / 2); 115 mCol.setPosition(pos); 116 mCol.setSize(mSize); 117 mCol.setTrigger(false); 118 mCol.setVector(mVector); 119 120 121} 122///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 123//描画 124void Player::Draw() 125{ 126 Bullet_Draw(); //バレット描画 127 Player_Draw(); //プレイヤー描画 128} 129 130 131//プレイヤー 描画 132void Player::Player_Draw() 133{ 134 //方向 135 if (mVector == VECTOR_UP) 136 { 137 DrawRotaGraph(mPosition.x, mPosition.y, 1.0, 0, mSprite, true, false); 138 } 139 else if (mVector == VECTOR_DOWN) 140 { 141 DrawRotaGraph(mPosition.x, mPosition.y, 1.0, PI, mSprite, true, false); 142 } 143 else if (mVector == VECTOR_LEFT) 144 { 145 DrawRotaGraph(mPosition.x, mPosition.y, 1.0, -(PI * 2) / 4, mSprite, true, false); 146 } 147 else if (mVector == VECTOR_RIGHT) 148 { 149 DrawRotaGraph(mPosition.x, mPosition.y, 1.0, (PI * 2) / 4, mSprite, true, false); 150 } 151 152 DrawPixel(mPosition.x, mPosition.y,GetColor(0,255,0)); 153} 154 155 156//バレット 描画 157void Player::Bullet_Draw() 158{ 159 for (std::vector<Bullet>::iterator itr = mBullet->begin(); itr != mBullet->end(); itr++) 160 { 161 itr->Draw(); //バレット描画 162 } 163} 164 165 166 167//デストラクタ 168Player::~Player() 169{ 170 171} 172

cpp

1#include "Stage.hpp" 2 3//コンストラクタ 4Stage::Stage(Entry* e) 5{ 6 7} 8 9//更新 10 11///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 12//プレイヤーとの当たり判定 13void Stage::ColPlayer(Player &player) 14{ 15 for (std::vector<MapChip>::iterator itr = mStage.begin(); itr != mStage.end(); itr++) 16 { 17 if (Box_Collision::Intersect(itr->mCol,player.mCol) == true) 18 { 19 switch (itr->mCol.getObjectType()) 20 { 21 //ショップ 22 case StageObjectType::Shop: 23 { 24 if (Owner->InputKey->getKeyDown(KEY_INPUT_P) == true) 25 { 26 player.setIsMenu(true); 27 player.FixPos(itr->mCol.getPosition()); 28 } 29 } 30 break; 31 32 //レンガとの当たり判定 33 case StageObjectType::Brick: 34 { 35 player.FixPos(itr->mCol.getPosition()); 36 } 37 break; 38 39 //ブロックとの当たり判定 40 case StageObjectType::Block: 41 { 42 43 player.FixPos(itr->mCol.getPosition()); 44 } 45 break; 46 } 47 } 48 } 49} 50/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 51 52 53//画面スクロール 54void Stage::ScrollMap(Player& player) 55{ 56 //左右移動 57 if (player.getPosition().x > (SCREEN_WIDTH - 100) + player.getSpeed() && player.getVector() == VECTOR_RIGHT) { 58 printf("Right\n"); 59 60 for (std::vector<MapChip>::iterator itr = mStage.begin(); itr != mStage.end(); itr++) 61 { 62 63 glm::ivec2 pos; 64 pos = itr->getPosition(); 65 pos.x += -player.getSpeed(); 66 67 itr->setPosition(pos); 68 } 69 } 70 else if (player.getPosition().x < ( 100 ) + player.getSpeed() && player.getVector() == VECTOR_LEFT) 71 { 72 printf("Left\n"); 73 for (std::vector<MapChip>::iterator itr = mStage.begin(); itr != mStage.end(); itr++) 74 { 75 glm::ivec2 pos; 76 pos = itr->getPosition(); 77 pos.x += player.getSpeed(); 78 79 itr->setPosition(pos); 80 } 81 82 //上下移動 83 }else if (player.getPosition().y > (SCREEN_HEIGHT - 100) + player.getSpeed() && player.getVector() == VECTOR_DOWN) { 84 printf("Dwon\n"); 85 86 for (std::vector<MapChip>::iterator itr = mStage.begin(); itr != mStage.end(); itr++) 87 { 88 89 glm::ivec2 pos; 90 pos = itr->getPosition(); 91 pos.y += -player.getSpeed(); 92 93 itr->setPosition(pos); 94 } 95 } 96 else if (player.getPosition().y < (100) + player.getSpeed() && player.getVector() == VECTOR_UP) 97 { 98 printf("Up\n"); 99 for (std::vector<MapChip>::iterator itr = mStage.begin(); itr != mStage.end(); itr++) 100 { 101 glm::ivec2 pos; 102 pos = itr->getPosition(); 103 pos.y += player.getSpeed(); 104 105 itr->setPosition(pos); 106 } 107 } 108 else { 109 110 111 //移動 112 int speed = player.getSpeed(); 113 glm::ivec2 vec = player.getVector(); 114 glm::ivec2 pos = player.getPosition(); 115 pos.x += vec.x * speed; 116 pos.y += vec.y * speed; 117 118 player.setPosition(pos); 119 } 120} 121 122//エネミーとの当たり判定 123void Stage::ColEnemy(std::shared_ptr<std::vector<Enemy>> enemy) 124{ 125 for (std::vector<MapChip>::iterator itr = mStage.begin(); itr != mStage.end(); itr++) 126 { 127 MapChip chip = *itr; 128 for (std::vector<Enemy>::iterator itr = enemy->begin(); itr != enemy->end(); itr++) 129 { 130 //交差判定 131 if (Box_Collision::Intersect(chip.mCol, itr->mCol) == true ) 132 { 133 switch (chip.mCol.getObjectType()) 134 { 135 136 //ブロック 137 case StageObjectType::Block: 138 { 139 itr->FixPos(chip.mCol.getPosition()); 140 itr->setMove_Rand(); 141 } 142 143 144 } 145 } 146 } 147 } 148 149} 150 151 152 153 154 155 156//デストラクタ 157Stage::~Stage() 158{ 159 160} 161 162

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

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

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

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

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

yumetodo

2021/02/22 03:45

そもそも肝心のキー操作系の部分のコードを載せないでどうでもいいシーン管理とかのせて何を聞きたいんだ。
dodox86

2021/02/22 04:02

この質問に限らないのですが、何度も同じような原因の質問を重ねたり、指摘を受けてからの追記、修正をたび重ねているところを見ると、自分で問題のポイントを抑えられていないのではないでしょうか。自力で考え、解決することを放棄してませんか。
txty

2021/02/22 04:19

yumetodoさん>それ私のせいかも。キー操作で遷移分ければいいとかいったから shosinsha_さん>遷移のレスください。答えられませんが、レスないで途中でおわると若干気持ち悪くなるので。
stdio

2021/02/22 05:07

すみません。 このゲームのジャンルは何でしょうか?
退会済みユーザー

退会済みユーザー

2021/02/22 05:25

2Dのアクションゲームです。  質問内容を修正しました。
stdio

2021/02/22 05:37

当たり判定のメイン関数であるBox_Collision::Intersectが機能していない可能性があります。 しっかりテストしましたか?
退会済みユーザー

退会済みユーザー

2021/02/22 05:38

しました。機能してます。trueを返しているので
yumetodo

2021/02/22 06:15

というかキー入力の判定部にOutputDebugStringつけて意図した回数そこを通過してるか見たらどうですかね?
退会済みユーザー

退会済みユーザー

2021/02/22 08:10

確認しましたが合ってました。
txty

2021/02/22 08:45

つまらないこと聞くけどあたり判定で潜った分元に戻す的なコードはどこ?半分ぐらいしか読んでないけど
退会済みユーザー

退会済みユーザー

2021/02/22 08:51

void Player::FixPos(glm::ivec2 pos)関数です。
txty

2021/02/22 09:04

2/cellは中点だろうけど、ぱっと見わからないから説明してもらっていいですか
退会済みユーザー

退会済みユーザー

2021/02/22 09:18

描画関数が回転する関数なので中心点が真ん中なので一旦左上に戻してそこからのCELL,CELLを大きさにしています。
txty

2021/02/22 09:51 編集

図かなんかあればすぐ分かるんだろ うけど、左上ってどうやってわかるんですか。後,説明ありがとうございました
退会済みユーザー

退会済みユーザー

2021/02/22 10:04

dxlib では左上が原点なので
退会済みユーザー

退会済みユーザー

2021/02/22 10:16

文章を修正しました。
txty

2021/02/22 10:53 編集

左上はレンガの左上みたいにして衝突したら強制的にレンガの左上みたいなところに持っていきcellを足して元にいた場所にもどすでいいの?コードはみてないけど。
退会済みユーザー

退会済みユーザー

2021/02/22 10:54 編集

はい、そうです。というかめり込み判定は普通に出来ているのですがなぜか素早く他のキーを押すと説明文のようなバグが発生します。これはなぜでしょうか?ゆっくりやると発生しません。w
fana

2021/02/22 11:30 編集

要は「衝突」した状態をまともに解消できていない状況が起こり得る,すなわち「衝突」と判定され得る状況のままで次の時刻以降に処理が進むことがある のだろうと推測. その場合,次の時刻に進むと再び「衝突した」と判定されることになるわけだが,その衝突を解消しようとして走る処理の内容というのが,"その時刻におけるキーの押下状態"に依存しているのであろう. その結果として,「素早く」操作した場合としなかった場合とで,解消処理の働きが異なる結果になるのではなかろうか.
退会済みユーザー

退会済みユーザー

2021/02/22 11:31

なるほど。ではどのうに修正したらいいのでしょうか?どうしても修正方法がわかりません。 githubのソースを参考に教えてくますでしょうか?
fana

2021/02/22 11:43 編集

そんなことまでする気はないです. というか,上記の推測を書いてから2分経過とかの時点で「どうしても修正方法がわからん」とか言われても,自身で修正する気が無いのだとしか思えません. 内容の成否について全く検証もされていないでしょう. あなたのプログラム固有のバグを修正したところで私には何も得るものがないので,そのような作業に従事するつもりはありません. もしも上記の推測が相応に正しいのであれば,私なら最初から作り直すレベルの修正を考えます. このコードの「正当な動作」を考えることは非常に難しいであろう,と想像するからです. そもそも各処理の「正当な動作」がしっかりと定義できているのかも謎です.もしもそのようなものが存在するのであれば,現象も修正方法も何一つわからないとか言わずにご自身で相応にデバッグを行えるハズです.
退会済みユーザー

退会済みユーザー

2021/02/22 12:19

分かりました。
txty

2021/02/22 12:30

興味本位で一応聞くけどcell以上大きめで戻すとどうなるんですか。これ以上は聞かないけど。
yumetodo

2021/02/22 21:48

ひとくちにキー入力と言ってもキーが押されたときなのか、一定時間押されているときなのか、押されたキーが離されたときなのか、いろいろありますよね。DxLibの場合これらをGetHitKeysを毎フレーム呼び出して適切に状態を管理しなければならず非常に難易度が高いです。いっそのことOpenSiv3Dでも使ってはどうですかね
退会済みユーザー

退会済みユーザー

2021/02/22 23:30

そうですか。キー入力は確認したのですが...
stdio

2021/02/23 01:46

突然すみません。私の予想では、やはりBox_Collision::Intersectの使い方が間違っているように思えます。衝突判定の方法を今一度ご検討しなおして下さい。 確かに私もDxLibでキーの入力やったことありますが、専用のクラスを作って、外部コントローラとキーボードの設定合わせたりとか色々面倒なこと多かった記憶あります...
fana

2021/02/23 02:21

キー入力の実装がどれだけ面倒か知らんけども, 「各処理の妥当な処理結果がどうあるべきか」が定まっているのであれば, 問題の現象が発生する状況からスタートさせてデバッグ実行していくとか 各所に適当なログ出力でも仕込むとかすればすぐに原因を絞り込んでいける話なんじゃないの? 「その状況においてはこうあるべき」という話と反する結果を生じている場所を見つけるだけの作業だと思うのだが.
guest

回答1

0

ベストアンサー

下記の提示コードですが以下の画面スクロール部でプレイヤーが移動するコードを書いている為でした。自己解決です。

動いてめり込み 離して動きが止まり 当たり判定を行う(めり込みしている状態)
という順序でおかしくなっていました。

cpp

1#include "Game_Scene.hpp" 2 3//コンストラクタ 4Game_Scene::Game_Scene(Scene_Type t,Entry *e) : Scene_base(t,e) 5{ 6 Owner = e; 7 8 9 flag = false; //ショップ中かどうか? 10 player = std::make_shared<Player>(e); //プレイヤー 11 stage = std::make_shared<Stage>(e); //ステージ 12 shop = std::make_shared<Shop>(e); //ショップメニュー 13 enemy_mng = std::make_shared<Enemy_Mng>(); //エネミー管理 14 15 16 17} 18 19//更新 20void Game_Scene::Update() 21{ 22 //バトル 23 if (player->getIsMenu() == false) 24 { 25 26 stage->ScrollMap(*player); //画面スクロール 27 stage->Update(); //ステージ更新 28 29 player->Update(); //プレイヤー更新 30 stage->ColPlayer(*player); //プレイヤーとマップとの当たり判定 31 32 enemy_mng->Update(); //エネミー更新 33 34 stage->ColBullet(player->getBullet()); //バレットとマップとの当たり判定 35 stage->ColEnemy(enemy_mng->getEnemy()); 36 } 37 else 38 { 39 //ショップ画面 40 if (shop->getState() == true) 41 { 42 shop->Update(*player); 43 } 44 else { 45 player->setIsMenu(false); 46 shop = std::make_shared <Shop>(Owner); 47 } 48 } 49 50 51 52} 53 54//描画 55void Game_Scene::Draw() 56{ 57 58 player->Draw(); //プレイヤー描画 59 stage->Draw(); //ステージ描画 60 //enemy_mng->Draw(); 61 62 //ショップ画面 63 if (player->getIsMenu() == true) 64 { 65 shop->Draw(); 66 } 67 68 69 70} 71 72//デストラクタ 73Game_Scene::~Game_Scene() 74{ 75 76} 77

cpp

1//画面スクロール 2void Stage::ScrollMap(Player& player) 3{ 4 //左右移動 5 if (player.getPosition().x > (SCREEN_WIDTH - 100) + player.getSpeed() && player.getVector() == VECTOR_RIGHT) 6 { 7 for (std::vector<MapChip>::iterator itr = mStage.begin(); itr != mStage.end(); itr++) 8 { 9 glm::ivec2 pos; 10 pos = itr->getPosition(); 11 pos.x += -player.getSpeed(); 12 itr->setPosition(pos); 13 } 14 15 glm::ivec2 pos = player.getPosition(); 16 pos.x = player.getPosition().x - player.getSpeed(); 17 player.setPosition(pos); 18 } 19 else if (player.getPosition().x < ( 100 ) + player.getSpeed() && player.getVector() == VECTOR_LEFT) 20 { 21 for (std::vector<MapChip>::iterator itr = mStage.begin(); itr != mStage.end(); itr++) 22 { 23 glm::ivec2 pos; 24 pos = itr->getPosition(); 25 pos.x += player.getSpeed(); 26 itr->setPosition(pos); 27 } 28 29 glm::ivec2 pos = player.getPosition(); 30 pos.x = player.getPosition().x + player.getSpeed(); 31 player.setPosition(pos); 32 33 //上下移動 34 }else if (player.getPosition().y > (SCREEN_HEIGHT - 100) + player.getSpeed() && player.getVector() == VECTOR_DOWN) 35 { 36 37 for (std::vector<MapChip>::iterator itr = mStage.begin(); itr != mStage.end(); itr++) 38 { 39 glm::ivec2 pos; 40 pos = itr->getPosition(); 41 pos.y += -player.getSpeed(); 42 itr->setPosition(pos); 43 } 44 45 glm::ivec2 pos = player.getPosition(); 46 pos.y = player.getPosition().y - player.getSpeed(); 47 player.setPosition(pos); 48 } 49 else if (player.getPosition().y < (100) + player.getSpeed() && player.getVector() == VECTOR_UP) 50 { 51 for (std::vector<MapChip>::iterator itr = mStage.begin(); itr != mStage.end(); itr++) 52 { 53 glm::ivec2 pos; 54 pos = itr->getPosition(); 55 pos.y += player.getSpeed(); 56 itr->setPosition(pos); 57 } 58 59 glm::ivec2 pos = player.getPosition(); 60 pos.y = player.getPosition().y + player.getSpeed(); 61 player.setPosition(pos); 62 } 63} 64

投稿2021/02/23 04:47

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問