dotgimon 제작기 01. 오리지널 몬스터 교체 설계
dotgimon은 작은 LCD 화면에서 몬스터를 먹이고, 재우고, 진화시키는 도트 육성 게임이다. Expo 프로젝트를 만들고 나니 코드보다 일찍 정리할 문제가 있었다. 작업에 쓰던 몬스터 이미지와 이름이 원작 게임의 것이었다. 배포를 생각한다면 이 상태를 계속 가져갈 수는 없었다.
이날 저장소에 남긴 앱은 기본 템플릿이었다. 화면에는 프로젝트를 열어 코드를 수정하라는 안내만 있었다. 구현을 늘리는 대신, 원작 이미지를 직접 만든 도트로 바꾸는 범위와 제작 규칙을 정했다.
그림을 바꾸는 일만으로 끝나지 않았다
교체 설계에 적힌 대상은 스프라이트뿐이 아니었다. 몬스터 이름, 속성 이름, 엔진이 참조하는 종 ID, 저장 키와 README까지 원작의 흔적이 이어져 있었다. 화면에서 그림만 갈아 끼워도 저장 데이터와 코드에는 옛 이름이 남는 구조였다.
설계에서는 기본 몬스터 81종의 이름과 도트를 바꾸고, 알도 새로 만들기로 했다. 코드에서 참조하지 않는 알 변형 이미지는 대체 대상을 따로 만들지 않았다. 쓰지 않는 파일까지 같은 수로 다시 그릴 필요는 없었다.
이날 저장소에는 기본 앱 템플릿만 남겼다. 게임의 교체 구현을 끝낸 날은 아니었고, 이름과 그림을 바꾸는 범위를 설계로 정리했다.
원작을 떠올리게 하는 요소도 함께 정리했다. 이름의 -mon 접미사는 사용하지 않고, Vaccine·Data·Virus 속성은 Sun·Moon·Star로 바꾸었다. Free는 그대로 두었다. 법적으로 어느 이름까지 문제가 되는지를 단정하기보다, 내 게임에서 사용할 표현을 직접 정하는 쪽을 택했다.
진화 연결은 유지하고 표현을 새로 정했다
외형을 바꾸는 동안 게임 규칙까지 흔들리면 작업 범위가 커졌다. 기존 종이 어떤 종으로 진화하는지, 어떤 조건과 수치를 쓰는지는 유지했다. 새 이름과 그림을 기존 종에 하나씩 대응시키는 방식이었다.
이 선택을 배포에 필요한 권리 검토가 끝났다는 뜻으로 삼지는 않았다. 아이디어와 표현을 구별하는 일반 원칙만으로 특정 게임의 진화 구조와 수치를 그대로 사용해도 안전하다고 단정할 수는 없다. 이번에 확정한 것은 직접 만들 표현의 범위였다.
이름 길이에도 화면 제약이 있었다. LCD의 이름 표시는 slice(0, 8)로 여덟 글자까지 잘랐고, 픽셀 폰트에 넘길 때 대문자로 바꾸었다. 이름은 여덟 글자 안에서 짓고 데이터에는 Title case로 적는 규칙을 두었다.
처음 시작할 몬스터를 뽑는 여섯 계통에는 외형 주제를 나눠 주었다. 화염과 공룡, 냉기와 야수, 천공과 유령, 수풀과 곤충, 그림자, 전기와 수생이었다. 종을 하나씩 만들더라도 같은 계통끼리는 이어져 보이게 하려는 기준이었다.
외부 에셋 대신 문자열로 도트를 만들었다
외부 에셋 팩도 선택지에 있었다. 다만 파일마다 라이선스를 확인하고 프로젝트에 맞는지 판단하는 비용이 들었다. CC0 팩도 후보에서 빼고, 에셋은 직접 만드는 것으로 정했다.
도트 원본은 그림 파일보다 문자열 배열로 관리하는 쪽을 골랐다. 공백과 #으로 16×16 격자를 표현하고, 계통별 파일에 종을 모았다. 몬스터 81종과 알 한 종을 같은 생성 규칙으로 다룰 수 있었다.
생성 과정은 도트맵을 읽어 검증한 뒤 두 배로 확대하고, 사방에 2px 여백을 붙이는 순서였다.
출력은 기존 렌더러에 맞춰 흰색과 검정만 쓰는 36×36 GIF로 정했다. 원본을 두 배로 키운 32칸에 양쪽 여백을 더한 크기다. 이 단계에서는 한 프레임 이미지를 기준으로 삼았다.
GIF 인코더도 생성 스크립트 안에 두는 설계였다. 색상과 크기, 프레임 수가 제한되어 있어 범용 이미지 도구를 붙이기보다 필요한 형식만 만드는 쪽을 골랐다. 압축률보다 구현을 단순하게 유지하는 데 무게를 두었다.
실루엣 크기는 진화 단계에 따라 달리 정했다. 유년기는 작은 덩어리로, 완전체는 격자를 더 많이 쓰는 모습으로 만들고 발이 닿는 기준선은 맞췄다. 파일마다 가운데를 맞추는 것만으로는 성장한 느낌이 나지 않아, 단계별 몸 크기도 제작 규칙에 넣었다.
종 ID가 바뀌면 저장 데이터도 달라졌다
코드에서는 digimon.ts를 dex.ts로 바꾸고 타입 이름도 Digimon에서 Monster로 바꾸기로 했다. 알의 ID는 digitama에서 egg로 옮겼다. 엔진과 LCD 렌더러에 하드코딩된 기본 이미지도 같은 ID를 가리키게 정리했다.
저장 데이터에는 종 ID가 그대로 들어 있었다. 새 도감에 없는 옛 ID를 읽으면 현재 펫을 찾을 수 없었다. 이 단계에서는 옛 종을 새 종으로 옮기는 변환기를 만들지 않고, AsyncStorage 저장 키를 pixelpet에서 pixelpet2로 바꿔 옛 데이터를 읽지 않는 쪽을 선택했다.
그림 파일을 지우는 작업과 저장 키 변경을 따로 생각할 수 없었다. 이미지, 도감 데이터, 엔진의 기본값, 저장 데이터가 모두 같은 ID를 공유했다. 어느 한 곳만 옛 이름을 남기면 새 도트가 있어도 제대로 불러오지 못했다.
눈으로 보는 검사와 코드 검사를 나눴다
생성기가 성공했다고 교체가 끝나는 것은 아니었다. 도감의 ID와 도트맵의 ID가 하나씩 맞는지 검사하고, 여러 몬스터를 한 화면에 모은 이미지로 외형을 확인하는 기준을 세웠다. 타입 검사와 남은 원작 문자열 검색도 완료 조건에 넣었다.
문자열 검색은 기억에 의존하지 않기 위한 장치였다. 이름을 바꾸다 빠뜨린 import, 알의 기본 ID, README의 출처 표기처럼 화면만 봐서는 놓치는 곳이 있었다. 에셋 파일과 코드 양쪽에서 교체 대상을 확인하도록 했다.
앱 기능은 거의 늘지 않았지만 교체 범위는 분명해졌다. 이름과 도트를 직접 만들고, 종 ID를 사용하는 코드와 저장 키를 함께 바꾸며, 게임의 진화 조건과 수치는 이번 작업에서 유지했다. 도트를 그리기 전에 어디까지 바꾸는 일인지부터 정리한 날이었다.