[Direct2D] 점프 구현
지난 글에서 플레이어 캐릭터가 착지할 수 있는 플랫폼을 만들었습니다.
[Direct2D] 충돌 및 지형 구현
위 글에서 생성된 플랫폼은 두 개 입니다.
하지만, 플레이어 캐릭터는 위로 올라갈 방법이 없었습니다.
이번 글에서는 플레이어 캐릭터에 점프 기능을 추가하도록 하겠습니다.
1. 키 입력 추가
이전에 구현한 중력 기능의 일부를 살펴보도록 하겠습니다.
FLOAT downSpeed = ~~~;
FLOAT gravity = ~~~;
void Update() {
...
FLOAT deltaDown = deltaTime * downSpeed;
downSpeed += deltaTime * gravity;
...
}
위와 같이 낙하 속도를 증가시키는 등가속 운동을 구현했습니다.
착지 판정 시 downSpeed는 0이 되어 더 이상 낙하하지 않습니다.
점프는 초기에는 상승 운동을, 이후 속도가 점점 줄어들며 하강 운동을 하는 형태의 운동으로 볼 수 있습니다.
따라서, 점프 키에 초기 속도인 downSpeed를 음수로 (좌표계 상 음수가 위쪽 방향이므로) 지정합니다.
코드는 다음과 같습니다.
void MyApp::HandleKeyboardInput() {
...
if (GetAsyncKeyState(VK_MENU) & 0x8000) {
if (!inputFlag[VK_MENU]) {
inputFlag[VK_MENU] = true;
if (curJumpCount++ < maxJumpCount) {
downSpeed = jumpPower;
}
}
} else {
if (inputFlag[VK_MENU]) {
inputFlag[VK_MENU] = false;
}
}
...
}
기존의 키 입력을 구현한 함수 HandleKeyboardInput함수에 점프 관련 키를 추가했습니다.
키보드 입력과 관련된 글은 아래 글에 정리되어 있습니다.
[WinAPI] 키보드 입력 (WM_KEYDOWN, WM_KEYUP, GetAsyncKeyState)
VK_MENU는 왼쪽 Alt키를 지정하는 값입니다.
해당 값을 변경하면 임의의 점프 키를 할당할 수 있습니다.
코드를 상세히 분석하면 아래와 같습니다
- inputFlag는 키다운 상태에서 지속적인 호출이 되지 않도록 하기 위한 플래그입니다.
- curJumpCount와 maxJumpCount는 MyApp의 클래스 변수입니다.
- 위 두 JumpCount는 한 번에 여러 회의 점프를 가능하도록 하는 값 입니다.
2. Update함수 수정
Update함수의 충돌 판정 코드를 위 기능에 맞춰 수정해야 합니다.
우선, 기존 코드는 아래와 같습니다.
...
D2D1_RECT_F t = myCharacterBitmap->GetBitmapRect();
for (auto& i : ground) {
if (IsCollision(t, i)) {
downSpeed = 0;
deltaDown = 0;
}
}
...
위 코드의 문제점은 다음과 같습니다
- ground가 많아질 경우, 연산량이 커질 수 있습니다.
- 낙하속도가 클 경우, ground를 통과할 수 있습니다.
우선 첫 번째, 연산량 부분입니다.
위 코드는 좌우 이동이 아닌, 상하 이동에 관한 충돌만 판정합니다.
따라서, 현재 플레이어 캐릭터의 위치에서 착지할 수 있는 플랫폼에 대한 계산만 수행하도록 제한할 수 있습니다.
구체적으로는 다음과 같습니다.
for (auto& i : ground) {
if (!(i.left <= t.right && i.right >= t.left)) continue;
...
}
위 조건문은 좌우 충돌 판정 코드와 동일합니다.
이미지의 좌우가 걸리지 않았을 경우, 해당 플랫폼에는 착지할 수 없습니다.
따라서, 충돌과 관련된 계산이 불필요합니다.
다음은 낙하속도입니다.
낙하속도가 클 경우, 속도를 줄이는 방법을 생각해볼 수 있습니다.
구체적으로, 낙하속도와 플랫폼까지의 거리를 비교하여, 속도를 보정하도록 하겠습니다.
코드는 다음과 같습니다.
for (auto& i : ground) {
...
float groundDist = abs(i.top - t.bottom);
if (groundDist <= deltaDown) {
deltaDown = groundDist;
curJumpCount = 0;
downSpeed = 0;
}
}
기존 IsCollision함수를 이용한 코드를 제거하고 코드를 새로 추가했습니다.
위 코드의 groundDist는 캐릭터와 바닥 사이의 거리입니다.
이미지가 다음 프레임에 이동할 거리는 deltaDown입니다.
두 값을 비교하여, deltaDown이 클 경우 이미지가 플랫폼을 통과한다는 것을 알 수 있습니다.
이 경우 이미지는 groundDist만큼만 이동하여 착지할 수 있도록 합니다.
추가적으로, 착지 시 필요한 연산 (하강속도 초기화, 점프 횟수 초기화)을 수행합니다.
중력이 이미 구현되었기 때문에, 점프에 대한 구현이 간단했습니다.
이번 글에서 사용된 코드의 전문은 아래 Github에서 확인하실 수 있습니다.
GitHub - ruru14/WinapiStudy: WinAPI및 DirectX를 공부하며, 간단한 운동 법칙을 적용해봅니다.
WinAPI및 DirectX를 공부하며, 간단한 운동 법칙을 적용해봅니다. Contribute to ruru14/WinapiStudy development by creating an account on GitHub.
github.com
이번 글이 도움이 되셨기를 바랍니다.
감사합니다.