스스로 만든 미로에 갇혀

스스로 만든 미로에 갇혀

1년 전쯤에, 저는 파이썬과 pygame을 이용하여 게임을 만들려고 했습니다.

원래의 목적은 목장이야기 코로보쿠르 스테이션evil farming game의 요소를 혼합한 자유도 높은 농사 시뮬레이터 게임을 만드는 것이었습니다. 그러나 실제 개발은 게임에 필요한 기본 요소(플레이어 이동, 농작물 시스템 등)를 만드는 데에서 중단되었습니다. 당시에는 어떤 코드가 좋은 코드인지, 어떻게 프로젝트를 잘 관리할 수 있는지 등을 전혀 알지 못한 채 무턱대고 코드를 작성했고, 그 결과 모래성 위에 모래성을 쌓으면서 스스로 잘 하고 있다고 착각했습니다.

​어느 선까지는 어떻게든 진행됐습니다. 그러나 결국 프로젝트의 복잡도는 혼자 관리할 수 있는 수준을 넘어서 버렸고, 결국 저는 프로젝트를 포기한 채 깃허브 한편에 1년 동안 방치해 놓았습니다.

그리고 오늘, 이 프로젝트를 다시 꺼내 분석해볼 것입니다.

들어가기에 앞서, 옛날 프로젝트를 파헤치도록 동기부여를 해준 동아리의 친구에게 감사를 표합니다. 의지할 문서도 없고 주석도 부실한 프로젝트를 분석하는 것은 그 자체로 큰 도전입니다. 프로그래밍의 입문자들이 이 글을 보고 교훈을 얻을 수 있도록 기술적 세부사항은 최소화하고, 코딩을 잘 모르더라도 읽기 쉽게 쓰려고 노력했습니다.

2.본격적 코드 분석

(참고:이 글에서는 파이썬 또는 pygame의 세부사항에 대해 다루지 않고, 코드의 추상적인 구조만을 설명합니다. 또한 구조의 설명에 필수적이지 않은 부분은 생략되었습니다.전체 코드를 보고 싶다면 여기를 참조하세요.)

2.1.파이게임 구조

이 프로젝트는 pygame에 기반하여 만들어졌으므로, 우선 pygame의 구조에 대해 살펴봐야 이 프로젝트를 이해할 수 있을 것입니다.

pygame 공식 사이트의 예제. 사진과 같이 크게 3개의 부분으로 나눌 수 있습니다.

pygame은 초기 설정-게임 루프-종료의 3단계로 이뤄집니다. 실제 '게임 플레이'에 해당하는 부분은 게임 루프 안에서 일어납니다.

2.2. main.py

이 프로젝트의 main.py 또한 전반적으로 이러한 구조를 취하고 있습니다. 우선 '초기 설정' 부분을 보겠습니다.

초기 설정 부분에서 입력 이벤트를 저장하는 eventList, pc(player character) 객체 및 매니저 객체를 담은 essential_pack을 만듭니다. 나중에 살펴보겠지만, 이 부분이 프로젝트의 설계 오류를 상징합니다.

게임 루프 안에서는, eventList에 한 틱 동안 발생한 모든 입력을 저장합니다. 이후 게임 상태의 업데이트 및 화면 그리기를 수행합니다.

2.3. pc.py

이 파일은 플레이어에 대한 코드입니다. 짐작할 수 있다시피 플레이어와 조금이라도 관련된 모든 코드를 몰아넣기에 좋은 곳이죠.

2.3.1 update

이 함수 하나에 몇 개의 기능이 들어 있을까요?

  1. 플레이어가 맵 바깥으로 벗어났는지를 검사합니다.
  1. 플레이어의 앞에 놓인 객체를 저장하는 용도의 변수들을 선언합니다.
  1. 플레이어가 앞으로 이동할 수 있는지 여부를 검사합니다.
  1. 여기서부터는 eventList 내의 입력을 처리합니다. 만일 입력이 방향키 중 하나라면 그 방향으로 움직입니다.(분량상 접기 처리한 나머지 3개의 elif문도 move, mapMamager를 통해 호출하는 메소드만 다르고 거의 동일한 구조를 가지고 있습니다.)
  1. 입력이 F키라면 인게임 정보를 보여줍니다. 이 기능은 디버그용 print문만 있는 더미로 구현되어 있습니다.(print문의 출력은 콘솔에만 출력되고 게임 화면에는 영향을 미치지 않습니다.)
  1. R키는 npc와의 상호작용 버튼입니다. mapManager를 통해 맵에 있는 npc 정보를 불러오는 것으로 보입니다.
  1. C키는 아이템 버리기 버튼입니다. throwing 함수를 호출합니다.
  1. E키는 '상호작용' 버튼입니다. 플레이어가 어떤 아이템을 들고 있는지, 플레이어의 앞에 무엇이 있는지 등의 상황에 따라 다른 상호작용이 발생하는 가장 복잡한 버튼입니다. 우선 들고 있는 아이템의 이름을 '_'를 기준으로 파싱하여 문재열 배열로 저장합니다.
  1. 만일 앞에 문이 있다면 문을 통해 이동합니다. target_door[0][0]은 문의 목적지를 가리키는 것으로 추정됩니다.
  1. 들고 있는 아이템의 0번째 단어가 tool이라면 도구를 이용한 상호작용을 수행합니다. 각 상호작용은 도구의 '_able' 속성(도구가 어떤 작업을 할 수 있는지 여부)과 맵의 소유자인지 여부(자신 소유의 맵에서만 도구 사용 가능)를 검사한 뒤 수행됩니다.
  1. 들고 있는 아이템의 1번째 단어가 seed라면 이를 심습니다.
  1. front(플레이어의 앞을 나타내는 객체), inventory를 업데이트 후 rect.x/y를 갱신합니다. 이 변수는 플레이어의 위치를 나타내는 것으로 추정됩니다.

보다시피 하나의 함수에 무려 12개의 기능이 구현되어 있습니다. 이렇게 한 함수가 너무 많은 일을 하게 된다면 함수의 목적과 기능을 파악하기 어려워지고, 함수의 한 부분을 수정했을 때 다른 부분이 영향을 받을 위험 또한 생깁니다.

Read more

식당 비유: 당신이 알고 싶었던 것보다 훨씬 더 많은 것

식당 비유: 당신이 알고 싶었던 것보다 훨씬 더 많은 것

1년 전에 저는 유튜브에서 이 노래를 찾았습니다. 여기에 포함된 무수한 식당 비유는 기억 속에 각인되었고, 저는 새로 배운 온갖 분야에 식당 비유를 적용하는 데 집착하게 되었습니다. "컴파일러를 식당으로 비유하면..." "RESTful API를 식당으로 비유하면..." 그리고 거의 1년이 지나서야 이 집착이 실제로 학습에 미치는 영향에 대해 생각해보게 되었습니다.

By 10% matter
좋은 정렬, 나쁜 정렬, 이상한 정렬

좋은 정렬, 나쁜 정렬, 이상한 정렬

서론 세상은 정말로 또 다른 '정렬 알고리즘 설명' 블로그 글을 필요로 할까요? 한편으로는 확실히 그렇습니다. 왜냐하면 정렬 알고리즘은 이미 너무 많이 설명되었기 때문에, 오히려 제대로 설명된 적이 거의 없기 때문입니다. 버블 정렬은 “느리고”, 퀵 정렬은 “빠르며”, 병합 정렬은 “안정적”이라는 문장은 수천 번 반복되었지만, 그 문장을 처음 들었을

By 10% matter
블로그 디자인 하는 법

블로그 디자인 하는 법

블로그를 시작했으니 이제 현실의 문제를 처리해야 합니다. Ghost 기본 디자인은 적절하다고 생각하지만, 이것으로는 성에 차지 않습니다. 무엇보다도 아직 디자인을 손대지 않은 신생 블로그들과 완전히 똑같아 보일 테니까요. 그러면 좋은 디자인을 어떻게 구현할 수 있을까요? 그보다, 좋은 디자인이란 과연 무엇일까요? 제 대답은... 아무것도 모른다는 겁니다. 하지만 정답을 모른다고 아무것도 안 할

By 10% matter
나는 왜 쓰는가?

나는 왜 쓰는가?

I. 블로그란 무엇일까요? 꽤 오랜 시간 동안 그 답은 명백하다고 생각했습니다 - 검색 결과에 가끔 섞여 들어오는 무작위적인 정보 조각입니다. 가끔 유용할 때도 있지만 대부분은 형편없고, 거의 모두가 정보의 품질이 아닌 광고 수익을 바라보고 글을 올립니다. 여기서 네이버 블로그를 예시로 든 것이 불공평하다고 생각할 수도 있습니다. 실제로 다른 블로그 플랫폼들은

By 10% matter