캐릭터 점프구현에 대해서 질문입니다..

프로그래밍 일반에 관한 포럼입니다.

Moderator: 류광

Locked
비회원

캐릭터 점프구현에 대해서 질문입니다..

Post by 비회원 »

캐릭터를 스페이스 키 눌렀을 경우 점프하게 하려고 하는데요..

어떻게 구현을 해야할지 감이 안오네요...

캐릭터는 지금 캐릭터_무브()라는 함수를 이용해서 앞뒤좌우로 움직이고 있습니다.

이 상태에서 캐릭터를 점프시킬때 어떻게 해야하는지 몇일째 헤매고 있습니다.

Animate() 함수에서 매프레임마다 캐리터_무브()라는 함수를 호출합니다.

이렇게 해서 앞뒤좌우로 움직일때마다 캐릭터 포지션을 갱신하고 있습니다..

근데 점프는 등가속도 운동을 써서 구현해야 하는건 알고 있는데..

지금 상태는 스페이스 키를 누르면 쭈욱 움직이는게 아니고 한번만.. 움직이고 마네요..

어떤식으로 해결하는게 좋을까요??
류광
Posts: 3805
Joined: 2001-07-25 09:00
Location: GPGstudy
Contact:

Post by 류광 »

간단한 답: 유한상태기계(FSM)을 도입하세요....

긴 답:
키보드 입력 처리와 캐릭터 좌표 갱신이 한데 모여 있는지요? 그렇다면 일단 그것을 분리시키는 게 먼저입니다. 키 입력은 캐릭터의 상태를 변경시키기만 하고, 좌표 갱신은 상태만을 참조해서 하는 것이지요. 그리고 상태는 키 입력 이외의 요인으로도 변경될 수 있어야 하구요(예를 들어 캐릭터가 땅에 닿으면 점프 상태 해제).

이런 것을 단순하게 구현하면 아마도 코드에 새로운 부울 변수, switch 문 등이 도입될 것입니다. 그런데 새로운 기능이 추가될수록 새로운 변수와 case들이 늘어날 것이고... 코드가 점점 지저분해져서 다른 방법을 찾게 될 것입니다. 그에 대한 한 가지 답이 유한상태기계(FSM)입니다.

(p.s. 프로그래밍 일반 게시판으로 옮겼습니다.)
valfiros
Posts: 19
Joined: 2006-07-08 09:28
Location: 은하바보연맹
Contact:

저같은 경우는...

Post by valfiros »

캐릭터를 스페이스 키 눌렀을 경우 점프하게 하려고 하는데요..
어떻게 구현을 해야할지 감이 안오네요...
캐릭터는 지금 캐릭터_무브()라는 함수를 이용해서 앞뒤좌우로 움직이고 있습니다.
이 상태에서 캐릭터를 점프시킬때 어떻게 해야하는지 몇일째 헤매고 있습니다.
Animate() 함수에서 매프레임마다 캐리터_무브()라는 함수를 호출합니다.
이렇게 해서 앞뒤좌우로 움직일때마다 캐릭터 포지션을 갱신하고 있습니다..
근데 점프는 등가속도 운동을 써서 구현해야 하는건 알고 있는데..
지금 상태는 스페이스 키를 누르면 쭈욱 움직이는게 아니고 한번만.. 움직이고 마네요..
어떤식으로 해결하는게 좋을까요??
그닥 능력있는 프로그래머가 아니라 부끄럽지만 답변을 달아봅니다. :oops:


현재 상태가 스페이스키를 누르면 쭈욱이 아니고 한번만...움직인다는게 무슨소리인지 사실 잘 모르겠습니다.
한번 점프가 되고 그이후에 다시 점프가 안된거라면, 아마도 점프 상태임을 확인하는 루틴 문제가 아닐까요?

상태가 점프중이라면 공중점프를 막는 부분이 있을테니, 공중에서 착지한 후 점프중이라는 상태가 착지상태로 상태변경이 되지 않는다면 재점프가 되지 않겠지요.

한번만 움직이고 만다는게 아주 짧게 점프하고 마는 상태라면 점프 에너지를 늘려주면 돼겠고요 -

3d이신듯 한데, (전후좌우니까.)

키입력 -> 상태버퍼 변경..
상태체크 -> 키입력 상태가 있을경우 해당 방향으로 하는 에너지를 객체의 현 가속도에 추가...(가속도는 물론 x,y,z 전부 ; )
중력체크 -> 상수로 지정해놓은 공기저항 및 중력을 적절한 방향으로 객체의 현 가속도에 추가.
(말이 좋아서 저항이지 제경우는 단순히 가속도에서 상수값을 빼주는 것 뿐이지만요.)
객체체크 -> 객체의 가속도에서 속도를 산출..
그리기 -> 객체의 x,y,z방향의 속도만큼 이동시킨 장소에 그리기.

저는 이런식으로 합니다. 사용하고자 하는 플랫폼에 맞춰서 간소화시키거나 해야하겠지만요.
(솔직히 게임같이 보이는걸 만들 수 있게 된 것은 586이 나온 후라서 ,
하드웨어 딸리는 플랫폼의 무서움은 모르는지라...)

물론 점프도 방향의 하나이므로 키입력으로 점프상태로 만들고,
점프상태로 들어갔을때 Z축으로 에너지를 주고, (물론 에너지는 키입력이 들어온 순간 1번만 줘야겠지요.)
그 에너지에서 중력을 뺀만큼 가속도를 더하고,
그 가속도가 속도로..속도가 이동으로 바뀌어서 Z축으로 상승하다가 점프시 받은 가속도가 중력가속도에
밀려 사라지는 순간 낙하가 시작돼어, 땅으로 떨어지겠죠.

여기서 물론 지면과 충돌체크 루틴이 있어야 착지했는지 확인하고 점프상태를 끌 수 있겠죠? (지면 충돌체크에 미스가 있어서 점프상태가 꺼지지 않는다면 재 점프가 불가능하겠죠.)



몇몇 액션게임처럼 스페이스바 누르는 시간에 따라 점프높이를 다르게 하고싶으면...
처음에 점프 들어갔을때 일정량의 에너지를 주고, 그이후 스페이스바가 계속 눌러져 있다면 소량의 에너지를 계속 공급해주면 돼겠죠.



-여랑 올림-


p.s 저는 미친듯한 SWITCH와 상태참조 함수의 지저분함에 해결책을 찾고있는 상황이라고 해야할 듯 하네요 :oops:
배우지 않으면 항상 불안한 겁많은 초보 프로그래머 A. 맹렬 다이어트중.
비회원

혹시 ...

Post by 비회원 »

농구 게임 ?

너비 뛰기 게임 ?

설마 높이뛰기 게임은 .. 아닐 듯 ..
xevious7
Posts: 175
Joined: 2006-03-30 17:31
Contact:

Re: 캐릭터 점프구현에 대해서 질문입니다..

Post by xevious7 »

비회원 wrote:캐릭터를 스페이스 키 눌렀을 경우 점프하게 하려고 하는데요..

어떻게 구현을 해야할지 감이 안오네요...

캐릭터는 지금 캐릭터_무브()라는 함수를 이용해서 앞뒤좌우로 움직이고 있습니다.

이 상태에서 캐릭터를 점프시킬때 어떻게 해야하는지 몇일째 헤매고 있습니다.

Animate() 함수에서 매프레임마다 캐리터_무브()라는 함수를 호출합니다.

이렇게 해서 앞뒤좌우로 움직일때마다 캐릭터 포지션을 갱신하고 있습니다..

근데 점프는 등가속도 운동을 써서 구현해야 하는건 알고 있는데..

지금 상태는 스페이스 키를 누르면 쭈욱 움직이는게 아니고 한번만.. 움직이고 마네요..

어떤식으로 해결하는게 좋을까요??

안녕하세요.

일단 구현의 촛점은(디자인측면) 위의 류광님의 답변을 참조하시면 될듯 합니다.

구현의 디테일은 다음과 같은 방법입니다.

움직임함수는 여러가지를 쓸수 있겠지만 점프라면 간단한 포물선또는 그런느낌만 주면 됩니다.

뭔가 정밀하게 하자면 중력가속도를 이용한 물리법칙으로 구현하시면 되구요.


초간단이라면 이런식입니다.(일단 2차원만 고려했습니다. 3차원도 결국 평면의 방향만 결정되면
캐릭터가 진행할면만 고정되면 그대로 사용해도 상관없을 것 같습니다.)

일단 점프가 끝나는 시점은 땅에 닺는 시점입니다. 결국 시간단위가 되겠죠. 점프시작시점이
T0 라고 하면 점프끝나는 시점은 어딘가의 Tn 시점이 되겠습니다.

점프곡선을 가파르게할것인지 아니면 유연하게 할것인지는 가속도로 정합니다. V
가속도는 당연이 T0와 Tn 단에서 가장 큽니다. 절벽으로 떨어지는 경우가 있기때문에
최대가속도도 정해놓으면 좋습니다. 최대가속도에 도달하면 더이상 속도는 증가하지 않는것이죠
가속도의 증분(dV) 에 의해서 최대높이가 결정됩니다. 만약 가속도가 10이고 증분치가 -1 이라면
최대높이는 T10 에서 이루어지며 10 + 9 + 8 + .... + 1 이 되겠습니다.


높이와 가속도 구하는 알고리즘은 이렇게 되겠습니다.

1. 높이계산 Tn 시점의 높이 = Tn-1 시점의 높이 + 가속도

2. 다음단계를 위한 가속도계산

가속도 = 가속도 - 일정치
if 가속도가 최대치를 넘는다면 최대가속도로 고정.


이것을 가지고 프레임단위로 적용하면 되겠습니다. 너무 빨리 내려온다고 싶으면 증분치를 작게설정하거나
높이가 낮다고 생각하면 최초가속도를 크게 하면 되겠습니다. 아니면 스케일링을 해도 됩니다.

높이 = 높이* 스케일.

위의 알고리즘은 굉장히 간단합니다만 상당히 정밀한 곡선을 가집니다. 왜냐면 미분의 원리를 이용한
방법이기 때문에 (이차방정식인 포물선을 미분하면 1차방정식이 되지요) 속도도 빠르면서 다른형태의
정밀한 방정식을 사용한 구현하고 별차이가 거의 없습니다.
가속도하고 증분값만 잘 조정해주면 말입니다. 실제적으로 위의 알고리즘이 사실
T에관한 운동의공식이기 때문에;;;.

뭐든지 그림이 확실하죠.

http://www.xevious7.com/102

앞으로 가는 속도가 없으면 제자리 뛰기가 될것이 속도가 크면 완만한 포물선 속도가 없으면 경사큰 포물선이
되겠습니다.

From Xevious7. http://www.xevious7.com
비회원

좀 무책임한 답이지만.

Post by 비회원 »

물리엔진을 쓰심이...
ode 나 ageia의 novodex 강추합니다.

토카막은 좀...
xevious7
Posts: 175
Joined: 2006-03-30 17:31
Contact:

좀더 정밀한 곡선을 원한다면 물리공식을 쓰면됩니다.

Post by xevious7 »

운동의 법칙에 의해서 시간에 따른 거리는 속도에 비례하고 가속도는 시간과 속도 비례로 정의되므로
아시다시피 다음과 같은 공식이 있습니다.

거리 s = v * t
가속도 a = v/t , 따라서 임의 t 시점에서의 거리는 s = a * t *t (t의제곱)
이 됩니다. 이공식을 이용하면 되겠습니다.

추가 글 이었습니다. From Xevious7. http://www.xevious7.com
xevious7
Posts: 175
Joined: 2006-03-30 17:31
Contact:

위의 직관적인 라직을 수학적으로 정리해보았습니다.

Post by xevious7 »

안녕하세요.

답변을 달다보니 단순하게 증분을 더하는 형태 가 결국 1에서 n까지의 수열합이라는 것을 알았습니다.
즉 위의 방법은 n(n+1) / 2 의 형태의 운동방정식이 되는 것입니다.

그래서 생각한것이 그럼 일반 운동방정식 a * n^2 + c 형태의 방정식도 수열합이 가능하지 않을까
라고 생각해서보니 일반항이 2*n -1 인 수열의 합이 n^2 이므로 이것도 더하는 값만 n에서
2*n -1 으로 바뀐 똑같은 알고리즘 적용이 가능하다는 것까지 생각했습니다.

최종 정리글은 http://www.xevious7.com/103 입니다.

좋은 주말 되세요.
Locked