Files
tetrig/README.md
tkrmagid 9a41c9a340 Pivot client to native Android (Kotlin) — engine module + JUnit
플레이스토어 출시 위해 클라이언트를 네이티브 Android(Kotlin+Compose)로 전환.
- android/engine: 순수 Kotlin 코어 엔진 이식 (보드·SRS+180 킥·7-bag·홀드·고스트·
  락딜레이·T-spin/mini 판정·콤보/B2B). 웹 engine.js 와 동일 알고리즘.
- android/engine/src/test: JUnit 24개 테스트 전부 통과 (Gradle 8.11.1 + JDK21).
- Gradle 래퍼 포함. :app(Compose UI) 모듈은 다음 단계.
- 서버(Cloudflare) 계획 불변. 웹 프로토타입은 동작 레퍼런스로 유지.
2026-08-22 14:31:50 +09:00

110 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# TETRIG (테트리그)
> 쌓아라, 부숴라, 올라가라.
TETR.IO 스타일의 **모바일 실시간 대전 블록 스태커** 웹 게임. 솔로 3모드 + 인원 무제한 커스텀 룸(FFA) + Glicko-2 랭크 리그전을 하나의 단일 HTML 클라이언트와 Cloudflare Workers 서버로 구현한다.
이 문서는 앱 제작을 위한 **최종 빌드 진입점(entry point)** 이다. 모든 설계 결정·수치·에셋의 **정본(source of truth)은 [`TETRIG-최종명세서.md`](./TETRIG-최종명세서.md)** 이며, 구현 시 반드시 명세서와 UX 목업을 함께 열어 작업한다.
> **클라이언트 변경 (2026-08-22 사용자 결정)**: 플레이스토어 출시를 위해 클라이언트를 **네이티브 Android (Kotlin + Jetpack Compose)** 로 제작한다. 소스는 [`android/`](./android). 코어 게임 로직은 UI와 분리된 순수 Kotlin 모듈 [`android/engine`](./android/engine) 에 있고 JUnit 으로 검증한다(SRS 킥테이블·7-bag·T-spin 판정·점수·좌표 등 §4·§13 데이터는 그대로 이식됨). 서버 계획(Cloudflare Workers + D1 + WebSocket)은 변경 없이 유지된다. 초기 웹(HTML) 프로토타입(`src/`, `index.html`)은 검증된 **동작 레퍼런스**로 남겨둔다.
---
## 무엇을 만드는가
산출물은 딱 2개다.
1. **클라이언트** — 단일 HTML 파일 (HTML + CSS + JS, Canvas 2D). **외부 에셋 0개**, 사운드는 100% Web Audio 신스 생성.
2. **서버** — Cloudflare Workers 프로젝트 (wrangler 표준 구조: Durable Objects 2종 + D1 + Cron).
게임 구성:
- **솔로 3모드**: SPRINT(40줄 최속) · TIME ATTACK(2분 점수) · ENDLESS(무한)
- **커스텀 룸**: 6자리 초대 코드, 인원 무제한 FFA, 호스트 규칙 설정
- **리그전**: Glicko-2 레이팅 + 18단계 랭크 + 배치 10경기 + 시즌제
## 아키텍처
```
[모바일 브라우저] [Cloudflare]
클라이언트 (단일 HTML, Canvas) ⇄ WSS ⇄ Workers
├ 게임 엔진 (SRS+, 판정, 렌더) ├ MatchmakerDO (리그 매칭 큐, 싱글턴)
├ 솔로 모드 3종 ├ GameRoomDO (경기방 — 리그 & 커스텀 공용)
└ 멀티/커스텀/프로필/리더보드 UI ├ D1 (계정·레이팅·전적·리더보드)
└ Cron (RD 감쇠, 시즌 처리)
```
- 클라이언트: Cloudflare Pages(또는 Workers 정적 자산)로 호스팅, 시작 주소는 `tetrig.pages.dev`.
- 서버: 무료 티어로 운영 가능 (DO SQLite 백엔드 + WebSocket Hibernation).
- 로컬 개발: `wrangler dev` + 브라우저 탭 여러 개로 다인전 테스트.
## 저장소 파일
| 파일 | 용도 |
|---|---|
| `TETRIG-최종명세서.md` | **정본 명세서** — 모든 규칙·수치·좌표·스키마·프로토콜 |
| `tetrig-ux-mockup.png` | 9화면 UX 목업 (1390×2944) — **UI 구현의 시각 기준** |
| `tetrig-logo.svg` / `tetrig-logo.png` | 가로형 워드마크 로고 (실사용 에셋 / 렌더 미리보기) |
| `tetrig-icon.svg` / `tetrig-icon.png` | 앱 아이콘 512×512 (실사용 에셋 / 렌더 미리보기) |
명세서의 화면 번호 ①~⑨는 목업 시트의 화면과 1:1 대응한다. **시각 판단은 목업 이미지를 따르고**, 명세서 §11~§13의 좌표·팔레트 수치로 정확도를 보정한다.
## 핵심 규칙 요약 (상세는 명세서 §4~§8)
- **보드**: 10열 × 40행(내부), 하단 20행 표시. 랜덤 7-bag, 넥스트 5, 홀드 1회/피스, 고스트 피스.
- **회전**: SRS + 180° 킥테이블 (명세서 §4.1). 락 딜레이 500ms / 최대 15회 리셋.
- **판정**: T-spin / T-spin mini, B2B, 콤보, All Clear. 4줄 클리어는 **"QUAD"** (Tetris/테트리스 단어 금지).
- **대전**: 가비지 전송 테이블 + 상쇄(counter) + 8줄/회 상한 + 장기전 방지 배율.
- **리그**: Glicko-2 (R=1500, RD=350, σ=0.06, τ=0.5) → 표시용 TR(0~25,000) → 18단계 랭크. 배치 10경기, RD<100일 때만 랭크 표시.
- **매치메이킹**: MatchmakerDO 싱글턴 큐, R ± 2×RD 구간이 겹치면 성사. 형식은 높은 랭크 기준 A+ 이하 FT3 / S- 이상 FT5.
## 디자인 시스템 (NEOBRUTAL — 상세는 명세서 §13)
- **테마 이원화**: 메뉴/로비/결과는 BONE(#EDE7DA) 라이트, 인게임은 INK(#17161B) 다크.
- **컴포넌트**: 2px 잉크 보더 + 블러 0 하드 오프셋 섀도 + 우하단 챔퍼컷 + 고대비 플랫 컬러.
- **시그니처**: 45° 해저드 스트라이프(가비지·공격·광고·난투에만 절제 사용).
- **금지**: 다크 네이비 배경 · 네온 글로우 · 그라디언트 · 블러 섀도 · 과도한 라운딩.
- **피스 7색(v2 확정)**: I `#3EC1B6` / O `#F5C531` / T `#A76BF2` / S `#7FCC4C` / Z `#F25C4C` / J `#4C7DF2` / L `#F2913D` / 가비지 `#46464F`.
## 개발 로드맵 (이 순서로 진행)
각 Phase 완료 시 실행 가능한 파일 + 코어 로직 단위 테스트 통과를 완료 기준으로 삼고, 사용자 확인 후 다음으로 넘어간다.
| 단계 | 내용 | 완료 기준 |
|---|---|---|
| Phase 1 | 코어 엔진: 보드·피스·SRS+180 킥·7-bag·홀드·고스트·락딜레이·클리어 | 키보드 플레이 + 킥/판정 단위 테스트 통과 |
| Phase 2 | 판정·점수 + 솔로 3모드 + 솔로 결과 화면 | 3모드 정상 플레이·기록 저장 |
| Phase 3 | 가상 버튼 + 스와이프 + 핸들링 설정 + 메뉴 화면들 | 모바일 브라우저 실기 조작 확인 |
| Phase 4 | 서버 뼈대: 게스트/계정·기록 이전·GameRoomDO·WS·가비지 원장 + 커스텀 1:1 | 탭 2개로 코드 방 1:1 대전 성사 |
| Phase 5 | 커스텀 FFA: 다인 타겟팅·미니뷰 그리드·KO 관전·도중 입장·리매치 투표 | 탭 4개+ FFA 라운드 정상 진행 |
| Phase 6 | MatchmakerDO + Glicko-2 + TR/랭크 + 리더보드·프로필·전적 + 리그 결과 | 매칭→경기→TR 반영 전체 사이클 |
| Phase 7 | 연출·사운드·시즌·광고 슬롯 연결·재접속/부하 점검·폴리시 | v1 배포 (wrangler deploy + Pages) |
## 개발 환경
```bash
# 서버 (Cloudflare Workers)
npm create cloudflare@latest # wrangler 프로젝트 초기화
wrangler dev # 로컬 개발 서버 + WS
wrangler deploy # 배포
# 클라이언트
# 단일 HTML 파일 — 브라우저로 직접 열거나 Pages/Workers 정적 자산으로 서빙
```
준비물(필요 시점에 사용자에게 확인 — 명세서 §17):
- Google OAuth 클라이언트 ID (Phase 4)
- 애드센스 계정 ID (Phase 7)
## 구현 가드레일 (반드시 지킬 것)
- **IP 금지**: 사용자 노출 텍스트에 "Tetris/테트리스" 금지, 테트리스 음악(Korobeiniki 등) 금지, 표준 가이드라인 색상 1:1 복제 금지, TETR.IO 에셋·명칭 복제 금지.
- **BRAND 상수화**: 앱 이름·로고 문구는 코드 1곳(`const BRAND = "TETRIG"` / `BRAND_KO = "테트리그"`)에서 관리해 1분 내 리브랜딩 가능하게.
- **튜닝 수치 상수화**: 중력·TR 커브·콤보 테이블 등 조정 대상은 코드 상단 상수로 분리.
- **언어**: 사용자 노출 텍스트는 한국어 (게임 용어 SPRINT/HOLD 등 영문 허용).
- **테스트 필수**: 킥테이블·T-spin 판정은 반드시 jsdom/node 단위 테스트로 검증.
- **명세 준수**: 명세서에 값이 명시된 것은 그대로 구현하고, 없는 것만 질문한다.
## 라이선스 / 상표
앱 이름 "테트리그(TETRIG)"는 상표 유사성 리스크를 인지한 뒤 **스토어 출시·수익화(광고 게시)까지 최종 확정**한 이름이다(2026-08-21). 이름 재검토 트리거는 없다. `BRAND` 상수화는 리브랜딩 대비가 아니라 표기 일관성·유지보수를 위한 단일 소스로서 유지한다 (명세서 §2).