1년 반의 세월을 건너 드디어 다음 버전으로 업데이트를 하게 되었다. 실용성을 갖고 지속적으로 활용될 수 있는 프로그램을 작성, 관리하는 일이 "개발"이라고 한다면 내가 해오는 일들은 개발이라고 보기 어렵다. 돈을 받고 한 일도 아니고 댓가를 바라고 있는 것도 아니지만 비유해보자면 자동차 회사가 차를 만들고 수십년이 지나도록 신형 차를 만들지 않는 것과 똑같다. 나는 프로그램을 만들었고 방치했다. 물론 바빠서도 큰 이유였지만 이걸 업데이트 하는 일이 귀찮았다는 사실을 부정할 수 없다. 그리고 변호하자면 어려운 과정이 있었다.
1. 주석 달기
지난 작업에 주석을 충분히 달아놓지 않은 것은 굉장히 멍청한 짓이었다. 1000줄 꼬박 넘는 작은 규모의 프로그램이긴 하지만 정식적인 개발 경험이 없어서 규격화되지 않은 코드에 주석은 필수적이다.
이렇게 변수 선언 부분 같이 비교적 앞쪽 코드들은 주석이 잘 달려있으나
이런 코드는 뭐가 뭔지 모르겠다. 지금 봐도 뭘 말하는지 좀 헷갈린다. path_ex는 뭐고 path_sh는 뭘까. 이번에 건드릴 부분이 아니라서 참 다행이다. 뭔가 주저리주저리 써놓는 것이 거추장스럽다고 생각했는데 성능에 영향을 주지 않는 기능이라면 누가 언제 읽어도 "어?" 없이 곧바로 이해할 수 있는 주석을 달아놓는 것이 정답인 것 같다. 라고 말하면서도 지금도 주석이 많이 부족하다. 천천히 읽으면서 달아놔야 할 것 같다. 새 스프라이트를 발견하고 나서부터 업데이트가 끝날 때까지 걸린 시간은 이틀이다. 그중 하루를 코드를 이해하는데 썼다. 다음부터는 꼭 주석을 잘 처리해놓자..!
2. 코드의 생산성
정말 크게 느꼈던 부분이다. 초기 버전의 프로그램을 만들면서 스프라이트를 처리하는 과정에 다양한 아이디어를 적용했었다. 결론은 이미지를 병합해서 한 장으로 처리해버리는 것이다. 이 방법은 이번에도 다시 써먹을 수 있었다.
입수한 포켓몬 스프라이트는 지난번과 같은 형식으로 되어있었다. 68*56px의 png 파일이며 파일명은 포켓몬의 영어이름. 폼의 구분은 "Maushold-Four"과 같이 하이픈으로 처리되어 있다. 먼저 포켓몬의 영어이름을 한국어로 바꾸어주어야 한다. 그리고 이미지를 병합했을 때, 폴더에 정렬된 순서로 파일을 불러오기 때문에 오름차순으로 정렬된 포켓몬의 영어이름을 알고 있어야 병합된 이미지에서 내가 원하는 포켓몬의 위치를 찾아 불러올 수 있다.
그래서 병합 프로그램을 따로 제작했었다. 단순히 이미지의 픽셀을 읽어서 새로운 비트맵에 배치하는 과정을 반복시킨다. 만약 이 과정이 없었다면 솔루션 포함리소스로 1464장의 이미지를 모두 불러왔어야 했다. 아니 3개의 난이도에 이로치까지 있으니 8784장이다. 이렇게 되면 답이 없다.
그렇게 병합된 이미지를 한 번에 작업해 포함리소스에는 단 6장의 이미지만 저장되었다. 얻어온 이미지를 더해서 다시 병합하면 됐기 때문에 작업 시간이 매우 단축되었다. 다음은 포켓몬의 이름이다. 영어이름을 한국어로 번역해줄 수 있는 진짜 말 그대로의 dictionary를 만들어야 했다. 파일명을 전부 불러와 csv로 저장해놓았다만 이걸 하나하나 바꾸기엔 시간이 너무 오래걸린다. 무엇보다 포켓몬의 배열이 도감 번호 순서가 아니라 이름의 오름차순이라 찾기도 쉽지 않다. 아쉽지만 이 csv파일을 만드는 과정은 순수 노가다였다.
이런 식으로 영어에 대응되는 한국어를 하나하나 입력해 csv파일로 만들었다. 다행인 것은 폼이 하이픈으로 구분되어 있기 때문에 하이픈을 단위로 스플릿 할 것을 산정해 분절시켜 데이터를 저장했다. 중복되는 것이 많았기 때문에 작업량은 그리 많지 않았다.(1185쌍을 입력함) 이 부분은 앞으로 10세대가 나온다면 다시 추가해줘야 한다. 만약 어떤 포켓몬의 폼이 이전에 등장한 포켓몬과 중복되는 경우, 이 프로그램은 심각한 문제를 맞이하게 된다. "original" 이라는 폼을 갖는 새 포켓몬이 등장했는데 그에 대응하는 한국어가 이미 저장되어있는 "500년전의색"이 아니라면 이걸 처리할 방법이 없다. 만약 그럴 경우에는 병합 전에 파일명을 미리 손봐서 original2로 바꾸던가 해야 할 것 같다.
이제 이미지 파일의 오름차순 목록과 한국어 대응쌍까지 만들었으니 병합된 이미지에서 그 순서에 맞도록 이미지를 꺼내올 수 있다. 이 모든 과정이 업데이트의 80%에 해당했는데 대부분의 시간을 영-한 대응 csv파일 제작에 소모했고 나머지 작업은 지난 작업의 결과물을 그대로 써먹었다. 10세대가 나와도 같은 방법으로 작업하면 될 것 같다. 앞으로 어떤 개발을 하든 재작업을 염두에 두어야 한다는 생각을 했다.
3. 규격화
이번 업데이트가 늦어진 가장 큰 원인이다. 26년에 걸친 1~9세대 포켓몬스터 게임에서 사용된 포켓몬 스트라이프는 계속 변해왔다.
전투 이미지만 따져보면 초기에는 이렇게 정적인 그래픽이었으나 나중에는
이렇게 되어버린다. 그리고 전투 중에는 뒷모습이 주로 나오기 때문에 활용하기 좋지 않다. 다른 이미지를 찾아보다가 발견한 것이 이 페이지였다.
PokéSprite - Gen 8
PokéSprite Database project of box and inventory sprites from the Pokémon core series games This table lists all Pokémon box sprites for Gen 8, which can be found in the pokemon-gen8 directory. The list is up-to-date as of Pokémon Sword/Shield, and som
msikma.github.io
8세대까지 등장한 모든 포켓몬의 박스 보관시 표기되는 스프라이트다. 박스 시스템은 이전 버전의 포켓몬도 받기 위해 있는 것이기 때문에 해당 버전까지 등장한 모든 포켓몬의 이미지가 같은 크기와 형식으로 그려진다. 그게 8세대에서는 68*56px 크기였다. 애석하게도 9세대의 박스 스프라이트가 찾기 어려웠고 따로 찾았던 것이 대강 120*80px 정도 크기의 이미지였는데 이러면 칸 수가 1만 칸 근접해버린다. 칸의 크기를 작게하는 것은 둘째치고 이미 이전에 68*56px 크기로 맞춰온 레이아웃도 새로 지정해야 하기 때문에 완전히 새로운 프로그램을 만드는 것과 다르지 않았다. 아예 9세대 전용 뽑기 프로그램을 만드는 것이 차라리 나을 지경. 그래서 결국 업데이트는 무기한 연기되었던 것이다...
이틀 전 저녁 오랜만에 생각나서 포켓몬 스프라이트를 검색하다가 우연히 새로운 이미지 파일을 얻었는데 확인해보니 그게 딱 68*56px인 박스 스프라이트였다. 곧바로 이미지를 내려받아 작업을 거쳤으나 1009번 이후의 포켓몬은 없었다. 만약 10세대 포켓몬스터의 박스 스프라이트가 68*56px이 아니라면 이 방식을 버리게 될지도 모른다. 아마 완전히 새로운 v3 버전을 내놓아야 할지도... 어떤 것을 규격으로 삼을 것인가, 내 프로그램이 다른 소스를 끌어 사용한다면 신중하게 고려할 문제인 것 같다. 규격화되지 않은 소스를 활용하면 언젠가는 규격에 맞추기 위해 많은 부분을 도려내야 할지도 모른다.
4. 느낀점
근 1년간 ps에만 푹 빠져서 맨날 백준만 기웃거리는데 알고리즘 공부도 좋지만 본질을 잊지 않아야겠다. ps를 시작하게 된 계기가 개발이었는데 이제 주객이 전도되어도 한참 바뀐 것 같다. 실질적인 결과물을 뽑아낼 때가 되었다..!
개발 경험이 턱없이 부족하다는 것을 느낀다. 어떤 코드를 짜도 자신감이 없다. "이 코드가 일반적인 코드가 아니면 어떡하지?"라는 생각에 다른 사람의 코드를 찾아보고, 검색해도 찾을 수 없는 부분은 한참의 고민 끝에 작성해 나가지만 나중에 돌아보면 십중팔구 개판이다. 개발자들이 엄격하게 따르는 개발 지침을 찾아봐야겠다.
마지막으로 C# 개발 계속 해나가려면 문법도 좀 더 자세히 익혀놔야 할 것 같다. 클래스 구현 없이 이 많은 코드를 하나에 때려 넣으려고 하니 가독성도 너무 떨어지고 객체지향언어라는 장점이 완전히 가려져버린다. 이럴 거면 그냥 C언어 배우는 게 나을지도 모르겠다.(배울 생각 없음)