6.5 오리지널 게임처럼 만들어 보기
Last updated
Last updated
기존 게임을 오리지널 게임처럼 바꾸는데는 게임 운영 알고리즘 자체는 바꿀게 없고, 기존 게임무대 배경은 없에고, 이후 단지 게임의 배우였던 공, 반사판, 블록더미를 코딩으로 직접 만들고 그리는 부분만 바꾸면 되는 과정이다. 그래서, 각각을 하나씩 어떻게 코딩으로 그릴 수 있는지 살펴보도록 하겠다. 먼저 코딩의 이해를 돕기 위해 우리가 만들게 될 게임의 최종결과를 미리 살펴보자.
제일 그리기 쉬운 것부터 살펴보자. 반사판은 그냥 직사각형(Rectangle) 하나이다. 파이게임에서 직사각형을 만들고 그 내부를 특정(여기서는 빨강)색으로 채워그리는 코드는 다음과 같다.
사각형 Rect 클래스(class)
Rect(화면상의 위치할 x좌표, 화면상의 위치할 y좌표, 가로길이, 세로길이)
우리는 지난 절을 통해 공의 본질이 기본적으로 (정)사각형 곧 Rect 라는 것을 알았고, 따라서 공 역시도 위에서 만들어본 반사판처럼 Rect 객체로 생성해야 한다. 이것을 이해한다면, 공을 만드는데 어려움은 전혀 없다. 다음의 코드를 통해 만들 수 있다.
다행이도 Rect 형태의 공일지라도 우리 눈에는 원처럼 보일 수 있게 그려주는 함수가 준비되어 있다. screnn.draw.filled_circle 메소드에 원의 중심좌표(공의 rect객체가 만들어지는 순간 center값은 자동으로 생성됨)와 반지름, 그리고, 원을 채울 색상값을 넘겨주면 된다.
다만, 공을 Rect로 만들 경우, 한 가지 추가로 고민할게 있는데, 공과 반사판 충돌검사는 천상 Rect간 출동로만 확인할 방법이 없게 된다는 것이고, 이 경우, 지난 시간에 언급했던 자세히 보면 공과 반사판이 정확히 닿지 않았는데도 충돌검사상 닿은 것으로 판단해 공을 반사시키는 것에 대한 버그를 기억할 것이다. 이 부분을 어떻게 해결하면 좋을까? pgzhelper 모듈을 떠올릴텐데, Rect된 공은 이미지가 아니라서, Actor로 만들 수도 없어서 해당 모듈의 도움도 요원한 상태이다.
이런 경우, 공의 충돌검사의 기준이 될 Rect와 우리 눈에 보이는 공의 원형외관의 관계설정을 통해 해결의 아이디어를 만들 수 있다. 우리는 기존에는 공의 밖을 둘러싸는 Rect에 대한 생각만 했지, Rect가 공의 안쪽에 있을 수도 있다는 것이다.
Rect를 공의 안쪽에 위치시켜 반사판과 충돌검사를 하게 되면 최소한 우리 눈에 공이 닿지도 않았는데, 반사되는 것으로 보이는 버그는 수정할 수 있게된다. 해당 내용을 반영하여 코드를 수정하는 다음과 같다. 참고로 sqrt 는 우리가 수학에서 배운 루트(root)의 의미이고, 이를 코딩으로 표현하려면 math 라이브러리를 import해 sqrt 함수를 사용해 계산해야 한다.
블록더미 코드도 어려울 것은 없다. 간단히 기존코드에서 블록 한장한장을 객체로 생성할 때, 이 블록을 Rect로 생성하면 되는 것이다. 이를 코드로 구현하면 다음과 같다.
여기서 블록의 가로길이는 기존에 이미지로 그릴 때와는 달리 100픽셀이 아니고, 96픽셀인 이유는 이웃하는 블록간의 서로 빈틈없이 블록을 연이어 그려 붙이면 블록더미 안의 블록 하나하나를 구분할 수 없게 보이기 때문에(맨 위의 게임의 최종결과 화면 참조), 각각의 블록 좌우로 2픽셀씩 아무것도 없는 빈 여유공간을 주기위해서 이다. 이 부분은 블록을 그려야 하는 위치선정시에도 고려해야 하는데, 따라서, block_col * 100 + 2 라고 추가로 2를 더한 것은 그 2픽셀의 빈공간을 넘어서 그 다음 블록을 그려야하기 때문이다. 이 부분을 잘 이해했다면, 블록의 세로길이가 25픽셀 아니고, 23픽셀인 이유도 마찬가지이고, 블록간의 세로방향의 빈공간은 2픽셀의 여유를 갖는다.
기존에 이미지형 무대 배경화면은 오리지널 게임에서는 없기 때문에 해당 코드는 제거하고, 대신에 등장 배우들을 그리기 전에 이전 그려진 것을 깨끗이 지우고 그 위에 그려야만 이전 잔상과 겹치지 않게 때문에 무대배경은 화면을 지우는 다음 코드로 대치한다.
이제 위에서 각각 그렸던 게임배우들을 다 종합한 전체 코드를 살펴보자. 서두에 언급했던 것처럼 게임 운영 알고리즘 자체는 바뀐게 없고, 단지 무대배경을 없에고, 게임의 배우들였던 공, 반사판, 블록더미를 코딩으로 직접 만들고 그리는 부분만 바뀌어져 있다.
이번 블록격파 게임은 여기까지 제작해 보는 것으로 종료하겠다. 그러나, 게임성을 더 높이기 위해 더 추가해 볼 기능들을 얼마든지 더 있다. 예를들어 게임의 시작과 끝까지 공의 속력변화가 없어서 게임이 쉽다고 느껴지고 도전정신이 살아나지 않는 것을 방지하기 위해 격파된 블록의 수가 많아지면 많아질수록 또는 반사판으로 공을 받아낸 횟수가 많아지면 많아질수록 특정시점을 기준으로 공의 속력을 조금씩 높여가는 방법이 있겠다. 그밖이 단순이 공을 받아내는데 것으로 만으로는 사용자의 자유도가 적은 편이라 흥미가 떨어질 수 있으니, 사용자가 공을 반사판의 좌우측 특정 부분으로 의도적으로 받아내느냐에 따라 공의 반사각도 변화를 받게하는 방법을 추가하는 것도 게임성을 높일 수 있는 좋은 아이디어가 되겠다. 추가 기능구현에 대한 과제는 여러분에게 맡겨놓겠고, 여기까지 공부하느라 여러분들도 수고가 많았다.
앞으로 몇 개의 게임을 더 만들어보면서 제작과정에서 만나는 문제상황을 돌파할 알고리즘을 답을 보기 전에 먼저 스스로 고민해 보고, 그 알고리즘을 텍스트코딩 기법 안에 어떻게 해결해 나가는 것까지 내것으로 소화해 나간다면 어느새 텍스트코딩이란게 내가 살아가면서 만나게 되는 다양한 세상의 문제해결을 위해 두려움 없이 꺼내어 쓸 수 있는 내 소유의 도구 또는 스킬셋(skillset) 중에 하나로 자리잡게 될 것이다. 그날이 올 것을 목표하고 기대하며 다음게임으로 넘어가 보자!
여기서 Rect(사각형) 클래스로 생성한 Rect객체는 파이게임제로에서는 내장객체처럼 사용할 수 있기 때문에 어떤 추가적인 모듈, 라이브러리의 import 없이도 사용했다는 것을 알 수 있다. 생성한 사각형(rect) 객체의 내부를 특정 색상으로 채우는 filled_rect 메소드는 파라미터로 내부를 칠할 색상을 지정하고 있다. 색상값은 빛의 3원색(빨강, 초록, 파랑)의 세기값(최소 0 ~ 최대 255)의 조합으로 표현하며, 연이은 3원색의 각각의 광원값을 (Red 광원값, Green 광원값, Blue 광원값) 형태의 데이터형태로 제공해야 한다. 색생표현법에 관한 내용은 에서 자세히 설명하였으므로 해당 부분을 참고하거나, 워낙 인터넷에 정리된 자료가 많은데 이 블로그를 참조할 수 있다.