ยท GJK-EPA ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ํ๋ ์ด์ด๋ฅผ ๋ฐ์ด๋ด๋ ์ค๋ธ์ ํธ ๋ง๋ค๊ธฐ
ยท ๋ถ๋ฆฌ์ถ(SAT)์ถฉ๋๊ฒ์ฌ๋ฅผ ์ฌ์ฉํด์ ๋ฐ์ด๋ด๋ ์ค๋ธ์ ํธ ๋ง๋ค๊ธฐ
ยท OBB์ถฉ๋๊ฒ์ฌ๋ฅผ ์ฌ์ฉํด์ ๋ฐ์ด๋ด๋ ์ค๋ธ์ ํธ ๋ง๋ค๊ธฐ
ยท ์ ์ถฉ๋์ฒดํฌ & AABB์ถฉ๋์ฒดํฌ
ยท ๋ฒกํฐ์ ์ฐ์ฐ๊ณผ ํ์ฉ
ยท ๊ทน์ขํ๊ณ์ ๊ธฐ๋ณธ ์ฐ์ฐ๋ค
ยท ์ ์ด ๋ค๊ฐํ์ ํฌํจ๋๋์ง ๊ตฌํ๊ธฐ
ยท ์ ์ ํฌํจ๊ณผ ์ ๋ถ์ ๊ต์ฐจ๋ฅผ ์ด์ฉํ ์ถฉ๋์ฒดํฌ
ํ๋ ์ด์ด๋ฅผ ๋ฐ๋ผ์ค๋ฉด์ ์ถ๊ฒฉํ๋ย ์ค๋ธ์ ํธ๋ฅผ ๋ง๋๋ ๋ฐฉ๋ฒ์ ๋ํ ๊ธ์ด์์
๊ทธ๋ฆฌ๊ณ ์ ๋ ์ํ์ด๋ ํ๋ก๊ทธ๋๋ฐ์ ์ ์๋๊ฒ ์๋๋ผ, ํ๋ฆฌ๊ฑฐ๋ ์๋ชป๋ ๋ถ๋ถ์ด ์์์๋ ์์ด์
ใ กใ กใ กใ กใ กใ กใ กใ กใ กใ ก
1. ๋ฒกํฐ์ ๋ง์ ์ ํ์ฉํ ๋ฐฉ๋ฒ
์ฒซ๋ฒ์งธ๋ ๋ฒกํฐ์ ๋ง์ ์ ํ์ฉํ ๋ฐฉ๋ฒ์ด์์, ์ด ๋ฐฉ๋ฒ์ผ๋ก๋ ๋ฐฉํฅ๊ณผ ์๋๊ฐ ๋ณํ๋ ์ถ๊ฒฉํ ์ค๋ธ์ ํธ๋ฅผ ๋ง๋ค์ ์์ด์
ย
ใ กใ กใ กใ กใ กใ กใ กใ กใ กใ ก
def vector_lim(x1,y1,x2,y2,lmn,lmx)
x3, y3 = x1+x2, y1+y2
d = (x3**2+y3**2)**0.5
if d < lmn
x3, y3 = x3/d, y3/d
return x3*lmn, y3*lmn
end
if d > lmx
x3, y3 = x3/d, y3/d
return x3*lmx, y3*lmx
end
return x3, y3
end
ใ กใ กใ กใ กใ กใ กใ กใ กใ กใ ก
์์ ์ฌ๋ ค๋์ ์ฝ๋๋ ๋ฒกํฐ์ ๋ง์ ์ ํด์ฃผ๋ ํจ์์ ์ฝ๋์์, rubyํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ก ์์ฑํ๊ฑฐ์์
๋ฒกํฐ (x1,y1) ๊ณผ (x2,y2)๋ฅผ ์ ๋ ฅํ๋ฉด, ๋ ๋ฒกํฐ๋ฅผ ๋ํ ๋ฒกํฐ๋ฅผ ์ถ๋ ฅํด์ค์
๊ทธ๋ฆฌ๊ณ ์ด๋ ๊ทธ๋ ๊ฒ ์ถ๋ ฅ๋๋ ๋ฒกํฐ๋ฅผ, ๋ฐฉํฅ์ ๋ณ๊ฒฝํ์ง ์์์ฑ๋ก ๊ทธ ๊ธธ์ด๋ง ์ ๋ ฅํ ์ต์๊ธธ์ด(lmn)์ ์ต๋๊ธธ์ด(lmx) ๋ฒ์ ๋ด๋ก ์ถ๋ ฅํด์ค์,
์ฆ, ๋ ๋ฒกํฐ๋ฅผ ๋ํ ๋ฒกํฐ์ ๊ธธ์ด๋ฅผ ๊ตฌํด์, ๋ง์ฝ ๊ทธ ๋ฒกํฐ์ ๊ธธ์ด๊ฐ ์ต์๊ธธ์ด๋ณด๋ค ์์ผ๋ฉดย ํด๋น ๋ฒกํฐ๋ฅผ ์ ๊ทํํด์ ๋จ์๋ฒกํฐ๋ก ๋ง๋ ๋ค์, ์ต์๊ธธ์ด๋ฅผ ๊ณฑํด์ ์ถ๋ ฅํด์ฃผ๋๊ฑฐ์์ย ์ฆ, ๋ฒกํฐ์ ๋ฐฉํฅ์ ์ ์งํ์ฑ๋ก ๊ธธ์ด๋ง ์ต์๊ธธ์ด๋ก ์ถ๋ ฅํด์ฃผ๋๊ฑฐ์์
์ต๋๊ธธ์ด๋ณด๋ค ์ปค๋ค๋ ๊ฒฝ์ฐ์๋ย ๋ง์ฐฌ๊ฐ์ง์์, ๋ฒกํฐ์ ๋ฐฉํฅ์ ์ ์งํ์ฑ๋ก ๊ทธ ๊ธธ์ด๋ง ์ต๋๊ธธ์ด๋ก ์ถ๋ ฅํด์ค์
https://gall.dcinside.com/m/game_dev/162026
[์๋ฆฌ์ฆ] ๊ฒ์์ ์ ยท GJK์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ ๋ค์ํ ๋ํ์ ์ถฉ๋ํ์ ๊ตฌํ๊ธฐ ยท GJK-EPA ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ํ๋ ์ด์ด๋ฅผ ๋ฐ์ด๋ด๋ ์ค๋ธ์ ํธ ๋ง๋ค๊ธฐ ยท ๋ถ๋ฆฌ์ถ(SAT)์ถฉ๋๊ฒ์ฌ๋ฅผ ์ฌ์ฉํด์ ๋ฐ์ด๋ด๋ ์ค๋ธ์ ํธ ๋ง๋ค๊ธฐ ยท OBB
gall.dcinside.com
๋ฒกํฐ์ ๊ธธ์ด๋ฅผ ๊ตฌํ๋ ๋ฐฉ๋ฒ๊ณผ, ๋ฒกํฐ์ ์ ๊ทํ์ ๋ํด์๋ ์์ ๊ธ์ 6๋ฒ~8๋ฒ ๋ถ๋ถ์ ๋์์์ด์
ใ กใ กใ กใ กใ กใ กใ กใ กใ กใ ก
angle = Math.atan2($player_y-$object_y,$player_x-$object_x)
$object_move_x, $object_move_y = vector_lim($object_move_x, $object_move_y,ย $object_aim*Math.cos(angle),$object_aim*Math.sin(angle),2,5)
$object_x += $object_move_x
$object_y += $object_move_y
$object_angle = Math.atan2($object_move_y,$object_move_x)
ใ กใ กใ กใ กใ กใ กใ กใ กใ กใ ก
๊ทธ๋ฆฌ๊ณ ์์ ์ฌ๋ ค๋์ ์ฝ๋๊ฐ, ์ค์ ๋ก ์ด๋ ๊ฒ ๋ฒกํฐ์ ๋ง์ ์ ์ฌ์ฉํด์ ์ถ๊ฒฉํ ์ค๋ธ์ ํธ๋ฅผ ์์ง์ด๋ ์ฝ๋์์
$player_x,ย $player_y ๋ ๊ฐ๊ฐ ํ๋ ์ด์ด์ x y์ขํ๊ณ
$object_x, $object_y ๋ ๊ฐ๊ฐ ์ค๋ธ์ ํธ์ x y์ขํ์์
๊ทธ๋ฆฌ๊ณ ย $object_move_x, $object_move_y ๋ ๊ฐ๊ฐ ์ค๋ธ์ ํธ์ x์ถ์์์ย ์ด๋์๋๋ y์ถ์์์ ์ด๋์๋์์ย
์ฐ์ ์ํฌํ์ ํธ2(arctan2)๋ก ์ค๋ธ์ ํธ์ ํ๋ ์ด์ด์ ํ์ฌ ์ขํ๊ฐ์ ํตํด์ย ์ค๋ธ์ ํธ์์ ํ๋ ์ด์ด ๋ฐฉํฅ์ย ๊ฐ๋๋ฅผ ๊ตฌํด์
๊ทธ๋ค์ ๊ทน์ขํ๊ณ์ ๊ฐ๋์ ๊ฑฐ๋ฆฌ ๊ณต์์ผ๋ก ๋ฏธ๋ฆฌ ์ค์ ํด๋์ ๊ธธ์ด($object_aim ๊ฐ, ์ฌ๊ธฐ์๋ 0.2์์)์ ํด๋น ๊ฐ๋์ ๋ฒกํฐ๋ฅผ ๊ตฌํ๋ค์
์์์ ์ค๋ช ํ ์ค๋ธ์ ํธ์ x y ์ถ์์์ ์ด๋์๋์, ์ด๋ ๊ฒ ๊ตฌํย ๋ฒกํฐ๋ฅผ ์์์ ์ค๋ช ํ vector_limํจ์๋ฅผ ํตํด์ ๋ํด์,ย
๊ทธ๋ฌ๋ฉด ์ต์ข ์ ์ผ๋กย ์ค๋ธ์ ํธ์ ํ์ฌ ์๋(๋ฒกํฐ)์์, ํ๋ ์ด์ด๋ฅผ ํฅํด ์ฝ๊ฐ ์ ๋๋ ์๋(๋ฒกํฐ)๊ฐย vector_limํจ์์์ ์ค์ ํ ๊ธธ์ด์ ๋ฒ์(์ฌ๊ธฐ์๋ ์ต์๊ฐ 2๊ณ ์ต๋๊ฐ 5์์) ์์ผ๋กย ๋์ค๊ฒ ๋์
์ฆ, ๊ฐ์๊ณผ ๊ฐ์์ ํ๋ฉด์ ํ๋ ์ด์ด๋ฅผ ์ถ๊ฒฉํ๋ ์ค๋ธ์ ํธ์ ์ต์์๋์ ์ต๋์๋๋ฅผ ์ค์ ํ ์ ์๋๊ฑฐ์์
๊ทธ๋ฆฌ๊ณ ์ต์ข ์ ์ผ๋ก ์ด๋ ๊ฒ ๊ตฌํ ์ค๋ธ์ ํธ์ ์๋๋งํผ ์ค๋ธ์ ํธ์ ์ขํ๋ฅผ ์ด๋์ํค๊ณ
์ค๋ธ์ ํธ์ ์๋์ ์ํฌํ์ ํธ2๋ฅผ ์ฌ์ฉํด์ ์ค๋ธ์ ํธ์ ํ์ฌ ๊ฐ๋($object_angle)๋ฅผ ๊ตฌํ๋๊ฑฐ์์
๊ทธ๋ฆฌ๊ณ 1ํ๋ ์๋ง๋ค ์ด๋ฐ์์ ์ฐ์ฐ์ ๋ฐ๋ณตํ๋๊น, ์ต์ข ์ ์ผ๋ก๋ ์ค๋ธ์ ํธ๊ฐ ๋ฐฉํฅ๊ณผ ์๋๋ฅผย ๋ณ๊ฒฝํ๋ฉด์ ํ๋ ์ด์ด๋ฅผ ์ถ๊ฒฉํ๊ฒ ๋๋๊ฑฐ์์
https://gall.dcinside.com/m/game_dev/164492
[์๋ฆฌ์ฆ] ๊ฒ์์ ์ ยท GJK์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ ๋ค์ํ ๋ํ์ ์ถฉ๋ํ์ ๊ตฌํ๊ธฐ ยท GJK-EPA ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ํ๋ ์ด์ด๋ฅผ ๋ฐ์ด๋ด๋ ์ค๋ธ์ ํธ ๋ง๋ค๊ธฐ ยท ๋ถ๋ฆฌ์ถ(SAT)์ถฉ๋๊ฒ์ฌ๋ฅผ ์ฌ์ฉํด์ ๋ฐ์ด๋ด๋ ์ค๋ธ์ ํธ ๋ง๋ค๊ธฐ ยท OBB
gall.dcinside.com
์ํฌํ์ ํธ2์ ๊ทน์ขํ๊ณ์ ๊ฐ๋์ ๊ฑฐ๋ฆฌ ๊ณต์์, ์์ ์ฌ๋ ค๋์ ๊ธ์ 3๋ฒ๊ณผ 4๋ฒ์ ๋์์์ด์
2. CCW์๊ณ ๋ฆฌ์ฆ์ ํ์ฉํ ๋ฐฉ๋ฒ
๋๋ฒ์งธ๋ CCW์๊ณ ๋ฆฌ์ฆ์ ํ์ฉํ ๋ฐฉ๋ฒ์ด์์,
์ด ๋ฐฉ๋ฒ์ผ๋ก๋ ์๋๋ ์ผ์ ํ๊ฒ ์ ์งํ ์ฑ๋ก ๋ฐฉํฅ๋ง ๋ณํ๋ฉด์ ํ๋ ์ด์ด๋ฅผ ์ถ๊ฒฉํ๋ ์ค๋ธ์ ํธ๋ฅผ ๋ง๋ค์ ์์ด์
ใ กใ กใ กใ กใ กใ กใ กใ กใ กใ ก
def side_angle(a,b)
t = Math.cos(a)*Math.cos(b)+Math.sin(a)*Math.sin(b)
if t > 1
t = 1
end
if t < 0
t = 0
end
return Math.acos(t)
end
ใ กใ กใ กใ กใ กใ กใ กใ กใ กใ ก
์์ ์ฌ๋ ค๋์ ์ฝ๋๋ a์ b๋ก ๋ ๊ฐ๋๋ฅผ ์ ๋ ฅํ๋ฉด, ๊ทธ ์ฌ์ด์ ๊ฐ๋๋ฅผ 0~180๋ ๋ฒ์๋ก ์ถ๋ ฅํด์ฃผ๋ ํจ์์์
๋ฒกํฐ์ ๋ด์ ์ ์ด์ฉํด์ ๋ ๋ฒกํฐย ์ฌ์ด์ ๊ฐ๋๋ฅผ ๊ตฌํ๋๊ฑฐ์์, ์์ ์ฌ๋ ค๋์ ๋ฒกํฐ๋ฅผ ์ค๋ช ํ ๊ธ์ 19๋ฒ์ ๋์์๋ ๋ด์ฉ์ด์์
ย
ใ กใ กใ กใ กใ กใ กใ กใ กใ กใ ก
def ccw(x1,y1,x2,y2,x3,y3)
return (x1*y2+x2*y3+x3*y1)-(y1*x2+y2*x3+y3*x1)
end
ใ กใ กใ กใ กใ กใ กใ กใ กใ กใ ก
๊ทธ๋ฆฌ๊ณ ์์ ์ฌ๋ ค๋์ ์ฝ๋๋ ccw์๊ณ ๋ฆฌ์ฆ์ ์ฝ๋์์,
(x1,y1,x2,y2,x3,y3)์ผ๋ก ์ธ ์ ์ ์ ๋ ฅํ๋ฉด, 1์ ์์ 2์ ์ ํฅํ๋ ๋ฐฉํฅ์ย ๊ธฐ์ค์ผ๋กย 3์ ์ด ๋ฐ์๊ณ๋ฐฉํฅ(+๋ฐฉํฅ)์ ์๋์ง ์๊ณ๋ฐฉํฅ(-๋ฐฉํฅ)์ ์๋์ง๋ฅผ ์์๋ผย ์ ์๋ ์๊ณ ๋ฆฌ์ฆ์ด์์
์ญ์ ์์ ์ฌ๋ ค๋์ ๋ฒกํฐ๋ฅผ ์ค๋ช ํ ๊ธ์ 22๋ฒ์ ๋์์๋ ๋ด์ฉ์ด์์
ใ กใ กใ กใ กใ กใ กใ กใ กใ กใ ก
x1,y1 = $object_x,$object_yย
x2,y2 = $object_x+5*Math.cos($object_angle),$object_y+5*Math.sin($object_angle)
x3,y3 = $player_x, $player_y
angle = Math.atan2($player_y-$object_y,$player_x-$object_x)
if side_angle(angle,$object_angle) <= $object_turn
$object_angle = angle
else
if ccw(x1,y1,x2,y2,x3,y3) > 0
$object_angle += $object_turn
else
$object_angle -= $object_turn
end
end
$object_x += $object_move*Math.cos($object_angle)
$object_y += $object_move*Math.sin($object_angle)
ใ กใ กใ กใ กใ กใ กใ กใ กใ กใ ก
๊ทธ๋ฆฌ๊ณ ์์ ์ฌ๋ ค๋์ ์ฝ๋๊ฐ ์ค์ ๋ก ccw์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํด์ ํ๋ ์ด์ด๋ฅผ ์ถ๊ฒฉํ๋ ์ค๋ธ์ ํธ๋ฅผ ์์ง์ด๋ย ์ฝ๋์์
์ฐ์ ccw์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ ย (x1,y1,x2,y2,x3,y3)์ ๊ฐ์ ๊ตฌํด์
1์ ์ ์ค๋ธ์ ํธ์ ์ขํ๊ณ , 2์ ์ ์ค๋ธ์ ํธ์ ํ์ฌ ๊ฐ๋๋ก 5๋งํผ ๋จ์ด์ง ๊ฑฐ๋ฆฌ์ ์ (๊ฑฐ๋ฆฌ์ ๊ธธ์ด๋ ์๊ด์์ด์)์ด๊ณ ย
3์ ์ ํ๋ ์ด์ด์ ์ขํ์์
๊ทธ๋ค์ ์ํฌํ์ ํธ2์ ์ค๋ธ์ ํธ์ ํ๋ ์ด์ด์ ์ขํ๊ฐ์ ๋ฃ์ด์, ์ค๋ธ์ ํธ์์ ํ๋ ์ด์ด ๋ฐฉํฅ์ผ๋ก์ ๊ฐ๋๋ฅผ ๊ตฌํด์
๊ทธ๋ฆฌ๊ณ ย ์์์ ์ค๋ช ํ side_angleํจ์๋ฅผ ์ฌ์ฉํด์ย ๊ทธ๋ ๊ฒ ์ป์ด์ง ๊ฐ๋์ย ์ค๋ธ์ ํธ์ ๊ฐ๋ ์ฌ์ด์ ๊ฐ๋๋ฅผ ๊ตฌํด์
๊ทธ๋ฆฌ๊ณ ๋ง์ฝ ๊ทธ ๊ฐ์ด ์ค๋ธ์ ํธ์ ํ์ ์๋($object_turn, ์ฌ๊ธฐ์๋ 5๋์์) ๋ณด๋ค ๊ฐ๊ฑฐ๋ ์์ผ๋ฉด, ์ค๋ธ์ ํธ์ ๊ฐ๋๋ฅผ ๊ทธ๋ ๊ฒ ๊ตฌํ ๊ฐ๋, ์ฆ ํ๋ ์ด์ด๋ฅผ ํฅํ ๊ฐ๋๋ก ๋ณ๊ฒฝํด์
๊ทธ๋ฆฌ๊ณ ๋ง์ฝ ๊ทธ ๊ฐ์ด ์ค๋ธ์ ํธ์ ํ์ ์๋๋ณด๋ค ํฌ๋ค๋ฉด
์์์ ๊ตฌํย (x1,y1,x2,y2,x3,y3)๊ฐ๋ค์ ๊ธฐ๋ฐ์ผ๋ก ccw์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํด์,ย
ํ๋ ์ด์ด๊ฐ ์ค๋ธ์ ํธ์ +๋ฐฉํฅ์ ์๋์ง, -๋ฐฉํฅ์ ์๋์ง๋ฅผ ๊ตฌํ๊ณ
์ค๋ธ์ ํธ์ ๊ฐ๋๋ฅผ ํด๋น ๋ฐฉํฅ์ผ๋กย ์ค๋ธ์ ํธ์ ํ์ ์๋๋งํผ ๋ณ๊ฒฝ์์ผ์(+5 ๋๋ -5)
๊ทธ๋ฆฌ๊ณ ์ต์ข ์ ์ผ๋ก ์์์ ์ค๋ช ํ ๊ทน์ขํ๊ณ์ ๊ฐ๋์ ๊ธธ์ด ๊ณต์์ผ๋ก
๊ทธ๋ ๊ฒ ๋ณ๊ฒฝ๋ ์ค๋ธ์ ํธ์ ๊ฐ๋๋ก, ์ค๋ธ์ ํธ์ ์๋($object_move, ์ฌ๊ธฐ์๋ 3์ด์์)๋งํผ ์ค๋ธ์ ํธ์ ์ขํ๋ฅผ ์ด๋์ํค๋๊ฑฐ์์
๊ทธ๋ฆฌ๊ณ 1ํ๋ ์๋ง๋ค ์ด๋ฐ ์ฐ์ฐ์ ๋ฐ๋ณตํ๋๊น, ์ต์ข ์ ์ผ๋ก๋ ์ค๋ธ์ ํธ๊ฐ ์๋๋ ์ผ์ ํ๊ฒ ์ ์งํ์ฑ๋ก ๋ฐฉํฅ๋ง ๋ณ๊ฒฝํ๋ฉด์ ํ๋ ์ด์ด๋ฅผ ์ถ๊ฒฉํ๊ฒ ๋๋๊ฑฐ์์
์์ ์ฌ๋ ค๋์ ์์์, ์์์ ์ค๋ช ํ ๋ฐฉ๋ฒ์ผ๋ก ์ธ๊ฒ์์์ ํ๋ ์ด์ด๋ฅผ ์ถ๊ฒฉํ๋ ์ค๋ธ์ ํธ๋ฅผ ๋ง๋ ๊ฑฐ์์
์ฒซ๋ฒ์งธ ๋ณด๋ผ์์ด ๋ฒกํฐ์ ๋ง์ ์ ์ฌ์ฉํ, ๋ฐฉํฅ๊ณผ ์๋๊ฐ ๋ณํ๋ฉด์ ํ๋ ์ด์ด๋ฅผ ์ถ๊ฒฉํ๋ ์ค๋ธ์ ํธ๊ณ
๋๋ฒ์งธ ์ฐ๋์์ด CCW์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ, ์๋๋ ์ผ์ ํ๊ฒ ์ ์งํ๋ฉด์ ๋ฐฉํฅ๋ง ๋ณํ๋ฉด์ ํ๋ ์ด์ด๋ฅผ ์ถ๊ฒฉํ๋ ์ค๋ธ์ ํธ์์
๊ทธ๋ฆฌ๊ณ ์ด๋ฐ์์ผ๋ก ํ๋ฉด ํ๋ ์ด์ด๋ฅผ ์ถ๊ฒฉํ๋ ์ค๋ธ์ ํธ๋ฅผ ๋ง๋ค ์ ์์ด์
์ด์ ๊ธธ์ฐพ๊ธฐ๋ง ๋ง๋ค๋ฉด ๋๊ฒ ๋ค!!!