핀볼의 반사 알고리즘좀 부탁드립니다.

수학, 물리학 등 게임 프로그래밍의 기반이 되는 이론에 관한 포럼입니다.

운영자: 류광

Locked
비회원

핀볼의 반사 알고리즘좀 부탁드립니다.

전체글 글쓴이: 비회원 » 2009-11-25 09:13

답답한 마음에 여기에 올려봅니다.
물리와 수학이 짧아서 구현에 어려움을 느끼네요
2D의 일반적인 핀볼을 만들려고 합니다.
야매로 물리를 구현하는 것은 어렵지 않은데
그렇게 구현하다보니 말도안되고 여러가지 문제가 생겼습니다.
저는 공의 반사를 다음과 같은식으로 구현했습니다.
군더더기 다빼고 반사부분만 적어보겠습니다.

코드: 모두 선택

update()
{
vBallDir += vBallDir * vGravity;
vBallPos += vBallDir * fElapsedTime;

for(int i = 0; i < pin_count; ++i)
{
if(vec.length <= fBallRadian + fPinRadian)
{
vBallDir.x = randomf(-1.0, 1.0);
vBallDir.y -= (vBallDir.y * 2.0);
}
}

위아래 반사는 그냥 부딧친방향값의 반대방향의 2배만큼 더해주고
좌우반사는 구현할방법을 찾지 못하여 내비두었습니다.
(핀과 볼의 내적을 구하여 좌우에 대한 방향벡터를 구할수도 있을 것 같다는 생각을 했습니다만,
애초에 물리에 대한 제반지식이 없이 쓰면 오히려 더 복잡해질것 같아 내비두었습니다.)

어떻게 해야 제대로 구현을 할 수 있을지 잘 모르겠군요.
구글신한테 뒤져봐도 핀볼알고리즘이 잘 안나오고,

답변 부탁드립니다.

blackman
전체글: 68
가입일: 2006-04-11 15:35
사는 곳: 무소속
연락처:

반사벡터라면

전체글 글쓴이: blackman » 2009-11-25 09:39

http://www.gamza.net/bbs/view.php?id=Ar ... c=asc&no=2

감자님 글중에 위에것을 참고하시면 되지 않을까 싶습니다.

저같은경우엔 2D라도 가상의 Z축이 있다고 가정해서 3D관련 벡터함수나 평면함수등을 이용할때도 있습니다.

visco
전체글: 114
가입일: 2006-07-02 12:46

전체글 글쓴이: visco » 2009-11-25 12:41

평면 2D핀볼이라면 이 정도가 될 듯한데..
제가 이해를 잘 못한건가요?;

코드: 모두 선택

if (x < 0 || x > MAX_WIDTH)
{
    dir.x *= -1.f;
}

if (y < 0 || y > MAX_HEIGHT)
{
    dir.y *= -1.f;
}

비회원

글쓴이입니다.

전체글 글쓴이: 비회원 » 2009-11-25 15:10

두분 답변 감사합니다.


// visco
반사뿐만아니라, 중력값, 운동량을 가져야될 것 같아서 저렇게 했습니다.
-1.0f 을 곱한것과 2를 곱해서 뺀것과 똑같이 양수 음수전환입니다.
제가 말씀을 잘 못드린것 같습니다.

// blackman
감사합니다. 참고하여 우선 구현해 보았습니다.
결과물은 다음과 같습니다.

코드: 모두 선택

inline D3DXVECTOR2 getVec2Refflection(D3DXVECTOR2 vD, D3DXVECTOR2 vN)
{
    // 방향이 N이며 물체의 이동방향이 D일때 반사벡터는 다음과 같다. 2 * (-D * N) ) N + D
    D3DXVECTOR2 vRefflectionDir = (2 * D3DXVECTOR2(-vD.x * vN.x, -vD.y * vN.y));
    return D3DXVECTOR2(vRefflectionDir.x * vN.x, vRefflectionDir.y * vN.y) + vD;
}
그런데 반사뿐만아니라 다른문제가 또 고민이 되는군요.
핀이 단순히 반사에 그치지 않고, 농구공처럼 포물선을 그리며 중력에 영향을 받아 점점 솟구치는 힘이
떨어지게 하고싶은데, 중력값과 그에 따른 운동량을 어떻게 구현해야할지 어렵습니다.
이는 어떻게 해야될까요.

moonyeom
전체글: 168
가입일: 2007-02-05 16:38

Re: 글쓴이입니다.

전체글 글쓴이: moonyeom » 2009-11-25 15:35

비회원 작성: 그런데 반사뿐만아니라 다른문제가 또 고민이 되는군요.
핀이 단순히 반사에 그치지 않고, 농구공처럼 포물선을 그리며 중력에 영향을 받아 점점 솟구치는 힘이
떨어지게 하고싶은데, 중력값과 그에 따른 운동량을 어떻게 구현해야할지 어렵습니다.
이는 어떻게 해야될까요.
공의 속도의 y 성분에 매 업데이트때마다 G*DeltaT 만큼 더하거다 빼주면 됩니다.
G 는 중력가속도인데요,
공의 실제 크기와 좌표상의 값을 미터법으로 비교해서 1:1 대응이 되면 G = 9.8 을 쓰시면 되구요
그렇지 않다면 적절히 키우거나 줄여 쓰시면 됩니다.
난, 가져다 쓰는건 왠지 싫어...

비회원

전체글 글쓴이: 비회원 » 2009-11-25 17:54

// moonyeom
우선 말씀하신부분을 적용하여 구현하였습니다.
만족스럽진 않지만 원하는 것과 비스무리한 구현이 나왔습니다.
그런데 제가 조금 더 듣고싶은 부분이 있습니다.
그것을 위해 일단 위에 설명해주신 모든분들의 도움으로 현재 구현된 것을 첨부합니다.

코드: 모두 선택

if(vBallDir.y > 0) fGravityPower += 9.8f * fElapsedTime;
else                    fGravityPower -= 9.8f * fElapsedTime;

vBallPos += vec2(vBallDir.x, vBallDir.y * fGravityPower) * fElpasedTime;

for(int i = 0; i < pin_coun; ++i)
{
if(vec2Length(vBallPos, vPinPos) > fRadian) // 핀과 충돌
{
    vBallDir = getVec2Refflection(vBallDir, vec2(0, 1)); // 현재 방향으로 반사벡터를 생성
}
지금 vBallDir 이라는 볼의 각도가 변경되는 시점은 핀에 볼이 부딧쳤을 경우입니다.
그외에는 볼의 각도가 변하지 않는데요.

vBallDir이 지금 구현으로는 순수한 방향값만 놔두고 있는데요.
쉽게말해서 방향값이 증가되거나, 감소되는 부분이 없습니다.
단순히 핀에 부딧쳤을때 변경되는 것밖에 없습니다.

굳이 그게 필요할까라고 물으신다면 현재 공이 너무 단조로운 감이 있기 때문입니다.
반사는 잘되고 통통튕기는데 그 힘이 항상 일정하고, 각도도 같습니다. 각도가 떨어지는 것도 없구요.
떨어진다면 방금 moonyeom이 도와주신대로 중력가속도가 떨어져서 위치가 떨어지는 것뿐이겠지요.
이 상태에서 무언가 바꿔주고싶은데 바꾸기가 어렵습니다.
아마도 각도를 바꾸면되지 않을까 생각하는데, 이를 어떻게 해야할까요.

비회원

전체글 글쓴이: 비회원 » 2009-11-25 17:56

위에 오타가났네요. 보통오타라면 넘어갈텐데 불쾌하실까봐...
moonyeom님 기분이 혹시라도 상하지 말라는 의미로 첨부합니다.
떨어진다면 방금 moonyeom'님'이 도와주신대로 중력가속도가 떨어져서 위치가 떨어지는 것뿐이겠지요.

moonyeom
전체글: 168
가입일: 2007-02-05 16:38

방향말고 "속도"로 해보셔요...

전체글 글쓴이: moonyeom » 2009-11-25 18:28

속도가 아닌 "공의 방향" 만으로 처리하고 계시군요.
방향벡터 vBallDir 를 방향과 속력을 함께 가지는 vBallSpeed 나 vBallVelocity 정도로 바꿔보셔요.

vBallSpeed.y = vBallSpeed.y - fGravityPower*fElapsedTime

이렇게 하면 업데이트때마다 속도에 중력이 영향을 주게 되어서 아래로 떨어지는 효과가 생길꺼구요.
fGravityPower 는 상수값으로 두시면 되고요.

위치 이동은 이렇게 하시면 됩니다.

vBallPos = vBallPos + vBallSpeed * fElpasedTime

사실, 아주 단순한 문제인데...
너무 복잡하게 바라보고 작업을 하신게 아닌지...
난, 가져다 쓰는건 왠지 싫어...

비회원

전체글 글쓴이: 비회원 » 2009-11-25 20:03

// moonyeom
제가 몰라서 불리하지 못한 것이 아닙니다. 저걸 뭉쳐놓으면 문제가 생깁니다.
x값은 방향벡터로서만 존재하는데, y값에 힘자체가 들어가서, 방향값을 제대로 얻어올 수 가 없어집니다.

혹시나싶어 말씀하신대로 수정을 해보았지만 역시 마찬가지입니다.
vBallDir 의 y값이 쌓여감에 따라 저걸 정규화시키면 x는 0에 가깝고, y는 1에 가깝게 나옵니다.
위에 처음에 질문했던 반사벡터가 작동을 안하게됩니다.

moonyeom
전체글: 168
가입일: 2007-02-05 16:38

약간의 오해가...

전체글 글쓴이: moonyeom » 2009-11-26 16:31

비회원 작성:x값은 방향벡터로서만 존재하는데, y값에 힘자체가 들어가서, 방향값을 제대로 얻어올 수 가 없어집니다.
이 부분에서 오해가 있는 것 같습니다.

x 값도 y 값도 속도라고 보셔야 합니다.
xy 성분을 갖는 속도벡터입니다.
그리고, 그 벡터의 크기 sqrt(x*x+y*y) 가 속력입니다.

중력이 아래로 작용하니 당연히 y 성분이 늘어나지만
바운딩(핀에 튕기는것)에 의해 방향이 바뀔때에는 x 값이 더 커지는 경우도 생긱게 됩니다.
이렇게 되면서 공이 핀들 사이를 이리저리 튕겨다니게 되는거죠.
비회원 작성:vBallDir 의 y값이 쌓여감에 따라 저걸 정규화시키면 x는 0에 가깝고, y는 1에 가깝게 나옵니다.
자꾸 방향값을 가지고 처리하시려고 하니까 문제가 생기는 것 같습니다.
속도 벡터를 가지고 처리하시면 되구요, 굳이 방향만 따로 필요할때에는 속도벡터를 Normalize 시켜 방향을 얻으시면 되구요...
근데 제가 볼때, 구현하시려는 것에서 방향벡터를 따로 갖고있을 필요가 없어요...
속도벡터만으로 이동도 구현하시고 바운딩도 구현하시면 됩니다...

아, 그리고...
반사벡터 구하기 공식을 가지고 바운딩을 구현하실때에, 얻어진 값에 탄성을 곱하시면 좀 더 자연스러운 모습을 구현하실 수 있습니다.
탄성은 0~1 사이의 값입니다.
난, 가져다 쓰는건 왠지 싫어...

사용자 아바타
Zeprod
전체글: 480
가입일: 2006-11-04 16:24
사는 곳: Creaty Networks
연락처:

전체글 글쓴이: Zeprod » 2009-11-27 17:53

이미 벡터요소에 x, y, z 인자가 있는데, 이것을 무시하고 직접 구현하시려고 하시는 것 같네요.

이런 기본적인 요소들은 계산방법의 차이도 거의 없고 평준화된 것들이니, 이왕이면 있는걸 쓰는게 안전하죠.
세상이 기다리는 나만의 SHOW!
----------------------------------------------
Zeprod 홈 : http://Zeprod.org
Project. Creaty : http://Creaty.net/
Creaty 게임제작 커뮤니티 : http://Creaty.net/game/
----------------------------------------------

Locked

접속 중인 사용자

이 포럼을 보고 있는 사용자: 회원 0 명, 손님 3 명