게임 개발자를 향해

[OpenGL] OpenGL을 이용한 "2D Stacking game" 본문

그래픽스/OpenGL

[OpenGL] OpenGL을 이용한 "2D Stacking game"

뿌단이 2023. 3. 12. 23:39

 
안녕하세요 뿌단이입니다!
 
예전에 대학에서 배웠던 그래픽스 OpenGL 지식을 토대로 창작과제 프로젝트가 있었습니다.
 
이번엔 OpenGL 포스팅에서 만든 2D 그래픽 환경을 기반으로 게임을 하나 만든 게임을 리뷰해 보겠습니다.
 
 



제가만든 게임은
바로 탑 쌓기 게임입니다!

Github 주소 클릭!
 

대학 수업에서 OpenGL 2D를 배운 이후 이 기능들만으로 무엇을 만들 수 있을까 고민했습니다.
 
그래서 간단한 그래픽으로도 만들 수 있는 게임들 중 Stacking game을 선택했습니다.
 
이 게임은 옛날 플래시 게임, 안드로이드 개발 초기 시에 킬링타임으로 즐길 수 있었던 고전게임입니다.

 
 

게임의 규칙은 아래와 같습니다.


    1. 하늘에서 블록이 좌우로 떠다닌다.
    2. 상호작용을 하면 탑에 블록을 쌓을 수 있다.
    3. 만약 어긋나게 쌓았을 시 어긋난 만큼 블록이 잘려나간다.
    4. 그래서 계속 어긋나게 쌓을 때마다 점점 쌓을 수 있는 범위가 줄어들게 됩니다.



이 게임은 위 규칙을 기반으로 블록으로 탑을 높은 층까지 쌓는 것이 목표인 게임입니다.
결국 오브젝트를 탑 위에 쌓지 못했을 경우, 게임 오버가 됩니다.

 

1. 게임 구조

1. 바닥
2. 블록 및 키다운
3. 카메라
4. 점수

 

 

이 게임에서의 기능을 위와 같이 4가지로 분류했습니다.


1. 바닥

 

바닥과 블럭을 따로 나눈 이유는 첫 블록은 움직이지 않고, 가운데에 고정되어 있어야 합니다.
그리고 그 블럭의 x축을 기준으로 블럭이 잘려야 하기 때문에 구현부에 바닥을 따로 나누었습니다.
 

 


2. 블록 및 키 다운

바닥 위에부터 쌓여지는 오브젝트입니다.
키 다운 시 블록이 탑에 쌓이고 어긋난 부분은 잘리게 됩니다.

잘린 이후 새로 쌓아야 하는 블록이 생성됩니다.
블록의 시작 위치는 왼쪽 오른쪽 번갈아 나오게 구현했습니다.
그리고 블록이 어떤 지점에서 멈추고 반대 방향으로 이동해야합니다.
 

 

 - 블록 좌표 배열 -

블록을 출력하려면 블록의 좌표와 길이를 저장해야 합니다. 쌓이면 쌓일 때마다 새로운 블록을 만들어야 하고, 쌓인 기존 블록들도 함께 출력돼야 합니다.

그럼 쌓이는 블록들의 좌표와 새로 만들어지는 블록들의 좌표들을 저장할 공간이 필요하겠죠?

그래서 해당 좌표들을 저장할 2차원 배열을 만들었습니다.
 
먼저 첫번째 블럭의 변수들을 변경시키다 키다운 입력이 들어오면 해당 좌표를 배열에 저장하고
다음 배열에 좌표를 저장할 준비를 합니다.
 

 - 블록 이동 -

블록을 이동하려면 해당 블록을 OnTimer() 함수로 주기적으로 좌표값에 상수값을 더해주면 됩니다. 이때 Timer의 주기와 상수값의 크기가 블록의 속도를 결정하게 됩니다. 그리고 Viewport 밖으로 블럭이 나가면 안되기 때문에 일정 거리 이동 시 방금말했던 상수값을 음수로 변경하여 블럭이 이동하는 방향을 바꿔줍니다.
 

 - 키 다운 -

키 다운이 될 때 마지막으로 쌓은 블록과 x좌표가 겹치지 않는다면 게임이 종료되고 겹친다면 쌓아야합니다.
그리고 만약 쌓인 블록과 어근난다면 그만큼 블럭이 잘리고 다음부터는 자르고 남은 만큼의 블록으로 게임을 진행해야합니다.
 

1. 키 다운이 발생하면 블록은 이동을 멈춥니다.


2. 현재 쌓으려는 블럭의 가장 최근에 쌓은 이전블록, 즉 이전 배열 값과 비교 합니다.
(이는 두 가지 경우로 나뉩니다.)


3. 블록이 어긋난 만큼 잘리고 다음 블록이 생성되어 움직이게 됩니다.

 

첫 번째 경우 : 왼쪽이 어긋난 경우 (위 사진과 반대인 경우)
두 번째 경우 : 오른쪽이 어긋난 경우 (위 사진과 같은 경우)

 

알아야 할 것은 블럭들의 기본 좌표는PosX1 PosX3 위치에서 시작한다는 것입니다.

해당 규칙을 기반으로 아래 식이 완성됩니다.

(자세한 개념 : 링크 클릭! )

 


[첫 번째 경우]

1. PosX3PosX1로 변경해준다.

PosX3 = PosX1

2. 잘린만큼 PosX4의 값을 빼줍니다.

PosX4 -= PosX1 - PosX3


[두 번째 경우]

이 경우는 조금 복잡합니다.

      PosX2 = PosX1 + BlockSize
      PosX4 = PosX3 + BlockSize
 
PosX2PoxX4도 좌표이기 때문에 PosX1과 PosX3에 블록의 X축 길이만큼 좌표값을 더해서 넣어주어야 합니다.
위 식을 이용하면 두 번째 경우 에서는 식이 아래처럼 변합니다.

 PosX4 = PosX2
      PosX3 + BlockSize = PosX1 + BlockSize

 

하지만 이런 식은 코드로 사용할 수 없기 때문에 PosX1를 이항하여 값에 BlockSize 값에 포함시켰습니다.
 
      BlockSize = PosX3 + BlockSizePosX1

 

이로서 위와 같은 식으로 어긋난 블록을 처리합니다.

정확한 코드는 깃헙을 확인해 주세요!

 

Github 주소 클릭!


3. 카메라

위 게임 영상을 보면 쌓일 때마다 카메라가 올라갑니다.
하지만 카메라 자체 개념을 배우지 않은 상태라 어떻게 표현할 지를 고민하다가 꼼수를 생각했습니다.
카메라가 아니라 쌓인 블록들의 y좌표를 내려버린다면?
Viewport의 시점이 올라가는 것처럼 보일 것입니다.
그래서 탑이 일정 개수로 쌓이면 쌓인 블럭들의 y좌표를 내려서 카메라가 올라가는 표현을 했습니다.
 


4. 점수

그냥 게임을 하면 재미 없으니까 몇층까지 쌓았다는 것을 알려즐 점수를 추가했습니다.
그냥 사각형만 출력할 수 있는 지금 이미지도 못넣는데 어떻게 숫자를 표현할까 고민했습니다.
생각한 결과 디지털 숫자를 쓰자는 생각을 했습니다.
 

 
일단 노트로 구상을 해보았습니다.
점수를 출력할 위치와 유닛 마다의 크기를 예상하여 위 그림처럼 유닛의 위치를 스케치 했습니다.
 

 - 유닛 정리 표 -

<유닛 번호매김>
0 → 가로 맨위    1 → 가로 중간    2 → 가로 아래
3 → 세로 왼쪽 위    4 → 세로 왼쪽 아래
5 → 세로 오른쪽 위    6 → 세로 오른쪽 아래
 
 
위 사진은 0 ~ 6의 숫자로 유닛을 구분하여 숫자마다에 쓰이는 유닛들을 정리한 표입니다.
만약 0을 만들기 위해선 유닛 1개 빼고 전부 출력해야 0을 표현할 수 있는 겁니다.
아래와 같이 배열을 생성했습니다.
 

 

 - 점수 규격 -

 

위 사진은 숫자의 비율과 좌표를 맞추기 위해서 임시적으로 가시화 했습니다.
나중에 변형을 고려해 위 규격 비율에 맞춰서 숫자의 크기가 지정되게 배열을 생성했습니다.
해당 규격의 위치와 크기에 따라서 점수의 좌표와 크기도 결정됩니다.
게임 플레이에서는 규격 출력 코드는 주석처리 합니다.

규격에 맞춰 유닛을 생성했습니다.
괜찮나요?
 

 - switch문, if문 코드 비교 -

이제 이것을 점수에 맞게 출력을 해야하는데
저에게 방법은 if문과 case문 두 개가 있었습니다.
처음엔 코드의 간결화를 위해서 if문으로 코딩했습니다.
 

 
if (score == "0 2 3 5 6 7 8 9" )
0번째 유닛을 출력해라
 
if (score == "2 3 4 5 6 8 9" )
1번째 유닛을 출력해라
 
if (score == "0 2 3 5 6 8 9" )
2번째 유닛을 출력해라
 
...
(생략)
 
 
이렇게 코딩을 한다면 출력을 하지않아도 되는 유닛을 출력해야하는지 아닌지를 검사해야합니다.
어차피 대단한걸 만드는 것도 아니고 큰 차이도 없을 테지만 조금이라도 속도를 줄이는 것도 중요하다 생각했습니다.

 
만약 switch문으로 작성하게된다면 아래와 같습니다.

 

 
너무 길어서 잘랐습니다..

 
코드 설명은 간단합니다! 숫자를 확인하고 그 숫자에 맞는 유닛만 출력하는 코드입니다!
만약 if문으로 썼다면 10의자리까지 합하여 if문 14개로 깔끔하게 끝났을 코드입니다.
switch문을 사용하니 코드가 길고 더러워 보이네요..
 
if문은 7개의 유닛을 전부 검사하지만, switch문은 각각의 case에 대해 비교연산을 하지 않기 때문에 숫자 하나만 검사하게 되니 체감은 안되겠지만 이론상 점수 출력부분에서는 7배 빨라졌을거라 생각합니다!
 


[ 작품 결과 ]

https://youtu.be/PiNPRnHT_dE

 

그래픽 바꾸는 방법을 알고있지 않아서 해당 프로젝트는 여기서 마무리 했습니다!

Github 주소 클릭!

[ 개발 후기 ]

예전 그래픽스 과제를 리뷰하려고 프로젝트를 꺼내보니 코드 구조가 조금 복잡한 것을 확인했습니다.
하여 리뷰를 하는 동시에 간단한 리팩토링을 했습니다.
역시 배우는 지식에 따라 코딩 스타일이 달라지는 것 같아요!
조금 더 숙련된 지금 리뷰하다보니 보이는 것들이 있네요..
 
 
 
 

아무튼 지금까지 Stacking Game 리뷰였습니다!
읽어주셔서 감사합니다!
 
 
 
 

 
 

'그래픽스 > OpenGL' 카테고리의 다른 글

[OpenGL 기초] 2D 환경 구축, 사각형 출력 및 이동  (0) 2023.02.16