当たり判定のやり方
kuku 2013/3/27(Wed) 23:30:17|NO.53290
矩形の判定のやり方が、色々調べてもわからないです
できたら教えて下さい
四角いもの同士の当たり判定です
ツノン 2013/3/28(Thu) 09:39:49|NO.53294
user32.dll の IntersectRect 関数を使用すると可能です。
下はスクリプト。
#include "user32.as"
rc = 10,10,100,100
rc2= 50,50,120,120
dim rt,4
drawrc rc
color 255
drawrc rc2
IntersectRect varptr(rt),varptr(rc),varptr(rc2)
if(stat){
color ,255
drawrc rt
dialog "接触している"
}
stop
#deffunc drawrc array rc_
boxf rc_,rc_.1,rc_.2,rc_.3
return
スクリプトは多分こんな感じだと思います。
二つの四角形の頂点をそれぞれ調べて、一つでももう片方の四角形の内側に入っている場合、重なっていると判断しています。
#module
#define global ctype ptinrc(%1,%2,%3,%4,%5,%6)\
((%3<=%1) and (%4<=%2) and (%5>=%1) and (%6>=%2))
#const ISL_ 1<<0
#const IST_ 1<<1
#const ISR_ 1<<2
#const ISB_ 1<<3
#const ISL_2_ 1<<4
#const IST_2_ 1<<5
#const ISR_2_ 1<<6
#const ISB_2_ 1<<7
#const MASKL_ 0b00010001
#const MASKT_ 0b00100010
#const MASKR_ 0b01000100
#const MASKB_ 0b10001000
#define ctype push(%1)\
r%1_=%1_:i_|=IS%1_
#define ctype push2(%1)\
r%1_=%1_2_:i_|=IS%1_2_
#define ctype setrtvar(%1,%2) \
if(ptinrc(%1_,%2_,l_2_,t_2_,r_2_,b_2_)){push(%1):push(%2)}
#define ctype setrtvar2(%1,%2) \
if(ptinrc(%1_2_,%2_2_,l_,t_,r_,b_)){push2(%1):push2(%2)}
#define ctype check(%1,%2) \
if(i_&MASK%1_)==0{if(i_&IS%2_2_){push(%1)}else{push2(%1)}}
// 四角形同士が接触しているかを判定して。
// 接触している四角形を返す。
#deffunc rect_Intersect \
int l_ , int t_ , int r_ , int b_ , \
int l_2_ , int t_2_ , int r_2_ , int b_2_ , \
var rl_ , var rt_ , var rr_ , var rb_ , \
local i_
setrtvar(l,t)
setrtvar(r,t)
setrtvar(r,b)
setrtvar(l,b)
setrtvar2(l,t)
setrtvar2(r,t)
setrtvar2(r,b)
setrtvar2(l,b)
if(i_){
check(l,r)
else:check(t,b)
else:check(r,l)
else:check(b,t)
}
return i_
#global
px=200:py=200
title "マウスを移動させて四角形同士を接触させてみて下さい。"
repeat
redraw 0
color 255,255,255
boxf
bx = mousex
by = mousey
color 255,255
boxf bx,by,bx+100-1,by+100-1
color 255
boxf px,py,px+50-1,py+50-1
rect_Intersect px,py,px+50,py+50,bx,by,bx+100,by+100 , rl , rt , rr , rb
if(stat){
color ,255,255
boxf rl , rt , rr , rb
}
redraw 1
await 30
loop
以前出来るだけ速度を上げようとしたそれなので、スクリプトはこんな感じですが。
一応動くのでアップします。
あり 2013/3/28(Thu) 10:31:21|NO.53299
矩形同士の判定なら一行ですみます。
式の意味は『四角 当たり判定』等で検索すれば解説ページが沢山出てくるので
そちらを参照下さい。
; 自機の矩形サイズ
#const X1 -50
#const X2 50
#const Y1 -50
#const Y2 50
; 記述簡略用マクロ
#define CX1 x + X1
#define CX2 x + X2
#define CY1 y + Y1
#define CY2 y + Y2
; 敵の矩形サイズ
#const TX1 350
#const TX2 550
#const TY1 200
#const TY2 400
x = 120
y = 120
gsel 0, 1
*main
redraw 0
color 255, 255, 255 : boxf
stick key, 15
if key & 1 : x - 1
if key & 2 : y - 1
if key & 4 : x + 1
if key & 8 : y + 1
; 矩形の当たり判定
TC = 155, 255, 0
if (CX1 <= TX2) & (TX1 <= CX2) & (CY1 <= TY2) & (TY1 <= CY2) = 1 : TC = 0, 0, 255
; 敵矩形表示
color TC(0), TC(1), TC(2) : boxf TX1, TY1, TX2, TY2
pos TX1 - 28, TY1 - 20 : mes "(" + TX1 + "," + TY1 + ")"
pos TX2 - 34, TY1 - 20 : mes "(" + TX2 + "," + TY1 + ")"
pos TX1 - 28, TY2 + 4 : mes "(" + TX1 + "," + TY2 + ")"
pos TX2 - 34, TY2 + 4 : mes "(" + TX2 + "," + TY2 + ")"
; 自機矩形表示
color 255, 0, 0
circle x - 5, y - 5, x + 5, y + 5
line CX1, CY1, CX2, CY1
line CX2, CY2, CX1, CY2
line CX1, CY2, CX1, CY1
line CX2, CY1, CX2, CY2
pos x - 36, y + 8 : mes "(" + x + "," + y + ")"
pos CX1 - 28, CY1 - 20 : mes "(" + (CX1) + "," + (CY1) + ")"
pos CX2 - 34, CY1 - 20 : mes "(" + (CX2) + "," + (CY1) + ")"
pos CX1 - 28, CY2 + 4 : mes "(" + (CX1) + "," + (CY2) + ")"
pos CX2 - 34, CY2 + 4 : mes "(" + (CX2) + "," + (CY2) + ")"
redraw 1
await 10
goto *main
FunnyMaker 2013/3/28(Thu) 11:10:19|NO.53303
解決しそうな勢いですね。
が、ちょっと作ってしまったものがあってどうしても紹介したいので、載せちゃいます。
任意の四角形で判定が可能です。ゆがんでいる四角形でも難なく判定できるということです。
原理としては、四角形を2つの三角形に分割して個別に判定しています。
三角形同士の領域のシェアチェックは面倒な手順を踏みますが、 高等学校数学U までやっていれば割と簡単です。
原理の説明のPDFも入っています。
http://kie.nu/UT9
上記のURLから「test.zip」をDLして解凍すると「こんな感じ?.hsp」というサンプルが出ます。
それを実行してみてください。
モジュール化していますので、よかったら使ってやってください。
kuku 2013/3/28(Thu) 12:08:40|NO.53306
ツノンさん、ありさん、FunnyMakerさん
ありがとうございました。
よく読んで勉強します!
YSR 2013/3/30(Sat) 01:21:27|NO.53341
>NO.53306
一応補足だけど、
NO.53294やNO.53299は「辺が座標軸に平行な長方形同士の当たり判定」、
NO.53303は「任意の四角形同士の当たり判定」であることに注意な
当然後者の方が重い(判定に時間が掛かる)から、
前者で十分なものに後者のアルゴリズム使っても時間の無駄
(後者が必要なら仕方がないが)
特にシューティングやアクションのようにリアルタイム性が求められる
ゲームを作る時なんかは、そうした当たり判定の取捨選択がとても大切だったりする