HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2008
1127
紅玉楕円の当たり判定19解決


紅玉

リンク

2008/11/27(Thu) 01:14:18|NO.21061

当たり判定を自作したいのですが、
楕円&真円、楕円&矩形の判定で躓いてます。

うまい方法は無いでしょうか?



この記事に返信する


tsuka

リンク

2008/11/27(Thu) 13:29:35|NO.21066

色で判定とか・・・

randomize repeat 5 //図形作成 circle rnd(ginfo_sizex),rnd(ginfo_sizey),rnd(ginfo_sizex),rnd(ginfo_sizey) boxf rnd(ginfo_sizex),rnd(ginfo_sizey),rnd(ginfo_sizex),rnd(ginfo_sizey) loop repeat a=0 pget mousex,mousey ;色取得 if ginfo_r=0 & ginfo_g=0 & ginfo_b=0 :a=1 ;黒なら1 title ""+a wait 1 loop



raisen

リンク

2008/11/27(Thu) 17:53:57|NO.21070




紅玉

リンク

2008/11/27(Thu) 19:28:59|NO.21075

tsukaさん>
楕円の判定をしたい画像にグラデーションとかで沢山色使ってまして…
純粋に計算で求められないかと思ったのですが

raisenさん>
1通り見させて頂きました。
…が、真円の方法しか書いてないっぽいですね…
わざわざ探してもらって申し訳無いですが



a

リンク

2008/11/27(Thu) 20:06:44|NO.21078

マジでやるなら↓の式を参考に
http://marupeke296.com/COL_2D_No7_EllipseVsEllipse.html



紅玉

リンク

2008/11/27(Thu) 20:59:20|NO.21080

aさん>
見させて頂きました。
こんなにきっついとは…

何とかこれで頑張ってみます。
ありがとうございました。



check

リンク

2008/11/27(Thu) 21:01:24|NO.21081

>紅玉s
円を描画していないバッファでやればいいのでは。

1.描画するスクリーンと同じ大きさのバッファを用意する。
2.あたり判定を行いたいものを描画するときにそれと同じ形の図形を、
最初に用意したバッファに描画する。
3.バッファをアクティブにしてあたり判定を行う。



いかろ

リンク

2008/11/27(Thu) 22:18:52|NO.21085

解決されたようですが一応。
「2定点(焦点)からの距離の和が一定」なので
(焦点Fからの距離)+(焦点F’からの距離)<(一定値)
の状態を当りとすれば楽なような気がします。
 ふと思いついただけなので正しさは保障できませんが。



紅玉

リンク

2008/11/28(Fri) 01:14:54|NO.21092

checkさん>
ああ、成る程、そんな手もありますね。
どうしても計算で無理だったら、その方法も考えてみます。

いかろさん>
ちょっと考えてみました。
…何だかいけそうな気がしてきました。
閃いた気がします。ヒントありがとうございました。



ANTARES

リンク

2008/11/28(Fri) 01:24:39|NO.21093

円と楕円のあたり判定
円の半径をrとする。
楕円周上の一点の各焦点からの距離の和をqとする。
楕円の一方の焦点Aと円の中心を結んだ線分をLとして、その長さをxとする。
円の中心からrの距離にある線分L上の点と楕円のもう一方の焦点Bとの距離を
yとする。
x-r+y<qならあたっていると言えそうな気がします。



GENKI

リンク

2008/11/28(Fri) 01:53:44|NO.21094

こんなの作ってみました。

dim tpos, 3 dim mpos, 3 tpos = ginfo_winx/2, ginfo_winy/2 c = 200.0 d = 100.0 ddim dpos, 3 *main redraw 1 : await 16 : redraw 0 : color 255, 255, 255 : boxf : color : pos 0,0 mpos = mousex, mousey ;相対座標 dpos(0) = double(tpos(0) - mpos(0)) dpos(1) = double(tpos(1) - mpos(1)) ms = sqrt(dpos(0)*dpos(0) + dpos(1)*dpos(1)) mes "楕円中心からマウスまでの距離 = " + ms cost = dpos(0)/c / sqrt( dpos(0)*dpos(0)/(c*c) + dpos(1)*dpos(1)/(d*d) ) sint = dpos(1)/d / sqrt( dpos(0)*dpos(0)/(c*c) + dpos(1)*dpos(1)/(d*d) ) tr = sqrt( cost*c*cost*c + sint*d*sint*d ) ;距離 mes "赤い線の長さ = "+tr if ms<=tr : mes "内側" : else : mes "外側" circle tpos(0)-c, tpos(1)-d, tpos(0)+c, tpos(1)+d, 0 line -cost*c+tpos(0), -sint*d+tpos(1), mpos(0), mpos(1) color 255 line tpos(0), tpos(1), -cost*c+tpos(0), -sint*d+tpos(1) goto *main
いったん半径1の円に変換して、もう一度楕円に戻しています。

衝突判定は同じように、片一方を半径1の円にして円と楕円の判定という形に変換。
円の直径が1と小さいので無視してもそう問題ないかも知れませんね。
あるいはNO.21078のページとあわせればなんとかなりそうな気がします。


む。楕円を円に変換するならANTARESさん(21093)のやり方でやったほうがいいのか。orz



natu

リンク

2008/11/28(Fri) 17:38:09|NO.21104

楕円の2焦点O1, O2から任意の点P1, P2との距離の和は,楕円の軌跡上では一定ですが,その他は線形変化しないので
x+y<q+Rという関係は成り立たないかと思います.よく考えてないので成り立つのかもしれませんが.



SYAM

リンク

2008/11/28(Fri) 19:39:22|NO.21108

>x+y<q+Rという関係

それが成り立つかどうか、試しに画面全部の点について調べて色で塗り分けてみれば、わかりますね。



SYAM

リンク

2008/11/28(Fri) 20:10:51|NO.21109

仕事あがったので、塗り分けました。


#define X1 150 #define Y1 150 #define X2 250 #define Y2 250 #define W 200 screen 0,480,480 : cls 4 color 255,255,255 repeat ginfo_winx : x=cnt repeat ginfo_winy : y=cnt gosub *IS_AREA if(ret==1) : pset x,y await 0 loop:loop color 0,0,0 pset X1,Y1 pset X2,Y2 stop *IS_AREA dx1=(X1-x)*(X1-x) dy1=(Y1-y)*(Y1-y) dx2=(X2-x)*(X2-x) dy2=(Y2-y)*(Y2-y) ret=0 if ((sqrt(dx1+dy1)+sqrt(dx2+dy2))<w) : ret=1 return ret



natu

リンク

2008/11/28(Fri) 20:41:43|NO.21112

簡易で作ってみましたが、判定できないようです.
それから気づいたのですが NO.21105 のスクリは楕円では使い物になりませんね OrZ(^^;
後で消しておきます.

#define R 20 ;#define R 0 cx = ginfo_winx / 2 : cy = ginfo_winy / 2 a = 200.0 : b = 50.0 : d = sqrt(a*a - b*b) cl = cx - d : cr = cx + d ; 焦点 q = 2.0 * a repeat y = cy - mousey x = cl - mousex : d1 = sqrt(x*x + y*y) x = cr - mousex : d2 = sqrt(x*x + y*y) if(d1+d2 <= q + R) { title "内側" } else { title "" } redraw 0 color 255, 255, 255 : boxf color : circle cx-a, cy-b, cx+a, cy+b circle mousex-R, mousey-R, mousex+R, mousey+R redraw 1 await 10 loop



ANTARES

リンク

2008/11/29(Sat) 02:18:53|NO.21120

>x = cr - mousex : d2 = sqrt(x*x + y*y)
y2=y*(d1-R)/d1
x2=cr-mousex-(x*R/d1)
d2=sqrt(x2*x2+y2*y2)

 でも、ダメでした。残念。
プログラムを実行してわかりましたが、典型的な例として円の中心のX座標と
楕円の中心のX座標が一致し、線分Lと円の交点が楕円周上にあるときを
考えれば、x+y=r+qであるにも関わらず、明らかに円は楕円と重なっています。
正しいのは、円の中心のY座標と楕円の中心のY座標が一致する場合のみでした。



GENKI

リンク

2008/11/30(Sun) 03:13:56|NO.21144

> NO.21094

2つの楕円の中心を直線で結んで判定しようなどと考えると失敗します。しました。orz
あれはその産物です。


あの後、この↓ページの解説どおりやってみようかと思ってやってみたのですが…断念しました。
http://marupeke296.com/COL_2D_No7_EllipseVsEllipse.html

断念したものの、少し違う方法でがんばってみたところ「なんとなく判定」できるものが出来ました。
↓これでいかがでしょうか。
http://hspdev-wiki.net/?%BE%D7%C6%CD%C8%BD%C4%EA#g01e4264
私の脳みそではこれが限界でした。orz



金魚ちゃん

リンク

2008/12/3(Wed) 12:04:34|NO.21211

リージョンを使うのはどうですか?
メモリは増加するが、これならどんな図形でも
正確に重なりをチェックできます。
(でも図形が毎回変わる場合は不向きだね)

// 楕円,真円の作成
CreateEllipticRgn
http://msdn.microsoft.com/ja-jp/library/cc428336.aspx

// 矩形の作成
CreateRectRgn
http://msdn.microsoft.com/ja-jp/library/cc428352.aspx

// 当たり判定に使う関数
CombineRgn
http://msdn.microsoft.com/ja-jp/library/cc428338.aspx

// 参考
http://eternalwindows.jp/graphics/bitmap/bitmap12.html
http://hspdev-wiki.net/?%C9%D4%C4%EA%B7%C1%A5%EA%A1%BC%A5%B8%A5%E7%A5%F3



あまま

リンク

2008/12/5(Fri) 19:07:43|NO.21280

ここ↓の通りにやってみました
http://marupeke296.com/COL_2D_No7_EllipseVsEllipse.html

ほぼそのままですが・・・


//============================================================== //========= 楕円情報等 //===== #define pai 3.14159265358979 ; π // 楕円情報 中央 #define RX01 100.0 ; X軸半径 #define RY01 50.0 ; Y軸半径 #define ANG01 0.0 ; 回転角度 (360°) posx = ginfo(12) / 2 ; 中心座標X posy = ginfo(13) / 2 ; 中心座標Y ANG01_R = ANG01 * pai / 180.0 ; 回転角度をラジアンに変換 // 楕円情報 マウス側 (中心座標はマウスの位置になるため省略) #define RX02 100.0 ; X軸半径 #define RY02 50.0 ; Y軸半径 #define ANG02 90.0 ; 回転角度 (360°) ANG02_R = ANG02 * pai / 180.0 ; 回転角度をラジアンに変換 goto *Win_Setup //============================================================== //============================================================== //============================================================== //========= 接触判定 //===== #deffunc CollisionEllipse // STEP1 : E2を単位円にする変換をE1に施す DefAng = ANG01_R - ANG02_R Cos01 = cos(DefAng) Sin01 = sin(DefAng) nx = RX02 * Cos01 ny = -RX02 * Sin01 px = RY02 * Sin01 py = RY02 * Cos01 ox = cos(ANG01_R)*(mousex - posx) + sin(ANG01_R)*(mousey - posy) oy = -sin(ANG01_R)*(mousex - posx) + cos(ANG01_R)*(mousey - posy) // STEP2 : 一般式A〜Gの算出 rx_pow2 = 1.0 / (RX01 * RX01) ry_pow2 = 1.0 / (RY01 * RY01) A = rx_pow2*nx*nx + ry_pow2*ny*ny B = rx_pow2*px*px + ry_pow2*py*py D = 2.0 * (rx_pow2*nx*px + ry_pow2*ny*py) E = 2.0 * (rx_pow2*nx*ox + ry_pow2*ny*oy) F = 2.0 * (rx_pow2*px*ox + ry_pow2*py*oy) G = ox*ox*rx_pow2 + oy*oy*ry_pow2 - 1.0 // STEP3 : 平行移動量(h,k)及び回転角度θの算出 tmp1 = D*D - 4.0*A*B h = (F*D - 2.0*E*B) / tmp1 k = (E*D - 2.0*A*F) / tmp1 if (B - A) == 0 { Th = 0 } else { Th = atan(D, B - A) / 2.0 } // STEP4 : +1楕円を元に戻した式で当たり判定 CosTh = cos(Th) SinTh = sin(Th) A_tt = CosTh*CosTh*A + SinTh*SinTh*B - SinTh*CosTh*D B_tt = SinTh*SinTh*A + CosTh*CosTh*B + SinTh*CosTh*D KK = A*h*h + B*k*k + D*h*k - E*h - F*k + G if KK > 0.0 { ; // 念のため KK = 0.0 } Rx_tt = 1.0 + sqrt(-KK / A_tt) Ry_tt = 1.0 + sqrt(-KK / B_tt) x_tt = CosTh*h - SinTh*k y_tt = SinTh*h + CosTh*k JudgeValue = (x_tt * x_tt) / (Rx_tt * Rx_tt) + (y_tt * y_tt) / (Ry_tt * Ry_tt) if JudgeValue <= 1.0 { flag = 1 } else { flag = 0 } return //===== //========= //============================================================== //============================================================== //============================================================== *Win_Setup screen 0, 640, 480, 0 // バッファに楕円を描画(回転させて表示するときのため) // 中央 buffer 2, RX01 * 2, RY01 * 2, 0 color 0, 0, 0 boxf color 0, 0, 255 circle 0, 0, RX01 * 2 - 1, RY01 * 2 - 1 // マウス buffer 3, RX02 * 2, RY02 * 2, 0 color 0, 0, 0 boxf color 0, 255, 0 circle 0, 0, RX02 * 2 - 1, RY02 * 2 - 1 gsel 0 //============================================================== //========= 描画処理(メインループ) //===== *main redraw 0 await 16 color 255, 255, 255 boxf CollisionEllipse gsel 2 if flag { ; 接触していたら赤く表示 color 255, 0, 0 } else { color 0, 0, 255 } circle 0, 0, RX01*2 - 1, RY01*2 - 1 gsel 0 // 楕円 中央 gmode 2, RX01 * 2, RY01 * 2 pos posx, posy grotate 2, 0, 0, ANG01_R // 楕円 マウス gmode 2, RX02 * 2, RY02 * 2 pos mousex, mousey grotate 3, 0, 0, ANG02_R color 0, 0, 0 pos 0, 0 if flag { mes "接触中" } redraw 1 goto *main



a

リンク

2008/12/5(Fri) 20:45:27|NO.21281

↑すげー



ONION software Copyright 1997-2023(c) All rights reserved.