|
|
2008/11/27(Thu) 01:14:18|NO.21061
当たり判定を自作したいのですが、
楕円&真円、楕円&矩形の判定で躓いてます。
うまい方法は無いでしょうか?
|
|
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
|
|
2008/11/27(Thu) 17:53:57|NO.21070
|
|
2008/11/27(Thu) 19:28:59|NO.21075
tsukaさん>
楕円の判定をしたい画像にグラデーションとかで沢山色使ってまして…
純粋に計算で求められないかと思ったのですが
raisenさん>
1通り見させて頂きました。
…が、真円の方法しか書いてないっぽいですね…
わざわざ探してもらって申し訳無いですが
|
|
2008/11/27(Thu) 20:06:44|NO.21078
|
|
2008/11/27(Thu) 20:59:20|NO.21080
aさん>
見させて頂きました。
こんなにきっついとは…
何とかこれで頑張ってみます。
ありがとうございました。
|
|
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さん>
ああ、成る程、そんな手もありますね。
どうしても計算で無理だったら、その方法も考えてみます。
いかろさん>
ちょっと考えてみました。
…何だかいけそうな気がしてきました。
閃いた気がします。ヒントありがとうございました。
|
|
2008/11/28(Fri) 01:24:39|NO.21093
円と楕円のあたり判定
円の半径をrとする。
楕円周上の一点の各焦点からの距離の和をqとする。
楕円の一方の焦点Aと円の中心を結んだ線分をLとして、その長さをxとする。
円の中心からrの距離にある線分L上の点と楕円のもう一方の焦点Bとの距離を
yとする。
x-r+y<qならあたっていると言えそうな気がします。
|
|
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
|
|
2008/11/28(Fri) 17:38:09|NO.21104
楕円の2焦点O1, O2から任意の点P1, P2との距離の和は,楕円の軌跡上では一定ですが,その他は線形変化しないので
x+y<q+Rという関係は成り立たないかと思います.よく考えてないので成り立つのかもしれませんが.
|
|
2008/11/28(Fri) 19:39:22|NO.21108
>x+y<q+Rという関係
それが成り立つかどうか、試しに画面全部の点について調べて色で塗り分けてみれば、わかりますね。
|
|
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
|
|
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
|
|
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座標が一致する場合のみでした。
|
|
2008/12/3(Wed) 12:04:34|NO.21211
|
|
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
| |
|
2008/12/5(Fri) 20:45:27|NO.21281
↑すげー
|
|