9.1 절차지향형으로 개발하기 1
Last updated
Was this helpful?
Last updated
Was this helpful?
바로 아래 화면의 우리가 만들게 될 게임의 최종 결과물을 먼저 보고나면 코드 이해가 훨씬 쉬울 것이다. 다만, 이번 과의 맨 서두에서 언급했듯이 난이도 조절을 위해 오리지널 게임의 기능동작 전체 다를 구현하지 않을 예정이고, 대신 이 게임을 두 가지 프로그래밍 패러다임(, ) 각각을 사용한 두 가지 버전으로 만들어 볼 예정이다. 먼저 이전 절에서 예고했듯이 다시한번 나만의 객체를 만들고 활용하는 것으로 배워 봄으로써 이제는 보편화되어 사용되는 객체지향형이 기존의 절자지향형과 어떠한 현격한 차이를 가지는지를 한번 더 명확하게 이해하는 것이 이번 장의 과업이라고 할 수 있겠다.
우리는 이미 5-8장 통해 4개의 게임제작을 소화했기에 이미 튜토리얼 수준을 넘어섰다 볼 수 있다. 따라서, 이번 장에서도 이미 설명한 기본적인 내용에 대한 자세한 중복설명없이 빠르게 핵심적인 코딩에 대한 설명 위주로 진행하도록 하겠다.
참고로 이번 게임제작에 필요한 이미지, 사운드 등의 리소스들은 에서 다운로드 할 수 있으며 게임에 필요한 이미지 파일들은 코드에서 사용한 이름 그대로 imgaes 폴더에 이미 저장되어 있고, 효과음은 sounds 폴더에 저장되어 있다고 간주하고 시작하겠다. 또는 를 사용 중이라면 뮤 에디터의 작업 디렉토리인 (사용자계정)\mu_code\examples\pygame_zero 안에서 복사해 올 수 있다.
우선은 먼저 절차지향형으로성의 개발을 시작해 보자. 배틀시티게임은 이전에 만들어 본 블록격파 게임과 트윈비 게임을 섞어놓은 게임과 같다.
벽더미의 구성을 자세히 살펴보자. 벽 한개의 크기는 가로세로 50픽셀(WALL_SIZE)의 정사각형이다. 이 벽이 가로세로 800x600픽셀 크기의 화면에 몇 개가 들어갈지는 WIDTH / WALL_SIZE 와 HEIGHT / WALL_SIZE 계산으로 쉽게 알 수 있다. 궁금한 점은 왜 그 계산식을 int()라는 내장함수에 넣어 사용했는가인데, 그 이유는 파이썬에서의 나눗셈 연산은 결과를 항상 실수형(float)으로 값을 되돌려 주기 때문이다. 우리는 그 연산결과를 다시 range() 내장함수에서 사용할 건데, 이 함수의 인자값(argument)은 또 항상 정수형(integer)을 넘겨주어야 한다. 결국 int() 함수의 목적은 실수값을 정수값으로 변환해 주는 함수인 것이다.
34번 라인에서 전체 세로열에서 2를 뺀 것은 위의 게임결과 화면에서 보면 알 수 있듯이, 화면 전체에 전부 벽을 놓을 게 아니라 적 탱크(enemy)가 위치할 화면 맨 윗 열(row)와 내 탱크(tank)가 위치할 화면 맨 아래 하단의 한 열(row)을 비워두기 위한 목적이다. 그리고, 17번 라인은 이 게임이 벽을 다 부시는 블록격파(?) 게임은 아니고, 상대 탱크를 포로 맞춰 없에는게 과업인 게임에서 일부러 화면전체에 벽을 가득채우지 않고, 군데군데 랜덤하게 비워두기 위해서 넣은 코드이다.
왜 지연이 필요한가? 그렇다. 근본적인 이유는 트윈비에서도 유사한 상황이 있었는데 바로 update 콜백함수의 호출속도 (60FPS) 때문이다. 따라서, bullet_delay_cnt 는 대포알의 너무 빨리도 많이도 나가지 않게 하기 위한 목적이고, enemy_move_cnt 는 적 탱크들은 사람이 조작하는게 아니라 컴퓨터에 의해 자동조작 운행이 될 예정인데 이 때 너무 빠른 속도로 운행되지 않게 하기 위한 목적이다. 결국, 대표알이든 탱크 움직임이든 게임성을 저해하지 않게 적당해야지 대전형 게임에서 어느 한쪽이 지나친 우위를 점하면 게임성이 떨어져 재미가 없어진다는 건 누구나 아는 상식이다.
마지막으로 컴퓨터에 의한 적 탱크의 자동조정의 아이디어는 3가지 행동(움직하기, 방향전환, 포쏘기)을 무작위화(램덤화)하는 것이고, 이 때 움직이는 시간에 대해서도 랜덤화함으로써 좀 더 변칙적인 행동을 유도한다. 그럼, 이제 다음 절에서부터 우리의 3가지 사용자 함수의 구현체를 구체적으로 채워보도록 하겠다.
위의 37번째 라인까지 코드는 게임무대의 배우객체들을 생성하는 것이다. 장애물 벽더미(walls), 주인공 탱크(tank)와 3대의 적 탱크(enemies)를 생성한다. 벽더미를 만드는 부분은 기존의 블록격파 게임에서 블록생성 부분과 크게 다르지 않다. 다만, 벽더미의 생성 알고리즘이 일부 다를 뿐이다.
현재는 절차지향형으로 개발하기로 했기때문에 필요한 기능들을 함수화(functionalize) 할 필요가 있다는 것을 배웠다. 이번 게임도 함수화를 진행해보자. 코딩에서 항상 염두해 두어야 할 점은 나와 남을 위해 가독성이 좋고, 추후 수정에 대비한 유지보수(maintenance) 측면을 늘 고려해야 한다. 사실상 함수도 그러한 이유로 출연했다고 할 수 있다. 함수의 주목적은 코드중복을 줄이는 것으로 이전 트위비 게임에서는 안타깝게도 공통 기능적으로 함수로 묶을 만한게 마땅지 않았지만, 이번 배틀시티 게임에서는 그 목적에 부합하는 함수 3개(move_player, fire_bullets, collide_bullets)를 만들 수 있다.
다음 절부터 위에 언급된 3개 함수의 구현체를 만들어보기로 하고, 지금은 그 함수들을 제외한 나머지 코드들에 대해 더 검토해보자. 지금까지 모든 과정을 함께 공부해 온 여러분의 실력상 대부분은 이전에 이미 배웠던 것들의 약간의 변형이라 찬찬히 드려다보면 대부분 이해가 될 것으로 믿는다. 약간 낯선 부분이 있다면, bullet_delay_cnt, enemy_move_cnt 두 변수에 관한 것일 것 같다. 두 변수값은 다시 BULLET_DELAY, ENEMY_MOVE_DELAY 이란 (Macro)값으로 채우고 있다(79, 91라인). 변수명이나 매크로명에서 유추할 수 있듯이 뭔가 의도적으로 코드실행의 지연(delay)을 주기 위한 것으로 유추할 수 있다.