F.R.I.D.A.Y.

물리엔진 - 좌우 이동 본문

DEV/Direct2D

물리엔진 - 좌우 이동

F.R.I.D.A.Y. 2021. 5. 14. 01:47
반응형

 바로 전 시리즈에선 바닥 구현을 했습니다. 좌우로만 이동하면 이제 제대로 된 캐릭터 이동이 가능해지겠네요.

 


프로젝트 업데이트

 이번 포스트부터는 기존 제공한 프로젝트와 해당 프로젝트로 구성한 중력구현 등을 포함한 버전의 새로운 프로젝트를 사용합니다. 프로그램 사용이 보다 접근성이 높아야 흥미를 느낄 수도 있을것 같아 몇가지 기능을 추가했으니 참고해주세요.

PhysicsEngine.zip
0.01MB

 본 파일에 추가된 기능/소스코드는 다음과 같습니다.

  • 마우스 좌측버튼 및 마우스 끌기로 블럭 형성이 가능합니다.[# 이렇게 만들어진 블럭에 대해서도 중력 구현 및 충돌의 영향을 받도록 구성해 캐릭터가 그 위에 놓였을 때 더이상 내려가지 않습니다]
  • 마우스 우측버튼으로 형성된 블럭을 삭제할 수 있습니다.[# 프로그램 생성부터 나온 하단의 메인 블럭은 지우지 않습니다.]

 

캐릭터 조작

 캐릭터는 좌/우로 이동합니다. 이제 그 과정을 만들어보도록 하겠습니다. 키 입력에 대한 정보는 keyState 멤버로 바인딩되어 있으므로 키 입력과 관련해 수정을 할 필요는 없습니다.

 

 좌측 이동은 x값이 감소하는 방향입니다. 마찰력이 100%인 상태. 즉, 키 입력을 해제했을 때 즉시 멈추는 밀리지는 현상이 없는 상태로 구성할것입니다.

 

 Calculate 메서드에 아래 내용을 추가합니다.

static float moveSpeed = 5.f;

 

 그 다음, 점프 구현 다음 영역에 아래와 같은 코드를 입력해줍니다.

	if (keyState[VK_LEFT]) moveSpeed = -5.f;
	else moveSpeed = 0.f;

 하지만 이렇게 코드를 구성하면 제대로 동작하지 않을겁니다. 좌우측 이동은 서로 연관되어 있습니다. 때문에 좌우측을 연계해서 판단해주어야 합니다.

 

 우리가 고려해야할 사안은 이겁니다.

  • 좌우측 버튼이 함께 눌렸을 때는 움직이지 않을것
  • 좌우측 버튼중 하나라도 눌리지 않았을 때 움직이지 않을것
  • 좌측 버튼이 눌리면 x값을 뺄 것
  • 우측 버튼이 눌리면 x값을 더할 것

 이 때, 첫 번째 옵션과 두 번째 옵션은 합치는 것이 가능합니다.

	if (keyState[VK_LEFT] == keyState[VK_RIGHT]) moveSpeed = 0.f;
	else if (keyState[VK_LEFT]) moveSpeed = -5.f;
	else if (keyState[VK_RIGHT]) moveSpeed = 5.f;

 

 keyState[VK_LEFT]와 keyState[VK_RIGHT]의 값이 모두 0[# 키가 눌리지 않은 상태]이거나 1[# 두 키 모두 눌린 상태]이면 moveSpeed는 0이 되고, 이 경우가 아닌 경우 각 상황에 맞게 moveSpeed를 옮겨줍니다.

 

 그리고 마지막 rcCenter에 x값에 moveSpeed를 더해줍니다.

rcCenter.x += moveSpeed;

 

최종 코드

 이렇게 구성하면 이제 좌우 이동이 가능한 캐릭터를 구성할 수 있습니다. 이동 속도는 moveSpeed 값을 수정해 조절할 수 있겠네요.

void MainWindow::Calculate()
{
	static float gravity = 4.3f;
	static float dropSpeed = 0.f;
	static float moveSpeed = 5.f;
	if (canJump && keyState[VK_SPACE]) {
		dropSpeed = -30.f;
		canJump = false;
	}
	else {
		dropSpeed += gravity;
	}

	if (keyState[VK_LEFT] == keyState[VK_RIGHT]) moveSpeed = 0.f;
	else if (keyState[VK_LEFT]) moveSpeed = -10.f;
	else if (keyState[VK_RIGHT]) moveSpeed = 10.f;

	if (dropSpeed >= 0.f) {
		for (size_t i = 0; i < cGround; ++i) {
			if (!(ground[i].left < rcCenter.x + rcSize.width/ 2.f && 
            	rcCenter.x - rcSize.width / 2.f < ground[i].right)) continue;

			if (ground[i].top < rcCenter.y + rcSize.height / 2) continue;

			if (abs(ground[i].top - rcCenter.y - rcSize.height / 2) < 0.001f) {
				dropSpeed = 0.f;
				canJump = true;
				break;
			}

			if (rcCenter.y + rcSize.height / 2 + dropSpeed > ground[i].top) {
				float gap = ground[i].top - rcCenter.y - rcSize.height / 2.f;
				dropSpeed = gap;
			
			}

		}
	}

	rcCenter.x += moveSpeed;
	rcCenter.y += dropSpeed;
}

 

다음 예고

 영상을 보면 만들어진 블럭 위에 있을 수는 있지만, 블럭 위에 존재하지 않는다면 지나다닐 수 있네요. 약간 맞지 않는 것 같습니다. 그래서 다음번엔 블럭을 지나치지 못하도록 만들어보겠습니다.

 

# index

728x90
반응형

'DEV > Direct2D' 카테고리의 다른 글

지뢰찾기  (0) 2021.06.28
물리엔진 - 벽 충돌 part2. 좌우 벽 구현  (0) 2021.05.14
물리엔진 - 점프 구현하기  (0) 2021.05.13
물리엔진 - 벽 충돌 part1. 바닥 구현  (0) 2021.05.11
물리엔진 - 중력 구현 안정화  (0) 2021.05.10
Comments