コミュニティアイコン プチコン 非公式コミュニティ トピック

アバター
こういち ◆ou0jbJnEJ0Kb
2023/4/5 22:53
情報交換
続:衝突判定について
http://petitverse.hosiken.jp:80/community/petitcom/topic/?pg=20&read=1687
これの続きです。
前回はあらゆる形状の物体について書こうとした結果失踪してしまったので、今回は円、(へこみのない)四角形、三角形に絞って考えようと思います。その他の形状は要望があればお気持ちだけ解説する感じにします。
例のごとくマルペケつくろーさん( http://marupeke296.com/COL_main.html )を参考にしていきます。


それはそうと、久しぶりにSPCOLの存在を思い出しました。これは単に便利だから存在するのか、それとも衝突判定に必要なのか…

コメント

アバター
こういち 2023/4/5 22:57 ◆ou0jbJnEJ0Kb
最初のコメントだけコピペします。なお、時間については考慮せず、その瞬間の状況から最もそれらしいものを返すものとします。

サブルーチンの仕様
出力
当たり判定であるため、衝突したかどうかの情報は必須である。0の場合衝突しておらず、それ以外は衝突したものとする。
また、それ以外にも「どこから衝突したか」「衝突したか場所はどこか」の情報が必要な場合もある。その情報は法線ベクトル,座標として出力することにする。
変数名は
HIT,NormalR,NormalJ,CX,CYとする。NormalR,NormalJはNR,NJと略すかもしれない。
なお、衝突していない場合の法線と衝突座標の値は何でもいいものとする。

入力
入力として、重心の座標と、半径や頂点の位置ベクトルなどその図形を表現する情報を渡すことにする。頂点情報は時計回りに渡されるものとする。

サブルーチン名
SmileBASIC標準の当たり判定サブルーチンに倣い
(図形1)HIT(図形2)
のような命名とする
なお、先の法線ベクトルは図形1を基準としたものとする。
アバター
こういち 2023/4/10 21:34 ◆ou0jbJnEJ0Kb
三角形同士の判定
基本的にマルペケつくろーの通りです。( http://marupeke296.com/COL_2D_TriTri.html )
ただし、2の一次判定は既にSPHITSPや四分木によって行われている前提なので省略します。
また、3の投影はわざわざ垂直なベクトルを求めずとも行列式(二次元外積)で求まります。(ただし、2D空間限定)

衝突した点ですが、「ある辺から見て内側にあって、最も辺との距離が近い相手の頂点」を衝突した点と見なすとそれらしくなります。
また、相手の重心が外側にある辺を優先的に衝突された辺と見なすことでよりそれらしくなると思います。

def trihittri cx1,cy1,x10,y10,x11,y11,x12,y12,cx2,cy2,x20,y20,x21,y21,x22,y22 out hit,nr,nj,cx,cy
x10=x10+cx1:x11=x11+cx1:x12=x12+cx1
y10=y10+cy1:y11=y11+cy1:y12=y12+cy1
x20=x20+cx2:x21=x21+cx2:x22=x22+cx2
y20=y20+cy2:y21=y21+cy2:y22=y22+cy2

var mmin#=1e6,mcx#,mcy#,mr#,mj# '重心が外側にある中で辺に最も近い頂点とその辺
var minx#,maxx#
var cmin#=1e6
var cross#,crsc#
var tr#,tj#
' 辺10,11
tr#=x11-x10:tj#=y11-y10
minx#=1e5:maxx#=0
'頂点20
cross#=tr#*(y20-y10)-tj#*(x20-x10)
crsc#=tr#*(cy2-y10)-tj#*(cx2-x10)
if cross#>maxx# then maxx#=cross#
if cross#<minx# then minx#=cross#
if cross#>=0&& cross#<cmin# then
cx=x20:cy=y20
nr=tj#:nj=-tr#
cmin#=cross#
endif
if crsc#<0&&cross#>0&&cross#<mmin# then
mcx#=x20:mcy#=y20
mr#=tj#:mj#=-tr#
mmin#=cross#
endif
'頂点21
cross#=tr#*(y21-y10)-tj#*(x21-x10)
if cross#>maxx# then maxx#=cross#
if cross#<minx# then minx#=cross#
if cross#>=0&& cross#<cmin# then
cx=x21:cy=y21
nr=tj#:nj=-tr#
cmin#=cross#
endif
if crsc#<0&&cross#>0&&cross#<mmin# then
mcx#=x21:mcy#=y21
mr#=tj#:mj#=-tr#
mmin#=cross#
endif
'頂点22
cross#=tr#*(y22-y10)-tj#*(x22-x10)
if cross#>maxx# then maxx#=cross#
if cross#<minx# then minx#=cross#
アバター
こういち 2023/4/10 21:37 ◆ou0jbJnEJ0Kb
if cross#>=0&& cross#<cmin# then
cx=x22:cy=y22
nr=tj#:nj=-tr#
cmin#=cross#
endif
if crsc#<0&&cross#>0&&cross#<mmin# then
mcx#=x22:mcy#=y22
mr#=tj#:mj#=-tr#
mmin#=cross#
endif
if maxx#*(tr#*(y12-y10)-tj#*(x12-x10)-minx#)<0 then hit=0:return

' 辺11,12
tr#=x12-x11:tj#=y12-y11
minx#=1e5:maxx#=0
'頂点20
cross#=tr#*(y20-y11)-tj#*(x20-x11)
crsc#=tr#*(cy2-y11)-tj#*(cx2-x11)
if cross#>maxx# then maxx#=cross#
if cross#<minx# then minx#=cross#
if cross#>=0&& cross#<cmin# then
cx=x20:cy=y20
nr=tj#:nj=-tr#
cmin#=cross#
endif
if crsc#<0&&cross#>0&&cross#<mmin# then
mcx#=x20:mcy#=y20
mr#=tj#:mj#=-tr#
mmin#=cross#
endif
'頂点21
cross#=tr#*(y21-y11)-tj#*(x21-x11)
if cross#>maxx# then maxx#=cross#
if cross#<minx# then minx#=cross#
if cross#>=0&& cross#<cmin# then
cx=x21:cy=y21
nr=tj#:nj=-tr#
cmin#=cross#
endif
if crsc#<0&&cross#>0&&cross#<mmin# then
mcx#=x21:mcy#=y21
mr#=tj#:mj#=-tr#
mmin#=cross#
endif
'頂点22
cross#=tr#*(y22-y11)-tj#*(x22-x11)
if cross#>maxx# then maxx#=cross#
if cross#<minx# then minx#=cross#
if cross#>=0&& cross#<cmin# then
cx=x22:cy=y22
nr=tj#:nj=-tr#
cmin#=cross#
endif
if crsc#<0&&cross#>0&&cross#<mmin# then
mcx#=x22:mcy#=y22
mr#=tj#:mj#=-tr#
mmin#=cross#
endif
if maxx#*(tr#*(y10-y11)-tj#*(x10-x11)-minx#)<0 then hit=0:return

' 辺12,10
tr#=x10-x12:tj#=y10-y12
minx#=1e5:maxx#=0
'頂点20
cross#=tr#*(y20-y12)-tj#*(x20-x12)
crsc#=tr#*(cy2-y12)-tj#*(cx2-x12)
if cross#>maxx# then maxx#=cross#
if cross#<minx# then minx#=cross#
アバター
こういち 2023/4/10 21:39 ◆ou0jbJnEJ0Kb
if cross#>=0&& cross#<cmin# then
cx=x20:cy=y20
nr=tj#:nj=-tr#
cmin#=cross#
endif
if crsc#<0&&cross#>0&&cross#<mmin# then
mcx#=x20:mcy#=y20
mr#=tj#:mj#=-tr#
mmin#=cross#
endif
'頂点21
cross#=tr#*(y21-y12)-tj#*(x21-x12)
if cross#>maxx# then maxx#=cross#
if cross#<minx# then minx#=cross#
if cross#>=0&& cross#<cmin# then
cx=x21:cy=y21
nr=tj#:nj=-tr#
cmin#=cross#
endif
if crsc#<0&&cross#>0&&cross#<mmin# then
mcx#=x21:mcy#=y21
mr#=tj#:mj#=-tr#
mmin#=cross#
endif
'頂点22
cross#=tr#*(y22-y12)-tj#*(x22-x12)
if cross#>maxx# then maxx#=cross#
if cross#<minx# then minx#=cross#
if cross#>=0&& cross#<cmin# then
cx=x22:cy=y22
nr=tj#:nj=-tr#
cmin#=cross#
endif
if crsc#<0&&cross#>0&&cross#<mmin# then
mcx#=x22:mcy#=y22
mr#=tj#:mj#=-tr#
mmin#=cross#
endif
if maxx#*(tr#*(y11-y12)-tj#*(x11-x12)-minx#)<0 then hit=0:return


' 辺20,21
tr#=x21-x20:tj#=y21-y20
'頂点10
cross#=tr#*(y10-y20)-tj#*(x10-x20)
crsc#=tr#*(cy1-y20)-tj#*(cx1-x20)
if cross#>=0&& cross#<cmin# then
cx=x10:cy=y10
nr=tj#:nj=-tr#
cmin#=cross#
endif
if crsc#<0&&cross#>0&&cross#<mmin# then
mcx#=x10:mcy#=y10
mr#=tj#:mj#=-tr#
mmin#=cross#
endif
'頂点11
cross#=tr#*(y11-y20)-tj#*(x11-x20)
if cross#>=0&& cross#<cmin# then
cx=x11:cy=y11
nr=tj#:nj=-tr#
cmin#=cross#
endif
if crsc#<0&&cross#>0&&cross#<mmin# then
mcx#=x11:mcy#=y11
mr#=tj#:mj#=-tr#
mmin#=cross#
endif
'頂点12
cross#=tr#*(y12-y20)-tj#*(x12-x20)
アバター
こういち 2023/4/10 21:43 ◆ou0jbJnEJ0Kb
if cross#>=0&& cross#<cmin# then
cx=x12:cy=y12
nr=tj#:nj=-tr#
cmin#=cross#
endif
if crsc#<0&&cross#>0&&cross#<mmin# then
mcx#=x12:mcy#=y12
mr#=tj#:mj#=-tr#
mmin#=cross#
endif

' 辺21,22
tr#=x22-x21:tj#=y22-y21
'頂点10
cross#=tr#*(y10-y21)-tj#*(x10-x21)
crsc#=tr#*(cy1-y21)-tj#*(cx1-x21)
if cross#>=0&& cross#<cmin# then
cx=x10:cy=y10
nr=tj#:nj=-tr#
cmin#=cross#
endif
if crsc#<0&&cross#>0&&cross#<mmin# then
mcx#=x10:mcy#=y10
mr#=tj#:mj#=-tr#
mmin#=cross#
endif
'頂点11
cross#=tr#*(y11-y21)-tj#*(x11-x21)
if cross#>=0&& cross#<cmin# then
cx=x11:cy=y11
nr=tj#:nj=-tr#
cmin#=cross#
endif
if crsc#<0&&cross#>0&&cross#<mmin# then
mcx#=x11:mcy#=y11
mr#=tj#:mj#=-tr#
mmin#=cross#
endif
'頂点12
cross#=tr#*(y12-y21)-tj#*(x12-x21)
if cross#>=0&& cross#<cmin# then
cx=x12:cy=y12
nr=tj#:nj=-tr#
cmin#=cross#
endif
if crsc#<0&&cross#>0&&cross#<mmin# then
mcx#=x12:mcy#=y12
mr#=tj#:mj#=-tr#
mmin#=cross#
endif

' 辺22,20
tr#=x20-x22:tj#=y20-y22
'頂点10
cross#=tr#*(y10-y22)-tj#*(x10-x22)
crsc#=tr#*(cy1-y22)-tj#*(cx1-x22)
if cross#>=0&& cross#<cmin# then
cx=x10:cy=y10
nr=tj#:nj=-tr#
cmin#=cross#
endif
if crsc#<0&&cross#>0&&cross#<mmin# then
mcx#=x10:mcy#=y10
mr#=tj#:mj#=-tr#
mmin#=cross#
endif
'頂点11
cross#=tr#*(y11-y22)-tj#*(x11-x22)
if cross#>=0&& cross#<cmin# then
cx=x11:cy=y11
nr=tj#:nj=-tr#
cmin#=cross#
endif
アバター
こういち 2023/4/10 21:43 ◆ou0jbJnEJ0Kb
if crsc#<0&&cross#>0&&cross#<mmin# then
mcx#=x11:mcy#=y11
mr#=tj#:mj#=-tr#
mmin#=cross#
endif
'頂点12
cross#=tr#*(y12-y22)-tj#*(x12-x22)
if cross#>=0&& cross#<cmin# then
cx=x12:cy=y12
nr=tj#:nj=-tr#
cmin#=cross#
endif
if crsc#<0&&cross#>0&&cross#<mmin# then
mcx#=x12:mcy#=y12
mr#=tj#:mj#=-tr#
mmin#=cross#
endif

hit=1
if mmin#<cmin# then
cx=mcx#:cy=mcy#
nr=mr#:nj=mj#
endif
var dist#=nr*nr+nj*nj
nr=nr/dist#:nj=nj/dist#
end

…長い!
アバター
うょリウム 2023/4/22 1:15 ◆gZYHRw9FSPa8
まーまーそんな難しく考えない
醜い解をご覧にいれましょう!?

判定用グラフィックページを用意して
そこにGFILLなりGCIRCLEなりGTRIなりで
判定したい図形を塗りつぶして
GSPOIT()で判定する!!

(ひどい)
アバター
こういち 2023/4/22 8:45 ◆ou0jbJnEJ0Kb
グラフィックでゴリ押す方法。
一対一で点との衝突判定なら悪くない選択肢ではあるんですよね。
似たような案は前トピックにも出ては居るんですけど、物体を大きくすると厳しくなりそうってのがあって…(8x8が限度)
アバター
うょリウム 2023/4/23 1:27 ◆gZYHRw9FSPa8
GCOPY、GSAVEとGLOADまで使えば
限られた条件でうまくいくかもしれません…?
アバター
こういち 2023/4/23 8:42 ◆ou0jbJnEJ0Kb
確かにGCOPY,GSAVE,GLOADは一切の時間を消費しないヤバい命令(たぶんカラクリがあって、連続で使うと分からない)
minはforの30倍以上早いことを考えると上手く使えばそれなりに使えそうですね。

コメントを書く

  • こちらは「プチコン3号」「プチコンBIG」など、プチコンシリーズに関する話題を扱ったコミュニティです
  • プチコンシリーズにまったく関係ない書き込みはご遠慮下さい。削除の対象となります
  • こちらにはその他のゲームや雑談のコミュニティはなく、作る予定もありません (ひとりで管理できないため)。ごめんなさい
  • ユーザー登録なしで書き込みができます
  • 秘密の合い言葉は成りすましの防止 (トリップ機能)、書き込みの編集時の本人認証に使用します
  • 秘密の合い言葉に他人に推測されやすい言葉、他サービスと同じパスワードは入力しないでください。
  • 書き込むと、投稿時に入力したお名前と秘密の暗号が記憶され、ログイン状態になります

- WEB PATIO -