이 글은 Sandrop 시리즈의 22번째 기록입니다. (총 23개)

오늘 한 일

  • Kenney 도안을 다시 받음 — 여백 잘라내기가 빠져 있었다. 채움 비율 0.19 → 0.46, 통과 도안 69 → 121
  • Fluent Emoji 도입 — 노토가 떨어뜨린 431개 중 120개를 살렸다. 쓸 수 있는 도안 1205종
  • 도안 뷰어에 출처 태그·필터, 색 계열 필터, “칙칙한 것만” 필터
  • 일일 보상을 상자에서 카드로. 뒤집기 + 보상 아이콘 + 꽃가루
  • 고르기 전 카드가 숨쉬는 움직임. 카드마다 박자를 밀었다
  • 일일 보상 화면만 어두운 배경으로
  • 하트·코인 아이콘을 그림으로 교체
  • 손그림을 도안으로 넣는 경로(fetch_drawn.py). 태극·복주머니 교체
  • 릴리스 서명 — 업로드 키 연결. 스토어에 올릴 수 있는 파일이 나온다
  • 레벨 동결은 출시 직전으로 미루기로 결정
  • 언어 전환(한국어/영어) — 문구 103개를 한곳으로 모으고 설정에 선택지를 넣음
  • 광고 보고 하트 받기(하루 1회) — 하트가 0일 때 코인을 거치지 않는 탈출구
  • 한 수도 안 둔 판은 뒤로가기에 확인 없이 바로 목록으로
  • 상점 아이콘 규칙 정리, 게임 방법을 모달로. 완성작 갤러리 탭은 안 만들기로 결정

막힌 부분

Kenney 도안이 작았던 건 여백을 안 자른 탓이었다

도안이 색이 뭉뚱그려지고 작아 보여서 원인을 찾아봤다. 두 가지가 겹쳐 있었다.

작은 쪽은 고칠 수 있었다. 투명 여백을 잘라내는 처리를 나중에 추가하는 바람에 먼저 받은 두 묶음에는 적용이 안 됐다. 다시 받으니 그림이 화면을 채우는 비율이 0.19에서 0.46이 되고, 커진 만큼 색이 살아 통과 도안도 69에서 121로 늘었다.

  • 해결: 새 소스를 받을 때 여백 자르기는 선택이 아니라 필수 단계로 두었다
  • 색이 뭉개지는 쪽은 못 고친다 — 3D 렌더라 음영이 많고, 작은 격자에 다섯 색으로 줄이면 중간톤이 뭉갠다. 소스의 성격이라 그림마다 다른 문제가 아니다

새 소재를 늘리면 무중복이 깨질 뻔했다

화풍이 맞는 소스를 찾다 Fluent Emoji를 봤다. 앞서 “다른 이모지 세트는 같은 소재의 다른 그림이라 늘어나는 게 없다”고 적어 뒀는데, 실제로 재보니 틀렸다. 노토가 떨어뜨린 431개 중 259개가 여기 있었고 120개가 통과했다. 3D라 음영이 있어 노토 평면 그림이 “색이 너무 비슷하다”고 버린 것들이 갈라졌다.

문제는 이미 도안이 있는 소재까지 받으면 같은 그림이 둘이 된다는 것이었다. 매 판 다른 그림이 나온다는 약속이 깨진다.

  • 해결: 노토가 실패한 코드포인트만 골라 받게 했다
  • 라이선스는 MIT라 상업 배포에 제약이 없다. 고지 의무만 있어서 원문을 같이 저장했다

도안 출처를 이름으로 판정했더니 완전히 틀렸다

뷰어에서 어느 소스에서 온 도안인지 보려고 이름 앞머리로 갈랐다. 그런데 노토 도안에도 apple·heart 같은 평범한 이름이 많아서 직접 만든 것과 섞였다.

199개가 직접 만든 것으로 잡혔는데 실제로는 17개였다.

  • 해결: 실제 소스 목록을 읽어 판정하게 고쳤다
  • 이름은 사람이 붙인 라벨이지 출처가 아니라는 걸 늦게 알았다

채도를 일괄로 올리면 이미 진한 색이 망가진다

칙칙한 도안을 밝게 하려고 채도를 곱했더니, 앞서 크루아상이 빨개졌던 것과 같은 일이 반복될 뻔했다.

  • 해결: 도안마다 색 구분 기준을 안 깨는 최대 배율을 따로 찾고, 절대 상한을 뒀다
  • 225개 중 210개가 개선되고 15개는 그대로 뒀다. 백자·백조처럼 원래 흰색이 본질인 것들이라 올리면 그 도안이 아니게 된다

회전만으로는 카드가 안 뒤집힌다

일일 보상 카드를 Y축으로 돌렸는데 뒤집히는 게 아니라 가로로 납작해졌다 돌아오기만 했다.

원근이 없으면 회전이 폭 변화로만 보인다. 깊이를 주고 나서야 카드가 도는 것처럼 보였다.

Matrix4.identity()
  ..setEntry(3, 2, 0.0015)   // 이게 없으면 납작해지기만 한다
  ..rotateY(turn * pi)
  • 남은 문제: 반 넘게 돌면 화면이 좌우로 뒤집힌 상태라 액자 장식이 거울상이 된다. 뒷면에 180도를 한 번 더 걸어 되돌렸다

꽃가루가 눈처럼 흩날렸다

터지는 조각이 퍼져 나가지 않고 매 프레임 다른 자리에 나타났다. 그림 그리는 객체가 프레임마다 새로 만들어지는데, 조각의 각도와 속도를 그 안에서 정하고 있었던 게 원인이다.

  • 해결: 카드를 고르는 순간 한 번만 만들어 화면 상태로 들고 있게 했다

코인을 밝히는 방법을 세 번 갈았다

금화 아이콘이 게임 화면에서 어두워 보였다. 재보니 밝기가 151로, 원래 있던 노란 원(209)보다 어두웠다. 어두운 배경 위에서는 괜찮고 밝은 배경에서만 탁해 보이는 것이었다.

  • 처음엔 색을 곱해서 올렸다. 밝기는 맞았는데 코인의 60%가 순백으로 날아가 각인이 사라졌다
  • 감마를 세 채널에 각각 걸어 봤다. 하이라이트는 살았지만 원래 값이 낮은 파랑이 비율상 더 올라가 금색이 베이지로 바랬다
  • 해결: 채널 최댓값에만 감마를 걸고 나머지를 비례로 따라가게 했다. 색상과 채도는 그대로 두고 밝기만 151에서 178로

밝게 하는 건 에셋에 구워 두고, 어두운 배경에서는 곱해서 낮춘다. 곱해서 낮추는 건 날아갈 하이라이트가 없어 안전하다.


손그림을 넣었더니 색이 사라졌다

직접 그린 태극·복주머니를 도안으로 넣었는데, 복주머니의 파란 리본과 금색 동전이 통째로 없어졌다.

기존 파이프라인이 부드럽게 줄이는 방식을 쓰는데, 픽셀로 그린 그림에서는 경계가 섞여 원래 없던 중간색이 생긴다. 작은 요소는 그 과정에서 사라진다.

  • 해결: 손그림은 최근접으로 줄이게 했다. 파랑과 금색이 살아났다
  • 손그림 가장자리에 남는 얇은 색도 문제였다 — 면적 1~2%짜리 색이 잡히는데, 게임에서는 색 하나가 바스켓 하나다. 칸 몇 개를 위해 바스켓을 쓰게 되므로 3% 미만은 가까운 색에 흡수시켰다

그림 두 장 바꿨는데 469탄이 달라졌다

교체 후 재생성하고 확인해 보니 500탄 중 469탄의 그림이 바뀌어 있었다.

도안을 난이도 순으로 정렬해 배정하는 구조라, 그림 하나가 바뀌면 그 도안의 점수가 달라지고 정렬 순서가 밀려 뒤따르는 배정이 전부 어긋난다.

  • 지금은 문제가 아니다 — 아직 유저가 없다
  • 출시 후에는 치명적이다. 300탄까지 깬 사람이 지나온 레벨이 전부 다른 그림이 된다
  • 결정: 동결은 출시 자체에는 필요 없다(그날 있는 레벨을 그대로 내보내면 된다). 없으면 안 되는 시점은 출시 후 첫 갱신이라, 그때까지 미루기로 했다

새로 그린 도안이 어느 난이도에도 안 맞았다

복주머니를 여러 난이도 자리에 넣어 봤더니 여섯 곳 전부 “너무 쉬움”이 나왔다. 태극은 여섯 중 다섯을 맞췄는데.

처음엔 다시 그려서 생긴 문제인 줄 알았다. 그런데 코드로 그리던 예전 복주머니도 똑같이 쉬웠다.

원인은 색 면적이었다. 복주머니는 그림의 86%가 빨강 하나고 나머지는 6~8%씩이다. 부을 순서를 고민할 거리가 없으니 벽을 아무리 깔아도 어려워지지 않는다. 태극은 45대 41로 갈려 있어 어느 쪽을 먼저 붓느냐가 판을 좌우한다.

  • 둘 다 색이 세 개인데 난이도가 딴판이다. 색 개수가 아니라 면적 분포가 정한다
  • 전체 재생성 때는 상관없다 — 생성기가 그 도안에 맞는 자리를 골라 준다(복주머니는 8탄으로 갔다)

서명 설정을 비워 두는 걸로는 사고를 못 막았다

릴리스 서명을 붙이면서, 키가 없으면 서명 설정을 비워 빌드가 실패하게 했다고 적었다. 확인하려고 키를 잠시 치우고 돌려 보니 빌드가 그냥 성공하고 서명 없는 파일이 나왔다. 이름도 평소와 똑같았다.

막으려던 사고를 그대로 두고 있었던 셈이다. 디버그 키로 조용히 넘어가던 것과 증상이 같다.

  • 해결: 릴리스 작업이 실제 실행 목록에 있을 때만 중단하게 했다. 설정 단계에서 무조건 중단하면 키가 없는 환경에서 개발 빌드까지 막힌다
  • 세 경우를 확인했다 — 키 없이 릴리스는 실패, 키 없이 디버그는 성공, 키 있고 릴리스는 성공하며 지문이 업로드 키와 일치

문구를 한곳으로 모으니 상수가 전부 깨졌다

언어 전환을 붙이려고 문구 103개를 한 파일로 옮겼더니, 상수로 두었던 자리가 전부 컴파일 오류가 났다. 상수는 빌드할 때 값이 정해져야 하는데 문구는 실행 중에 바뀐다.

  • 해결: 공용 안내 문구와 아이템 이름표를 매번 읽는 방식으로 바꾸고, 탭 목록처럼 통째로 상수였던 곳은 바깥 상수를 벗기고 안쪽 아이콘에만 남겼다
  • 번역이 빠지는 사고는 문구 클래스를 추상으로 만들어 컴파일이 잡게 했다. 기본값을 두고 덮어쓰게 하면 빠뜨린 문구가 조용히 한국어로 나온다

언어를 바꿨는데 뒤에 있던 화면은 그대로였다

설정에서 영어로 바꾸고 뒤로 나갔더니 목록 화면이 한국어 그대로였다. 이미 만들어진 화면은 다시 만들 이유가 없으니 당연한 일이다.

  • 해결: 루트에서 키를 바꿔 화면 트리를 통째로 새로 만들게 했다
  • 문구는 전역으로 뒀다 — 언어는 앱 전체가 한 번에 바뀌는 값이라 화면마다 다를 일이 없고, 그림 그리는 쪽처럼 화면 정보가 없는 곳에서도 읽어야 한다

위젯 테스트 12개가 한꺼번에 깨졌다

문구를 옮기고 테스트를 돌리니 화면 관련 테스트가 무더기로 실패했다. 테스트가 찾는 문구는 한국어인데, 테스트 환경의 기기 언어가 영어라 기본값이 영어를 골랐다.

  • 해결: 테스트에서 언어를 한국어로 고정했다. 문구 원문이 한국어라 그쪽이 읽기 쉽고, 영어 누락은 어차피 컴파일이 잡는다

영어로 바꾸니 설정 줄이 넘쳤다

화면이 한국어 기준으로 짜여 있어서, 영어 문구가 길어지자 설정의 토글 줄이 37픽셀 넘쳤다. “출시 전 제거”가 “Remove before release”가 된 자리였다.

  • 해결: 고정폭이던 문구를 남는 폭 안에서 줄어들고 그래도 길면 말줄임되게 바꿨다
  • 한 번 고치고 끝날 문제가 아니라, 영어로 설정 화면을 끝까지 그려 보고 넘치면 실패하는 테스트를 넣었다
  • 남은 한계: 다른 화면은 아직 이 검사가 없다. 영어로 직접 훑어봐야 한다

광고를 보고 하트를 받는데 4개가 버려졌다

하트가 4개일 때 광고를 보면 5개를 주지만 최대치가 5라서 1개만 들어온다. 하루 한 번뿐인 기회를 5분의 1 값에 쓰는 셈인데, 화면에는 +5 하트라고 적혀 있었다.

  • 해결: 정량이 아니라 지금 실제로 들어올 개수를 표시하게 했다
  • 막지는 않았다 — 당장 한 판 하려고 1개를 받는 건 손해가 아니라 선택이다. 숫자가 사실대로 적혀 있으면 속이는 게 아니다

셔플하고 나가면 하트가 환불되고 있었다

한 수도 안 둔 판은 확인 없이 바로 나가게 만들다가, “수를 뒀다”의 판정에 셔플이 빠져 있는 걸 발견했다.

  • 셔플만 하고 나가면 아이템을 쓰고도 입장 하트를 돌려받고 있었다. 이건 새 기능과 무관하게 원래 있던 구멍이다
  • 되돌리기는 이전에 둔 수가 있어야 쓸 수 있으니 이미 판정에 걸린다

고치려던 것이 이미 고쳐져 있었다

광고가 나오는 동안 배경음악이 겹쳐 난다고 적어 두고 할 일로 미뤄 뒀는데, 실기기에서 보니 이미 멈췄다가 광고가 끝나면 다시 났다.

이유를 찾아보니 며칠 전 붓는 소리 문제를 고치면서 같이 해결돼 있었다. 그때 “앱이 앞에 없으면 소리를 멈춘다”의 판정을 넓혔는데, 전체화면 광고도 거기 걸린 것이다.

  • 원인 설명이 틀렸었다. “광고는 앱을 배경으로 안 보내니 자동으로 안 멈춘다”고 적어 뒀는데, 전체화면 광고는 자기 화면을 띄우므로 앱이 앞에서 물러난 것으로 잡힌다
  • 예전 판정이 좁아서(완전히 가려진 경우만) 광고가 주는 신호를 놓쳤던 것이지, 신호가 안 온 게 아니었다
  • 계획대로 광고 쪽에 정지·재개를 따로 붙였다면 두 경로가 겹쳐 멈췄다 켜졌다 했을 것이다. 특히 보상형은 닫힘과 보상 지급 순서가 얽혀 있어 사고가 날 자리였다

할 일 목록에 오래 남은 항목은 착수 전에 아직 재현되는지부터 봐야 한다. 원인 설명이 그럴듯하면 더 그렇다.


다음에 할 일

  • 스토어 등록물·Play Console (콘텐츠 등급·데이터 보안 양식·타겟층 설정) — 영어 등록정보도 필요
  • 배포 전 디버그 모드 제거
  • 출시 후: 레벨 동결 — 출시된 레벨을 스냅샷으로 두고 이후 레벨만 추가 생성
  • 남은 성능 과제: 캔버스를 이미지로 구워 한 번에 그리기, 게임 루프가 화면 전체를 새로 그리지 않게 하기

Series: Sandrop


Suggested Posts