본문 바로가기
프로젝트

마리오 게임 모작

by Jini_Lamp 2024. 4. 22.

개발 기간: 2023년 11월 ~ 12월

사용 도구: Win32 API, VS, C++

이메일: jini031104@naver.com

git 주소: https://github.com/jini031104/MARIO_GAME

 

GitHub - jini031104/MARIO_GAME

Contribute to jini031104/MARIO_GAME development by creating an account on GitHub.

github.com

 

구현 목표

  • 마리오 게임의 기본적인 움직임
  • 캐릭터 이동을 통한 맵 이동
  • 점프를 통한 굼바 사냥
  • 간단한 엔딩 에니메이션
  • 랭킹 리스트

 

 

 

캐릭터 움직임

캐릭터의 움직임을 위해 본 컴퓨터에서 1초당 약 65fps인 초당 프레임 함수를 구현했습니다.

해당 함수를 통해 마리오와 굼바의 속도를 조절하였습니다.

초당프레임 구현
마리오의 움직임

 

 

 

맵 구현

화면 크기: 640 * 480

16px 타일 총 40개 필요.

 

정확한 맵 제작을 위해 엑셀을 활용하여 대략적인 지형을 설정했습니다.

마리오 게임 맵

 

캐릭터가 움직일 때 타일을 움직여 앞으로 나아가는 느낌을 내는 것입니다. 이때, 화면 밖으로 잘려나간 타일은 다음에 등장할 타일의 위치로 이동합니다.

타일 이동 알고리즘

 

하지만 구현 결과, 이 경우 화면의 양 끝에서 끝에서 타일이 깜빡이는 현상이 보입니다. 이는 타일이 움직이면서 왼쪽의 타일이 오른쪽으로 이동하는 사이에 발생하는 빈 공간때문에 생기는 현상입니다.

아래 영상은 캐릭터가 오른쪽으로 향했을 때 발생하는 문제점입니다. 해당 문제점은 캐릭터가 왼쪽으로 향했을 때에도 발생합니다.

타일 이동 문제 발생 동영상

 

이를 해결하기 타일을 40개에서 41개로 늘렸으며, 첫번째 타일을 화면의 시작부분을 (0, 0)이 아닌 (-16, 0)으로 초기화하였고, 두번째 타일을 (0, 0)으로 설정하였습니다.

즉, 첫번째 타일은 미리 화면 밖에서 대기하고 있다 두번째 타일이 화면 밖으로 나오면, 밖에 있던 첫번째 타일이 이동하는 방법입니다.

수정된 알고리즘

 

코드는 아래와 같습니다. 한 방향으로 쭉 향할 경우와 다시 되돌아오는 경우를 예상하여 타일의 위치값을 계산하였습니다.

타일 이동 코드

 

이때 사용되는 nBgX는 맵의 X축 위치입니다. 이는 곧 nBgX  == 0 은 아직 맵이 움직이지 않았음을 의미하며, 마리오가 오른쪽으로 움직일 수록 맵은 왼쪽으로 향하게 되어 X축 위치 값이 마이너스(-)로 향하게 됩니다. -640이 되면 다시 0부터 시작되어 쳇바퀴처럼 맵을 연속적으로 보여주게 됩니다.

배경 이동 코드

 

또한 수치에 차이를 주어 타일과 배경이 움직이는 속도를 다르게 했습니다. 이는 원근감을 위한 것으로, 비교적 멀리 있는 구름 풍경이 느릿하게 보이는 효과를 냅니다.

원근감을 위해 타일과 구름의 속도가 다르다

 

점프

점프 수학 공식은 다음과 같습니다.

Y = (b * x) - (-a / 2 * x * x)

  • a: 중력 가속도
  • b: 초기 점프 속도
  • x: 점프 시간
  • y: 점프 속도

하지만 이 경우에는 점프가 끝없이 올라가는 문제가 생깁니다. 물론 점프 수치를 수정하면 해결되긴 하지만, 제가 원하는 방식은 아니었습니다. 왜냐하면 공식을 하나만 사용할 경우 점프 값이 점점 커졌다가 점점 느려지는데, 저는 처음부터 빠른 속도였다, 점점 속도가 줄어드는 것을 원했기 때문입니다.

 

그래서 생각한 해결책은 점프 공식을 2번 사용하되, 다른 한쪽의 수치를 조금 더 크게 만든 것입니다. 그리고 큰 것에서부터 작은 것을 빼 나온 결과값을 사용하면 원하는 결과를 얻을 수 있었습니다.

왼쪽과 오른쪽(점프 공식 1회 사용) 오른쪽(점프공식 2회 사용)

 

점프를 구현했으면 다음은 점프를 통해 허공 지형에 올라갈 수 있는 방법입니다.

 

Win32 API에선 Unity처럼 충돌 감지나 물리 운동 시스템이 없습니다. 따라서 허공 지형을 그릴 때, 그 위치값을 플레이어에게 넘겨 주어 해당하는 위치에 캐릭터가 존재할 경우 충돌했음을 알려주는 코드가 필요합니다.

허공 지형 생성 및 해당 위치값 전달

 

먼저 GroupMapPain()를 통해 허공 지형을 그립니다. 각각의 매개변수는 (시작점, 높이, 연속된 블록의 개수) 입니다. 그렇게 설정된 위치값을 SetObstacleXY()를 통해 플레이어에게 전달해줍니다.

 

아래는 점프 코드입니다. SetObstacleXY()를 통해 얻은 값으로 충돌 감지를 해주고, 해당 구역 내에 점프를 할 경우 허공 지형에 착지할 수 있는가 없는가를 확인합니다. 

점프 코드

 

 

 

굼바 사냥

플레이어 캐릭터와 굼바는 같은 부모 클래스를 공유합니다. 그중 부모 클래스가 가지고 있는 충돌 체크를 통해 굼바를 사냥할 수 있습니다.

캐릭터 클래스 구조

 

플레이어 캐릭터와 굼바의 충돌을 체크하는 과정은 다음과 같습니다.

캐릭터 충돌 알고리즘
캐릭터 충돌 구현

 

 

 

몬스터 생성

생성 코드에 따라 몬스터를 생성합니다. 이는 추후 새로운 몬스터가 추가될 가능성을 염두한 것입니다.

 

 

 

애니메이션

자연스러운 움직임을 위해 더블 버퍼링을 사용하고, 출력 좌표를 움직여 캐릭터 이미지를 연속적으로 보여주어 애니메이션 효과를 냅니다.

애니메이션 원리

 

깃발에 도착하면 엔딩입니다. 남은 시간을 점수로 전환 후, 점수 및 이름 저장 화면으로 넘어갑니다.

엔딩 애니메이션

 

 

 

랭킹 리스트

엔딩 이후 플레이어의 이름을 입력합니다. 점수에 따라 순위가 바뀌며, 내림차순으로 정렬되었습니다.

랭킹 리스트
점수 및 이름 저장