아랫줄이 좌(액션)/우(이동) 두 컬럼에 걸쳐 있어 하드 드롭·홀드는 각각
화면의 28.7%, 소프트 드롭은 42.6% 를 차지했다. 정확히 1/3 씩 주려면 그
줄이 전체 폭을 써야 하므로, ControlPad 바깥을 Row → Column 으로 바꿔
윗줄(회전|이동)과 아랫줄을 각각 통짜 Row 로 깔았다. 윗줄 비율은 그대로다.
왼손 배치에서는 아랫줄도 좌우를 뒤집어 소프트 드롭이 왼쪽으로 간다.
검증(1080px 폭 실측): 아랫줄 버튼 폭 326/327/327px 로 균등. 윗줄은
↺199 ↻200 180°133 ◀202 ▶202 로 이전과 동일. 새 위치에서 홀드 탭 시
패널 유채색 0 → 5474, 하드 드롭 탭 시 넥스트 47584px 갱신,
소프트 드롭 길게 누름 시 낙하 속도 152 → 1137 px/s, 좌우 이동은
한 번에 정확히 한 칸(76px). 가로 화면은 구조가 달라 영향 없음(확인함).
엔진 테스트 28개 통과. 스토어 스크린샷 2장 교체.
아랫줄을 하드 드롭 + HOLD 로 정확히 반씩 나눴다(실측 각 276px).
윗줄에서 HOLD 가 빠져 생긴 한 칸은 ↺·↻ 가 나눠 가졌다. 180° 는 폭을
유지해야 해서 4등분 중 1칸(weight 1)을 그대로 두고 회전 두 개에 1.5 씩
줬다 — 실측으로 180° 는 127 → 132px(간격 하나가 줄어든 만큼), ↺·↻ 는
126 → 198px 이 됐다.
검증: 새 위치에서 HOLD 탭 시 홀드 패널 유채색 0 → 5476, 하드 드롭 탭 시
보드 43377px·넥스트 47948px 갱신, 회전 3종 모두 탭 직후 보드 변화 확인.
엔진 테스트 28개 통과. 바뀐 조작부가 찍힌 스토어 스크린샷 2장 교체.
세로 화면 조작부를 요청대로 바꿨다. 회전(↺ ↻ 180°)과 HOLD 를 윗줄로 올리고,
하드 드롭은 맞은편 소프트 드롭과 같은 자리(맨 아래 가로로 긴 낮은 버튼)로
내렸다. 한 줄에 버튼이 4개가 되어 액션 컬럼 폭을 1.1 → 1.35 로 늘렸다.
1.1 로는 버튼이 세로로 길쭉해져 엄지로 누르기 불편했다.
그 과정에서 HOLD 를 눌러도 패널이 그대로인 것을 발견했다. game.hold 와
game.peekNext() 는 Compose 가 관찰하지 못하는 평범한 엔진 필드인데,
BoardCanvas 와 달리 패널 쪽은 state.version 을 구독하지 않아 게임 시작
시점의 넥스트 큐가 끝까지 멈춰 있었다. 넥스트 미리보기는 이 장르의 핵심이라
출시 전에 잡아야 하는 버그다. 패널을 SidePanels 로 분리해 version 을
구독시켰다 — 재구성 범위를 패널 서브트리로 좁혀 매 프레임
BoxWithConstraints 측정이 다시 돌지 않게 했다.
검증: 에뮬레이터에서 HOLD 탭 후 패널 유채색 픽셀 0 → 5474, 넥스트 패널은
하드 드롭 뒤 49370 픽셀 변화(수정 전에는 보드가 116848 픽셀 바뀌는 동안
넥스트는 0 픽셀이었다). 회전 3종·하드 드롭·소프트 드롭 모두 동작 확인.
세로/가로 양쪽 확인. 엔진 테스트 28개 통과.
바뀐 조작부가 찍힌 스토어 스크린샷 3장도 다시 촬영했다.
iOS 타깃을 제거했다. Apple Developer Program 연 $99 와 맥이 필요한데
아이폰은 기존 웹 PWA 로 이미 커버되므로 비용 대비 실익이 없다고 판단했다.
commonMain 중심 구조는 그대로라 iosTarget 만 다시 넣으면 복구된다.
멀티·리그전/커스텀 카드에 '준비 중' 배지를 붙였다. 구현되지 않은 모드가
스토어 스크린샷에서 동작하는 것처럼 보이면 Play 의 허위 표시 정책에 걸린다.
store/ 에 Play Console 제출 자산을 모았다: 등록정보 문구, 데이터 보안 설문
답안(릴리스 APK 에 INTERNET 권한이 없음을 aapt2 로 확인), 개인정보처리방침,
피처 그래픽 1024x500, 스토어 아이콘 512x512, 폰 4장 + 태블릿 3장 스크린샷.
TWA 래퍼를 걷어내고 Compose Multiplatform 으로 다시 만들었다. 엔진·UI·모드
전부 commonMain 한 벌이라 Android 와 iOS 가 같은 코드를 쓴다.
- engine/: 웹 JS 엔진을 Kotlin 으로 이식 (SRS+180 킥, 7-bag, T-spin, B2B,
콤보, All Clear, 점수·레벨). commonTest 28개 통과
- game/: 모드 규칙 + 중력/락딜레이/DAS/ARR 타이밍
- ui/: 네오브루탈 컴포넌트, 메인/솔로시트/인게임/결과/설정
- ui/Responsive.kt: 고정 해상도를 버리고 가용 크기에서 셀 크기·배율 계산.
폰 세로, 플립 초세로, 플립 커버(소형), 폴드 펼침, 태블릿/아이패드 가로 대응
- androidMain: resizeableActivity + configChanges 로 접기/펴기·회전 시 재시작 없음
- iosMain + iosApp/: MainViewController + SwiftUI 껍데기 + XcodeGen 설정
(실제 iOS 빌드는 macOS + Xcode 필요)
- scripts/release.sh: 버전 상승 → 테스트 → 서명 빌드 → 태그 → Gitea 릴리스 자동화