# BLOCK BLOOM · 블록 블룸

`Block Out! — Color Sort Puzzle`의 핵심 색상 탈출 규칙과 광택·돌기형 블록 표현을 참고한 독립 HTML5 퍼즐입니다. 원본 자산·코드·레벨을 복사하지 않았습니다. [레퍼런스와 수익화 설계 노트](design.html).

## 실행

빌드나 런타임 패키지 설치 없이 [공개 게임](https://lunarelin.github.io/games/block-bloom/) 또는 정적 HTTP 서버에서 `games/block-bloom/`을 엽니다. 저장소 루트에서 다음 미리보기를 실행하면 `.mjs`와 글꼴 MIME 타입도 설정됩니다.

```powershell
python games/block-bloom/tests/serve.py --port 4174
```

`http://127.0.0.1:4174/games/block-bloom/`에 접속합니다. `--no-font`는 글꼴 실패 검증 전용 옵션입니다. 실행에는 외부 라이브러리나 웹 폰트 연결이 필요하지 않습니다.

## 조작과 모드

- 블록을 누른 채 마우스·손가락 경로를 따라 상하좌우로 이동합니다. 손을 떼지 않고 방향을 바꾸거나 되돌아올 수 있으며, 빈 공간에서는 두 축을 함께 따라갑니다. 장애물·보드 경계는 통과하지 않습니다. 손을 떼면 칸에 맞추고, 탈출·합성은 해당 지점에 닿으면 즉시 확정합니다. 한 번의 드래그는 이동·되돌리기 1회이며, 원위치 복귀·취소는 이동을 소비하지 않습니다.
- 블록 선택 후 방향키·WASD·화면 화살표로도 이동합니다. 출구에 블록 전체 폭을 맞추고 같은 색 출구 밖으로 한 번 더 밉니다. 기호 ● ◆ ✦ ▲로 색을 구별할 수도 있습니다.
- 처음에는 `시작`을 누를 때까지 시간이 멈춥니다. 상단 모드명을 누르면 모드를 고르고, 일시 정지 메뉴에서 재시작·설정·일일 선물·별 보상·홈 복귀를 선택합니다. 게임 화면에는 HUD·보드·이동·아이템만 표시합니다.
- 컬러 탈출: 같은 색 출구로 모든 블록 탈출.
- 트리플 도크: 탈출한 블록을 7칸 도크에 수집, 같은 색 3개 자동 제거. 7번째 칸에서 매칭이 일어나면 매칭을 먼저 판정합니다.
- 머지 2048: 같은 색·숫자 블록을 밀어 합성. 숫자 4 이상만 탈출.
- 키 & 락: 각 색 열쇠 블록이 먼저 탈출하면 해당 출구 개방.
- 아이스 브레이크: 얼음 블록은 움직일 수 있지만 다른 블록 2개가 탈출해 두 겹을 벗겨야 출구를 통과합니다.
- 블록 팩토리: 초기 보드를 비운 뒤 4개의 추가 블록을 생성기에서 하나씩 공급. 블록을 중앙 패드의 왼쪽 위 칸(x=2, y=2 또는 4, 0부터 시작)에 맞춘 뒤 승강기 버튼/Space로 두 패드 사이를 이동합니다. 목적지가 비어 있어야 합니다.
- 각 모드는 별도 레벨 진도와 새로운 시드를 가집니다. 레벨을 진행하면서 블록 수와 섞는 이동 수를 늘리며, 무한히 서로 다른 배치 수를 보장하는 시스템은 아닙니다.

## 아이템·보상

해머(선택 블록), 프리즈(20초 타이머 보호), 가이드 빔(다음 이동), 리와인드(직전 이동), 마그넷(선택 색 전체) 5종을 즉시 사용합니다. 해머·마그넷은 먼저 아이템을 누른 뒤 블록을 선택할 수도 있습니다. 길게 누르면 소비 없이 효과를 설명합니다. 유효하지 않은 사용은 소비하지 않습니다. 되돌리기는 시간을 복원하지 않고 사용한 아이템도 환불하지 않으며, 시간만 정지하는 프리즈는 이동 기록에 넣지 않습니다.

초기 350 코인, 클리어 보상 90~130 코인, 일일 100 코인, 누적 별 3·9·18 보상, 1회 무료 스타터 번들, 400 코인 오로라 보드를 제공합니다. 별은 남은 시간 65초 초과면 3개, 25초 초과면 2개, 그 이하면 1개입니다. 이어하기는 보드 유지·45초 추가·수집 블록 구조함 보관, 비용 120/180 코인, 한 판 최대 2회입니다. 구조함의 색은 새 수집 블록과 함께 3개씩 매칭되어 조합이 사라지지 않습니다.

실제 결제·실제 광고·외부 분석 전송은 없습니다. 광고 보상 버튼은 데모이며 일일 선물과 지급 제한을 공유합니다. 한국 시간 자정 기준, 이 브라우저의 저장 기록으로 판정합니다. 상품 구성·부스터·이어하기·재방문 보상의 수익화 가설과 실제 운영 시 필요한 서버 검증은 제작 노트에 구분해 기록했습니다.

## 생성·저장·연출

- 블록 삽입과 유효한 이동을 역순으로 기록해 해답을 가진 보드를 생성합니다. 합성 기본 배치, 트리플 색 묶음, 열쇠·빙결의 선행 조건, 팩토리 공급을 해답에 포함합니다.
- 힌트는 생성 경로의 반복 상태를 건너뛰고, 경로 밖에서는 제한된 탐색으로 가까운 탈출 또는 합성을 찾습니다. 임의의 교착 보드까지 풀어주는 완전 탐색기는 아닙니다. 길을 찾지 못하면 아이템을 소비하지 않습니다.
- `localStorage`의 `block-bloom:v1`에 진행·코인·아이템·설정·되돌리기 기록을 저장합니다. 완료 보상과 완료 상태를 결과 창 전에 한 번에 저장해 새로고침 중복 지급을 막습니다. 이전 저장의 구조함 필드는 자동 보완하며, 이전 이어하기에서 사라진 색의 나머지를 복구합니다. 이미 빈 구형 보드의 완료도 복구합니다. 코인·설정은 유지합니다. 저장 차단·손상 시 새 판으로 플레이할 수 있으며 다른 기기와 동기화하지 않습니다.
- 파편·충격파·출구 잔상·보드 흔들림·점수 팝업·연속 탈출 콤보·피버·절차적 Web Audio 효과음·지원 기기 진동. 4초 이내 콤보, 5콤보부터 10초 피버·점수 2배입니다.
- 파티클 180개 상한과 오디오 노드 정리, 설정·시스템 동작 줄이기, 모달·숨겨진 탭에서 시간·연출 정지, 키보드·색상 기호를 지원합니다. 탭 전환 시 드래그를 취소하고, 페이지 이탈 시 타이머·효과·오디오·리스너를 정리합니다. bfcache 복귀는 시계를 한 개만 재개합니다. HUD는 바뀐 숫자만 갱신합니다.
- 모바일 우선 한 화면 배치, 동적 뷰포트·안전 영역, HUD 30~38px·행동 이름 18~22px·효과 설명 16px, 44px 이상 터치 영역을 제공합니다. 글꼴과 Kenney 아이콘의 출처·라이선스·사용 파일·가공 내용은 [리소스 안내](assets/README.md)에 있습니다.

## 검증

규칙 검증은 설치 없이 실행합니다.

```powershell
node --test games/block-bloom/rules.test.mjs
```

DOM 통합 검증은 테스트 전용 의존성을 사용합니다. Node.js 24 권장.

```powershell
cd games/block-bloom/tests
pnpm install --frozen-lockfile
pnpm test
```

32개 규칙·DOM 검증: 6개 모드 1,200개 보드의 전체 해답·시드 재현, 충돌·출구 폭·잘못된 출구, 합성·열쇠·빙결·7번째 매칭, 생성기·승강기, 힌트 종료, 아이템·경제·보상, 구조함 이어하기·구형 저장 복구, 시작 대기, 한 드래그 중 네 방향 전환·양 축 추종·장애물 우회·원위치 복귀·취소·되돌리기·탈출·합성·다중 포인터 차단·빠른 대각선 충돌·다른 입력과의 경합, 페이지 이탈·bfcache 복귀, 길게 누르기·비동기 힌트 취소, HUD 중복 갱신 억제, 파일·포트폴리오 연결.

브라우저 검증과 자체 평가의 구체적인 근거·한계는 [검토 기록](review.md)에 있습니다. 데스크톱 Chromium의 모바일 뷰포트 검증은 실제 휴대폰 Safari·Android Chrome, 진동·오디오 지연·프레임 성능을 증명하지 않습니다. 실제 결제·광고 SDK와 서버 저장은 대상이 아닙니다.

## 파일

`rules.mjs`: DOM과 분리된 순수 규칙·생성·힌트·보상·저장 검증. `game.mjs`: 입력·표시·연출·소리·경제 UI·저장. `index.html`, `styles.css`, `icon.svg`: 게임 화면과 직접 제작한 그래픽. `design.html`: 출처·수익화 가설·모드·기술 설계. `rules.test.mjs`, `tests/ui.test.mjs`: 규칙과 DOM 통합 검증.
