ページ 1 / 1
c++ 玉の反射について
Posted: 2020年7月19日(日) 23:06
by calbee
現在タイマーを使って、斜め方向に進む2つの玉が、四方の壁に当たると反射するというものができています。2つの玉が衝突したときに跳ね返って、進行方向が変わるようにしたいのですが、やり方が分からないです…どのように書けば良いのでしょうか…?
Re: c++ 玉の反射について
Posted: 2020年7月20日(月) 10:08
by usao
最も手っ取り早い(しかし,しょぼい,ごまかし的な)方法の1つとして,2つの弾の速度を入れ替えるというものがある.
衝突してきた相手の移動方向や速さに応じたそれっぽい挙動を示したいなら,
おそらく物理的な話を持ち込む必要がある.
Re: c++ 玉の反射について
Posted: 2020年7月20日(月) 15:23
by calbee
コード:
if(x==x1 && y==y1) {
a=dx;
dx=dx1;
dx1=a;
b=dy;
dy=dy1;
dy1=b;
}
x,y x1,y1というのが2つの玉の座標で、dx,dy dx1,dy1が速度です。
これで衝突時(同座標)に速度を入れ替えたつもりなんですが、上手くいかないです…
やり方が違うのでしょうか…?
Re: c++ 玉の反射について
Posted: 2020年7月20日(月) 16:09
by usao
「やったつもりだけど上手くいかない」と言われましても,何が何だかわからんです.
【「やり方」が合っているか否か】というのは,あなたが実装しているプログラムに依存する話です.
例えば,「玉」と言われたら,私は「ある程度大きさを有する(丸い)物」を想像しますが,
そのコードを見た感じ,サイズという概念の無い「質点」のような扱いが成されているように見えます.
そのことが,あなたのプログラムの仕様の上で正しいのか正しくないのかは,私にはわかりません.
また,外野からすれば,自由に運動する何かの衝突判定として,
> x==x1 && y==y1
なる(「座標の完全一致」という)条件を満たすことは,非常にレアなケースであるようにも思えますが,
あなたのプログラムでは事情が異なるのかもしれません.わかりません.
---
で,
とりあえず,そのifの中に実際に処理が来ているのかどうかを調べるところから初めることを勧めます.
「衝突しているハズ」なのにifの中に処理が来ないならば,このifを書くべき場所を間違っているとか,あるいは前記したように「衝突」の判定基準が厳しすぎるのか,とにかく処理が来ない理由を把握して対処してください.
ifの中に処理は来ているのに挙動がおかしいとかいう場合には,dx等の値の遷移を追ってください.
・このifとは別の場所が,このifの処理を台無しにするような値の変更を行っていないか?
・このifの処理が「2回連続で」走ってしまい,結果として「入れ替えて,さらに入れ替えた」という残念なことになっていないか?
等.
Re: c++ 玉の反射について
Posted: 2020年7月20日(月) 16:16
by usao
それはそれとして,もうちょっと「まともな」挙動となる方法に関しては,例えば
「ビリヤード シミュレーション 計算方法」みたいな(いかにもそういう問題を取り扱っていそうな)語で検索してみると良いかもしれません.
Re: c++ 玉の反射について
Posted: 2020年7月20日(月) 18:13
by calbee
色々教えて頂きありがとうございます。
本来なら物理計算をすべきですが、調べても良く分かりませんでした…
コード:
if(x-x1<=1 || x1-x<=1 && y-y1<=1 || y-y1<=1) {
a=dx;
dx=dx1;
dx1=a;
b=dy;
dy=dy1;
dy1=b;
}
こんな感じで判定範囲を広げたところ、一応跳ね返っているように見えましたが、挙動がおかしいです…1という数字がまずいのでしょうか?
判定範囲が一定でないというか、x軸の範囲が凄く広かったり、教えて頂いたように処理が2回連続で走っているように見られる部分があります…
Re: c++ 玉の反射について
Posted: 2020年7月20日(月) 20:30
by usao
> x-x1<=1 || x1-x<=1 && y-y1<=1 || y-y1<=1
ご自身で書かれた条件を,ご自身で説明できますか?
例えば,
> x-x1<=1
これは,(x <= x1+1)であるときに満たされます.
ざっくり言えば,x1が100のとき,xが101以下であれば常に満たされ(てしまい)ます.
(例えば,一方の座標が100で他方が0のときに「衝突している」とは判定したくないと思いますが,そうであれば,これだといかんのでは?)
---
suggestion:
・「A || B && C」と書いた時,それは「A || (B&&C)」なのか「(A||B) && C」なのか?
把握していますか?
慣れないうちは,自分が意図した側になるように明示的に括弧で囲みましょう.
・ 理屈を「日本語で」考えて,そこでまずは「理屈としてまともかどうか」を確認しましょう.
・理屈ができたら,それを素直にコード化しましょう.
例えば,「xとx1との差が1以内」という条件を考えたならば,素直なコードは「abs(x-x1) <= 1」のようになるでしょう.
・理屈を決める際にはググるのも一つの方法です.
「玉」が円形や球系なのであれば,それらの衝突判定方法はググれば見つかるかもしれません.
(円や球同士の判定みたいなのは,きっと誰かがドヤ顔で解説している.)
Re: c++ 玉の反射について
Posted: 2020年7月20日(月) 22:37
by calbee
本当だ…条件が足りないですね…
r=半径
((x-x1)^2 + (y-y1)^2 <= (r+r1)^2)
という判定法を見つけたのですが、判定範囲が広くなってしまい、何故かできないです…
教えて頂いた絶対値の方法は、stdlib.hは入れたのですが、接触判定ができていないようで、すり抜けてしまいます…
コード:
if(abs(x-x1) <= 1 && abs(y-y1) <= 1) {
a=dx;
dx=dx1;
dx1=a;
b=dy;
dy=dy1;
dy1=b;
}
で問題ないはずですよね…?
Re: c++ 玉の反射について
Posted: 2020年7月21日(火) 01:09
by みけCAT
calbee さんが書きました: ↑5年前
r=半径
((x-x1)^2 + (y-y1)^2 <= (r+r1)^2)
という判定法を見つけたのですが、判定範囲が広くなってしまい、何故かできないです…
そのコードは見せていただけないですか?
ちなみに、C++のプリミティブ型では「^」は累乗ではなくxorの演算子です。
これで問題ないかはわかりません。
・calbeeさんの考えている世界で「1」がどの程度の大きさなのかわからないので、
当たり判定の範囲が適切かわかりません。
・各識別子の宣言が書かれていないので、型が適切かわかりません。
Re: c++ 玉の反射について
Posted: 2020年7月21日(火) 09:59
by calbee
「^」は累乗ではないのですね…知らなかったです。
乗算に直したらできました。教えて頂きありがとうございます(__)
1の方は値が小さすぎたようです。数を増やしたら接触判定が見られました。
Re: c++ 玉の反射について
Posted: 2020年7月21日(火) 20:26
by usao