質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
86.12%
C++

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

解決済

[ゲーム開発] 線分と円の当たり判定が実装出来ない。

退会済みユーザー

退会済みユーザー

総合スコア0

C++

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

2回答

0リアクション

0クリップ

681閲覧

投稿2022/08/22 12:33

編集2022/08/22 13:57

提示コードですが線分の円の当たり判定が実装出来ません、デバッグしたところによるよ常にstd::cout<<"(dot01 * dot02) <= 0.0f"<<std::endl;が成立しているみたいで常に交差しているみたいです。これはなぜなのでしょうか?参考サイトを参考にコードを入力したのですが③では②の結果と円の半径を比較します。部のあたりからif()文に内部なのか外に追記するのかわかりません。また他の部分をも確認しましたが問題ないです。

イメージ説明

参考サイト: https://yttm-work.jp/collision/collision_0006.html#:~:text=%E3%81%93%E3%81%AE%E6%99%82%E3%81%AB%E5%BD%93%E3%81%9F%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B%E3%81%A9%E3%81%86%E3%81%8B,%E5%B0%8F%E3%81%95%E3%81%8B%E3%81%A3%E3%81%9F%E3%82%89%E5%BD%93%E3%81%9F%E3%82%8A%E3%81%A8%E3%81%97%E3%81%BE%E3%81%99%E3%80%82

Console Log
shigurechan@shigurechan-System-Product-Name:~/Program/SDLGame/libTest$ sh run.sh g++ -c -MMD -MP src/Player.cpp -o obj/Player.o g++ -c -MMD -MP ../lib/src/Collision.cpp -o ../lib/obj/Collision.o ar rcs ../lib/libSDLGame.a ../lib/obj/Circle_Collision.o ../lib/obj/Circle_Render.o ../lib/obj/Collision.o ../lib/obj/Component.o ../lib/obj/GameObject.o ../lib/obj/Line_Collision.o ../lib/obj/Line_Render.o ../lib/obj/Rectangle_Collision.o ../lib/obj/Rectangle_Render.o ../lib/obj/SDLGame.o ../lib/obj/Sprite_Render.o ../lib/obj/Transform.o ../lib/obj/Circle_Collision.o ../lib/obj/Circle_Render.o ../lib/obj/Collision.o ../lib/obj/Component.o ../lib/obj/GameObject.o ../lib/obj/Line_Collision.o ../lib/obj/Line_Render.o ../lib/obj/Rectangle_Collision.o ../lib/obj/Rectangle_Render.o ../lib/obj/SDLGame.o ../lib/obj/Sprite_Render.o ../lib/obj/Transform.o g++ obj/Enemy.o obj/Game.o obj/Main.o obj/Player.o -o program ../lib/libSDLGame.a -lSDL2main -lSDL2 -lSDL2_image (dot01 * dot02) <= 0.0f (dot01 * dot02) <= 0.0f (dot01 * dot02) <= 0.0f (dot01 * dot02) <= 0.0f (dot01 * dot02) <= 0.0f (dot01 * dot02) <= 0.0f (dot01 * dot02) <= 0.0f (dot01 * dot02) <= 0.0f (dot01 * dot02) <= 0.0f (dot01 * dot02) <=
Collison

cpp

bool SDL::LineAndCircle_Collision_Hit(const glm::vec2 start,const glm::vec2 end,const glm::vec2 center,const float range) { glm::vec2 start_center = center - start; glm::vec2 end_center = center - end; glm::vec2 end_start = end - start; glm::vec2 norm = glm::normalize(end_start); float r = end_start.x * norm.y - end_start.y * norm.x; if(r < range) { float dot01 = start_center.x * end_start.x + start_center.y * end_start.y; float dot02 = end_center.x * end_start.x + end_center.y * end_start.y; // 二つの内積の掛け算結果が0以下なら当たり if ( (dot01 * dot02) <= 0.0f ) { std::cout<<"(dot01 * dot02) <= 0.0f"<<std::endl; return true; } if( (end_center.length() < range) || (start_center.length() < range) ) { std::cout<<"(end_center.length() < range) || (start_center.length() < range)"<<std::endl; return true; } } return false; }
Player.cpp

cpp

#include "Player.hpp" #include "../../lib/src/SDLGame.hpp" //#include "../../lib/src/BoxCollision.hpp" #include <iostream> #include <memory> /*################################################# # 初期化 ###################################################*/ Player::Player() : GameObject() { transform.position = glm::vec2((SDL::GetWindowSize().x / 2) - 50 - 200,(SDL::GetWindowSize().y / 2) - 50); lineCollision = std::make_shared<SDL::Line_Collision>(); lineCollision->startPosition = transform.position; lineCollision->endPosition = transform.position + glm::vec2(100,100); lineRender = std::make_shared<SDL::Line_Render>(); lineRender->startPosition = transform.position; lineRender->endPosition = transform.position + glm::vec2(100,100); lineRender->color = glm::vec4(255,255,255,255); } /*################################################# # 更新 ###################################################*/ void Player::Update() { Input(); lineRender->startPosition = transform.position; lineRender->endPosition = transform.position + glm::vec2(100,100); lineCollision->startPosition = transform.position; lineCollision->endPosition = transform.position + glm::vec2(100,100); } void Player::Collision(const std::shared_ptr<SDL::GameObject> obj) { if(lineCollision->getHitEnter(obj->circleCollision) == true) { std::cout<<"Enter"<<std::endl; } /* if(lineCollision->getHitStay(obj->circleCollision) == true) { std::cout<<"Stay"<<std::endl; } if(lineCollision->getHitExit(obj->circleCollision) == true) { std::cout<<"Exit"<<std::endl; } */ } /*################################################# # 描画 ###################################################*/ void Player::Render() const { lineRender->Render(); }
Enemy

cpp

#include "Enemy.hpp" #include "../../lib/src/SDLGame.hpp" /*################################################# # 初期化 ###################################################*/ Enemy::Enemy() : SDL::GameObject() { transform.position = glm::vec2((SDL::GetWindowSize().x / 2) - 50,(SDL::GetWindowSize().y / 2) - 50); circleCollision = std::make_shared<SDL::Circle_Collision>(); circleCollision->position = transform.position; circleCollision->range = 60.0f; circleRender = std::make_shared<SDL::Circle_Render>(); circleRender->transform.position = transform.position; circleRender->range = 60.0f; circleRender->color = glm::vec4(0,255,0,255); } /*################################################# # 更新 ###################################################*/ void Enemy::Update() { // circleCollision->position = transform.position; } /*################################################# # 描画 ###################################################*/ void Enemy::Render()const { circleRender->Render(); } /*################################################# # 終了処理 ###################################################*/ Enemy::~Enemy() { }
Game.cpp

cpp

/*################################################# # 更新 ###################################################*/ void Game::Update() { for(std::vector<std::shared_ptr<SDL::GameObject>>::const_iterator itr = gameObject.begin(); itr != gameObject.end(); itr++) { (*itr)->Update(); } for(std::vector<std::shared_ptr<SDL::GameObject>>::const_iterator itr = gameObject.begin(); itr != gameObject.end(); itr++) { for(std::vector<std::shared_ptr<SDL::GameObject>>::const_iterator it = gameObject.begin(); it != gameObject.end(); it++) { if(it != itr) { (*itr)->Collision(*it); } } } }

以下のような質問にはリアクションをつけましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

リアクションが多い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

2022/08/22 16:52

こちらの質問が他のユーザーから「やってほしいことだけを記載した丸投げの質問」という指摘を受けました。

fana

2022/08/23 00:59

リンク先は「本当にたかだか円と線分の判定の話なのか?」っていうくらいに異様に長すぎて私はその内容を読む気もしないが… > if()文に内部なのか外に追記するのかわかりません …っていうなら,あなたは「そもそもそこの話の演算の内容を理解できていない」ってことでしょ? そんな状態で実装に着手していること自体が間違っている.(偶然うまくいくことに賭けているの?) そのリンク先の長文の内容があなたに合わないのであれば,別の方法の話を探すなり,自前で導出するなりした方が早いのではあるまいか.
fana

2022/08/23 01:11

リンク先をちょっと見ただけでやたら話がごちゃごちゃしているけど, 円 vs 線分 であれば ・線分上の点のうち,円の中心に最も近い点Pを求む ・円の中心から点Pまでの距離 と 円の半径 とを比較 っていうだけの話で済むんじゃないかなぁ. (こういうのは座標群を最初に「一方の軸が線分と平行である座標系」の値に座標変換してから判定作業をするようなイメージで考ればわかりやすいんじゃないかな)
SaitoAtsushi

2022/08/23 01:27

問題なのは SDL::LineAndCircle_Collision_Hit の挙動ですが、それ以外の部分は SDL::LineAndCircle_Collision_Hit を呼出してすらいないのでどのように関係するのかわかりません。 質問者にとっては関係しそうな部分を抽出したのかもしれませんが、質問を読む人はプログラムの全体像の知識を全く持っていないということを前提として繋がりが分かるように提示してください。 あるいは単に座標の計算の話ですからどのような座標が与えられたときに SDL::LineAndCircle_Collision_Hit が期待と違う挙動をするのか具体例の数値をいくつか提示するという形でもよいと思います。
fana

2022/08/23 01:50

> glm::vec2 norm = glm::normalize(end_start); > float r = end_start.x * norm.y - end_start.y * norm.x; これは一体どのような意図の演算なのであろうか? r は理屈上常に 0 になると見えるが.
SaitoAtsushi

2022/08/23 04:58

各段階の計算結果を見ていけば意図通りの値になっていない箇所はすぐに発見できると思うんですが、個々の値の意味が十分に理解できていないので正しいかどうかわからないということでしょうね。

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
86.12%

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

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

質問する

関連した質問

同じタグがついた質問を見る

C++

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