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

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

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

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

Q&A

解決済

2回答

1220閲覧

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

退会済みユーザー

退会済みユーザー

総合スコア0

C++

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

0グッド

1クリップ

投稿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

1 2 3bool SDL::LineAndCircle_Collision_Hit(const glm::vec2 start,const glm::vec2 end,const glm::vec2 center,const float range) 4{ 5 glm::vec2 start_center = center - start; 6 glm::vec2 end_center = center - end; 7 glm::vec2 end_start = end - start; 8 9 glm::vec2 norm = glm::normalize(end_start); 10 11 float r = end_start.x * norm.y - end_start.y * norm.x; 12 13 14 if(r < range) 15 { 16 float dot01 = start_center.x * end_start.x + start_center.y * end_start.y; 17 float dot02 = end_center.x * end_start.x + end_center.y * end_start.y; 18 19 // 二つの内積の掛け算結果が0以下なら当たり 20 if ( (dot01 * dot02) <= 0.0f ) 21 { 22 std::cout<<"(dot01 * dot02) <= 0.0f"<<std::endl; 23 return true; 24 25 } 26 27 if( (end_center.length() < range) || (start_center.length() < range) ) 28 { 29 std::cout<<"(end_center.length() < range) || (start_center.length() < range)"<<std::endl; 30 31 return true; 32 } 33 34 } 35 36 return false; 37 38} 39
Player.cpp

cpp

1#include "Player.hpp" 2 3#include "../../lib/src/SDLGame.hpp" 4//#include "../../lib/src/BoxCollision.hpp" 5 6#include <iostream> 7#include <memory> 8 9/*################################################# 10# 初期化 11###################################################*/ 12Player::Player() : GameObject() 13{ 14 transform.position = glm::vec2((SDL::GetWindowSize().x / 2) - 50 - 200,(SDL::GetWindowSize().y / 2) - 50); 15 16 lineCollision = std::make_shared<SDL::Line_Collision>(); 17 lineCollision->startPosition = transform.position; 18 lineCollision->endPosition = transform.position + glm::vec2(100,100); 19 20 lineRender = std::make_shared<SDL::Line_Render>(); 21 lineRender->startPosition = transform.position; 22 lineRender->endPosition = transform.position + glm::vec2(100,100); 23 24 lineRender->color = glm::vec4(255,255,255,255); 25 26 27} 28 29/*################################################# 30# 更新 31###################################################*/ 32void Player::Update() 33{ 34 Input(); 35 36 lineRender->startPosition = transform.position; 37 lineRender->endPosition = transform.position + glm::vec2(100,100); 38 39 40 lineCollision->startPosition = transform.position; 41 lineCollision->endPosition = transform.position + glm::vec2(100,100); 42 43} 44 45void Player::Collision(const std::shared_ptr<SDL::GameObject> obj) 46{ 47 48 49 if(lineCollision->getHitEnter(obj->circleCollision) == true) 50 { 51 std::cout<<"Enter"<<std::endl; 52 } 53 54 55/* 56 if(lineCollision->getHitStay(obj->circleCollision) == true) 57 { 58 std::cout<<"Stay"<<std::endl; 59 } 60 61 62 if(lineCollision->getHitExit(obj->circleCollision) == true) 63 { 64 std::cout<<"Exit"<<std::endl; 65 } 66*/ 67 68} 69 70/*################################################# 71# 描画 72###################################################*/ 73 74void Player::Render() const 75{ 76 lineRender->Render(); 77 78} 79
Enemy

cpp

1#include "Enemy.hpp" 2#include "../../lib/src/SDLGame.hpp" 3 4 5/*################################################# 6# 初期化 7###################################################*/ 8Enemy::Enemy() : SDL::GameObject() 9{ 10 transform.position = glm::vec2((SDL::GetWindowSize().x / 2) - 50,(SDL::GetWindowSize().y / 2) - 50); 11 12 circleCollision = std::make_shared<SDL::Circle_Collision>(); 13 circleCollision->position = transform.position; 14 circleCollision->range = 60.0f; 15 16 17 circleRender = std::make_shared<SDL::Circle_Render>(); 18 circleRender->transform.position = transform.position; 19 circleRender->range = 60.0f; 20 circleRender->color = glm::vec4(0,255,0,255); 21 22} 23 24/*################################################# 25# 更新 26###################################################*/ 27void Enemy::Update() 28{ 29 30// circleCollision->position = transform.position; 31 32 33} 34 35/*################################################# 36# 描画 37###################################################*/ 38void Enemy::Render()const 39{ 40 circleRender->Render(); 41} 42 43/*################################################# 44# 終了処理 45###################################################*/ 46Enemy::~Enemy() 47{ 48 49} 50
Game.cpp

cpp

1/*################################################# 2# 更新 3###################################################*/ 4void Game::Update() 5{ 6 for(std::vector<std::shared_ptr<SDL::GameObject>>::const_iterator itr = gameObject.begin(); itr != gameObject.end(); itr++) 7 { 8 (*itr)->Update(); 9 } 10 11 for(std::vector<std::shared_ptr<SDL::GameObject>>::const_iterator itr = gameObject.begin(); itr != gameObject.end(); itr++) 12 { 13 for(std::vector<std::shared_ptr<SDL::GameObject>>::const_iterator it = gameObject.begin(); it != gameObject.end(); it++) 14 { 15 if(it != itr) 16 { 17 (*itr)->Collision(*it); 18 } 19 } 20 } 21} 22

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

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

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

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

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

回答2

0

ベストアンサー

提示コードの//コメント部のコードですがその2つが間違えていました。上の行は単純なコードの写し間違えでして
2つ目は絶対値にする必要がありました。なぜなら値がマイナスになるからです。

cpp

1 2bool SDL::LineAndCircle_Collision_Hit(const glm::vec2 start,const glm::vec2 end,const glm::vec2 center,const float range) 3{ 4 glm::vec2 start_center = center - start; 5 glm::vec2 end_center = center - end; 6 glm::vec2 end_start = end - start; 7 8 glm::vec2 norm = glm::normalize(end_start); 9 10 float r = end_start.x * norm.y - end_start.y * norm.x; 11 //float r = start_center.x * norm.y - start_center.y * norm.x; 12 13// std::cout<<fabs(r)<<std::endl; 14 15// if(r <= range) 16 if(fabs(r) <= range) 17 { 18 float dot01 = start_center.x * end_start.x + start_center.y * end_start.y; 19 float dot02 = end_center.x * end_start.x + end_center.y * end_start.y; 20 21 if ( (dot01 * dot02) <= 0.0f ) 22 { 23 if( (end_center.length() < range) || (start_center.length() < range) ) 24 { 25 return true; 26 } 27 } 28 } 29 30 return false; 31} 32

投稿2022/08/23 06:53

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

1.円の中心から線分に垂線を降ろす
2.垂線の長さ <= 円の半径?
3.2が成立した場合、線分と垂線の交点が線分の両端座標の範囲に入っているか?
垂線の降ろし方は算数の教科書を見てください

投稿2022/08/23 03:13

mike

総合スコア118

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

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

fana

2022/08/23 04:06 編集

質問内容を要約すれば「俺のコードのバグを見つけてくれ」という話になるでしょうから,これだと回答にならないのでは. …と言う意味での低評価を投じましたことを明記しておきます. (方法論の要約だとしても 3. が偽の場合の話が欠けているし)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.54%

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

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

質問する

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

C++

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