미니게임

이슬 모으기

토란잎을 기울여 흩어진 이슬방울을 굴려 하나로 합친다.

프롬프트를 복사해 claude.ai 에 붙여 넣으면 바로 실행됩니다 · Opus 5.5 · Effort High 기준

이슬 모으기 실행 화면

조작 폰 기울이기 · 화면 끌기 · 화살표 키(또는 W·A·S·D)

전체 화면으로

무대를 누르면 키보드로도 조작할 수 있습니다

권장 모델
Claude Opus 5.5 · Effort High
화면비
1:1 (정사각)
조작
폰 기울이기 · 화면 끌기 · 화살표 키(또는 W·A·S·D)
결과물
HTML 파일 하나 · 따로 설치할 것 없음

프롬프트

Claude 가 읽는 제작 지시문입니다. 맨 위 [바꿀 곳]의 값을 바꿔 붙여 넣어도 됩니다.

브라우저에서 바로 하는 미니게임 「이슬 모으기」를 HTML 파일 하나로 만들어 줘.

핵심 아이디어: 화면을 거의 다 채우는 토란잎 한 장 위에 이슬방울 여러 개가 흩어져 있다. 잎을 기울이면(화살표·끌기·폰 기울이기) 방울이 굴러가고, 두 방울이 닿는 순간 메타볼로 그린 물이 목처럼 이어졌다가 출렁 하나로 합쳐진다. 방울은 렌즈처럼 아래 잎맥을 굴절시켜 비춘다. 작은 방울은 잘 안 움직이고 잎맥 홈에 걸리며 벌레 먹은 구멍으로 빠지지만, 합쳐서 커진 방울은 미끄럽게 구르고 홈을 넘고 구멍 위를 건너간다. 시간 안에 잎 위의 물을 한 방울로 모으면 다음 잎으로 넘어간다.

시그니처 순간(이 작품의 얼굴): 페이지가 열리고 약 1.6초 뒤(1.0~2.5초 사이), 구경 모드에서 판 좌표 (0.41, 0.72) 근처 — 판 가운데에서 약간 왼쪽 아래 — 지름 0.068S 와 0.090S 인 두 방울이 서로 0.3r 까지 다가가 물의 목이 생기고, 닿는 순간 지름 0.113S 방울 하나로 합쳐지며 0.6초 동안 타원으로 출렁인다(가로세로 최대 ±28%). 합쳐진 방울 속에는 아래의 잎맥이 휘어져 비친다.

[바꿀 곳]
아래 값만 바꿔도 느낌이 달라지게, 모두 CONFIG 에 이름 붙여 둔다. (B = 게임판 한 변을 1 로 잡은 길이 단위. 게임판 한 변 = 화면 짧은 변 S 이므로 1B = S.)
- 방울 기본 반지름 r0 = 0.030B
- 첫 단계 방울 수 6, 단계마다 +1, 최대 12
- 첫 단계 제한 시간 30초, 단계마다 −2초, 최소 20초
- 기울기 최대일 때 중력 가속도 G = 1.2 B/s²
- 굴절 세기 refract = 0.035B
- 출렁임: 진폭 0.28, 진동수 7Hz, 감쇠 시간 0.35초
- 색: 잎 #7a8f68, 잎맥 #b5bf9b, 잎 가장자리 #4a5a40, 물 아래 바탕 #232b24, 바탕 먼 잎 그림자 #2f3a2c, 구멍 가장자리 #6b5a3e, 방울 하이라이트 #f4f7ee, 글자 #eef0e6, 강조색 #e2b65c(남은 시간 막대·점수 숫자만)
- 소리 크기(마스터 음량) 0.5

[크기]
- 게임판은 정사각형(1:1)이다. 한 변 S = min(창 너비, 창 높이). 판은 화면 가운데에 두고, 판 밖 남는 곳에도 같은 물 바탕과 먼 잎 그림자를 이어 그린다(빈 띠 금지).
- 판 좌표는 왼쪽 위 (0,0), 오른쪽 아래 (1,1), y 는 아래로 커진다.
- 토란잎 중심 C = (0.5, 0.5). 잎 윤곽은 극좌표 반지름 R(θ) = 0.45 × (1 − 0.35 × exp(−((θ − π/2) / 0.18)²)) — 거의 원이고 아래쪽(θ = π/2, 화면 아래 방향)에 잎자루 쪽으로 파인 홈(깊이 0.35×0.45 = 0.1575B, 그래서 홈 끝은 y ≈ 0.79)이 있다. 그림에는 여기에 0.006 × sin(9θ) 의 잔물결을 더하지만 물리 벽은 잔물결 없는 R(θ) 를 쓴다. θ 는 atan2(y−0.5, x−0.5).
- 잎은 지름 약 0.9S — 화면 짧은 변의 90% 를 채운다. 가운데 작은 그림으로 만들지 않는다.
- 방울 반지름: 처음 방울은 r0 × (0.8~1.2) 무작위, 즉 0.024~0.036B(지름은 화면 짧은 변의 약 5~7%). 합치면 넓이가 보존된다: r = √(r1² + r2²). 6방울을 다 모으면 r ≈ 0.073B(지름 약 0.15S).
- 구멍 반지름 hr = 0.040B + 0.003B × (단계 − 1), 최대 0.055B.
- 글자: 점수 0.05S, 안내 문구 0.045S, 끝 화면 제목 0.08S. 소리 단추는 화면 오른쪽 위 구석 44×44 CSS px.

[장면]
- 아래는 해 질 무렵 연못 물. #232b24 바탕에 아주 느린(주기 12초 이상) 물빛 일렁임을 밝기 ±4% 로 넣고, 판 바깥 쪽에는 흐릿한 다른 토란잎 그림자(#2f3a2c, 가장자리 부드럽게) 두세 장이 겹친다. 바탕은 채도가 낮다.
- 토란잎: #7a8f68 바탕, 가운데가 6% 밝고 가장자리로 갈수록 어두워진다. 표면은 왁스 같은 무광 — 아주 고운 점 무늬(밝기 ±3%)로 물이 스미지 않는 잎의 결을 낸다. 가장자리에는 #4a5a40 의 얇은 테두리(0.006B)와 바깥쪽 그림자.
- 잎맥: 잎자루가 붙는 점 P0 = (0.5, 0.53) 에서 다섯 굵은 잎맥이 방사형으로 잎 가장자리까지 뻗는다. 각도(화면 좌표, 0° = 오른쪽, 시계 방향 +): −90°(위로 곧게, 가운데 잎맥), −35°, −145°, +35°, +145°. 굵은 잎맥은 폭 0.012B 의 오목한 홈 — 한쪽 벽은 밝게(#b5bf9b), 반대쪽은 어둡게 그려 패인 느낌을 낸다. 굵은 잎맥 사이에는 가는 잎맥(폭 0.003B, #b5bf9b 를 40% 섞음)이 굵은 잎맥에서 바깥쪽으로 비스듬히 갈라진다. 가는 잎맥은 그림일 뿐 물리에 영향이 없다.
- 기울기 표시: 잎이 기운 쪽(낮은 쪽)은 8% 어둡고 반대쪽은 8% 밝게 빛 기울기가 바뀌며, 잎 전체가 기운 방향으로 최대 0.01B 밀려 보인다. 입력과 같은 프레임에 바뀐다.
- 구멍(2단계부터): 벌레 먹은 불규칙한 구멍. 윤곽은 반지름 hr 에 ±12% 의 울퉁불퉁함(각도의 사인 합 두세 개), 가장자리 0.008B 를 #6b5a3e 로 갈색 테두리, 구멍 안은 아래 물 바탕이 보인다.
- 이슬방울: 투명한 물. 메타볼로 그린다 — 닿기 직전 두 방울 사이에 물의 목이 생기고, 합쳐진 뒤에는 한 덩어리.
  · 방울 안에서는 아래 잎이 굴절되어 비친다: 방울 가장자리일수록 많이 휘고 가운데는 거의 그대로. 잎맥이 방울 속에서 휘어 보이는 것이 핵심이다.
  · 방울 안은 잎색보다 10% 밝고 살짝 푸르스름하며, 가장자리 0.15r 폭은 어두운 테(프레넬 느낌).
  · 왼쪽 위에서 빛이 온다: 방울 왼쪽 위에 작은 흰 하이라이트(#f4f7ee, 반지름 약 0.18r), 오른쪽 아래 잎 위에 방울이 모은 밝은 빛 자국(초승달, 밝기 +15%), 그 바깥 오른쪽 아래로 0.25r 어긋난 부드러운 그림자(잎 밝기 −25%).
  · 움직이는 방울은 속도 방향으로 늘어난다: 늘어남 = min(0.18, 속력 × 0.4), 그 수직으로는 같은 비율만큼 줄어든다.
  · 합쳐지는 순간 새 방울은 출렁인다: w(t) = 0.28 × sin(2π × 7 × t) × exp(−t / 0.35). 축은 두 방울을 잇는 방향. 0.6초면 거의 멎는다.
- 남은 시간: 판 맨 위 y = 0.03 높이에 판 너비 80% 의 가는 막대(높이 0.008S, 강조색 #e2b65c). 남은 5초부터 막대가 1초마다 한 번 깜박인다.
- 점수: 판 왼쪽 위 (0.06, 0.08) 에 강조색 숫자, 그 아래 작게 「잎 N」(단계). 최고 점수는 끝 화면에만.
- 판이 끝날 때(시간 끝): 남은 방울이 0.8초에 걸쳐 증발하듯 반지름이 0 으로 줄어든다. 구멍으로 빠지는 방울은 0.3초 동안 구멍 중심으로 빨려 들며 줄어들고, 아래 물에 작은 동그라미 물결 한 번(0.4초).
- 단계를 깼을 때: 마지막 한 방울이 크게 출렁이고 「+보너스」 숫자가 방울 위로 0.8초 떠오르며 사라진 뒤, 잎이 0.4초 어두워졌다 밝아지며 다음 잎(새 방울·새 구멍)이 나온다. 이 1.2초 동안 시간은 멈춘다.

[조작]
- 키보드: 화살표 ↑↓←→ 또는 W·A·S·D 를 누르고 있으면 그 방향으로 잎이 기운다(방울이 그쪽으로 굴러감). 두 키를 같이 누르면 대각선(크기는 1 로 맞춤). 기울기 벡터는 목표를 향해 초당 4 씩 따라가고(0 → 1 까지 0.25초), 키를 떼면 초당 2.5 씩 0 으로 돌아온다(0.4초). 키를 짧게 눌렀다 떼도 keydown 에서 기록해 최소 한 갱신은 기울기가 목표 쪽으로 움직인다.
- 터치·마우스 끌기: 화면 아무 곳이나 누른 채 끌면, 누른 점에서 손가락까지의 변위 ÷ (0.22S) 가 기울기 목표다(크기는 1 로 자름). 손을 떼면 키를 뗐을 때처럼 0.4초에 걸쳐 0 으로 돌아온다. 폰 세로 화면에서 엄지 하나로 된다.
- 폰 기울이기: deviceorientation 값이 실제로 들어오는(null 이 아닌) 기기에서는 gamma/25, (beta − 시작 때 beta)/25 를 기울기 목표로 쓴다(크기 1 로 자름). iOS 처럼 권한이 필요한 기기는 첫 탭 때 권한을 묻고, 거절되거나 오류가 나면 조용히 끌기만 쓴다.
- 우선순위: 눌린 키 > 끌고 있는 손가락 > 기기 기울기.
- 구경 모드에서 M 이 아닌 아무 키(화살표 포함)나 탭 → 새 판 시작. 시작시킨 그 입력 자체는 기울기로 쓰지 않는다(시작 탭이 끌기로 이어지면 그때부터는 끌기로 쓴다). 끝 화면에서도 M 이 아닌 아무 키나 탭 → 바로 새 판.
- M 키 또는 오른쪽 위 소리 단추 → 소리 켜고 끄기. 단추를 누른 탭은 게임 시작·끌기로 쓰지 않는다.

[규칙]
- 방울 물리(판 좌표 B 단위, 1/120초 갱신):
  · 기울기 벡터 tilt(크기 0~1)에 대해 방울이 받는 가속도 a = G × tilt (+ 잎맥 홈의 끌림, + 3단계부터 바람).
  · 크기에 따른 마찰: 정지 마찰 μs(r) = 0.30 × (r0 / r)², 0.04~0.30 으로 자름. 운동 마찰 μk = 0.5 × μs. 공기·물 저항 c(r) = 3.0 × √(r0 / r) (1/초).
  · 멈춰 있는 방울(속력 < 0.004 B/s)은 |a| ≤ μs × G 이면 그대로 있다. 그렇지 않으면 a − c × v − μk × G × (v 방향) 으로 움직인다. 최고 속력 0.8 B/s.
  · 검산: 처음 크기 방울(r = r0)은 μs = 0.30 이라 기울기 0.3 이상에서야 움직이고, 기울기 1 의 끝 속력은 1.2 × (1 − 0.15) / 3.0 = 0.34 B/s. 6방울을 다 모은 큰 방울(r ≈ 0.073)은 μs ≈ 0.05, c ≈ 1.92 → 끝 속력 ≈ 0.61 B/s. 큰 방울일수록 미끄럽다.
  · 잎 가장자리 벽: 방울 중심은 C 에서 R(θ) − r − 0.01 안에 머문다. 벽에 닿으면 벽 쪽 속도 성분을 −0.2 배로 튕긴다.
- 합치기: 두 방울 중심 거리 ≤ r1 + r2 이면 합친다. 새 반지름 √(r1² + r2²), 위치는 넓이 가중 평균, 속도는 넓이 가중 평균(운동량 보존). 틈(거리 − r1 − r2)이 0.25 × (r1 + r2)/2 보다 작으면 서로 1.5 B/s² 로 끌어당긴다(표면장력) — 목이 생기면 곧 붙는다.
- 잎맥 홈(굵은 잎맥 다섯 줄): 방울 중심이 잎맥 선에서 r 보다 가까우면 선 쪽으로 끌림 가속도 0.6 × G × min(1, 거리 / (0.5r)) 를 받는다. r < 0.045B(작은 방울)이면 그대로, 그 이상이면 0.2 배만. 홈 안의 방울은 잎맥 방향으로는 μs 가 절반이다. 그래서 작은 방울은 홈에 걸려 잎맥을 따라 미끄러지고, 홈을 가로지르는 기울기 성분이 0.6 을 넘어야 빠져나온다. 큰 방울은 거의 그냥 넘는다.
- 구멍: 방울 중심이 구멍 중심에서 hr 안에 들어오고 r < 1.3 × hr 이면 빠진다(0.3초 빨려 드는 연출 뒤 사라짐). r ≥ 1.3 × hr 인 큰 방울은 구멍 위를 다리처럼 건너가며, 그동안 방울 속에 구멍 아래 물이 비친다.
- 점수:
  · 합칠 때마다 +10 × k. k = 새 방울을 이루는 처음 방울 수(합칠 때 더해 간다). 6방울을 하나씩 다 모으면 10 × (2+3+4+5+6) = 200점.
  · 잎 위 방울이 1개만 남으면 그 단계를 깬다. 보너스 = 남은 초(내림) × 5 + 단계 × 50, 단 남은 물 비율(남은 넓이 ÷ 단계 처음 넓이)을 곱해 반올림.
- 판이 끝나는 때:
  · 남은 시간이 0 이 되면 0.8초 증발 연출 뒤 끝.
  · 구멍으로 빠져 남은 물이 단계 처음 넓이의 35% 밑으로 내려가면, 빠지는 연출(0.3초)이 끝난 뒤 끝.
  · 끝 연출 동안 state 는 'play', 연출이 끝나는 순간 'over'. 'over' 화면은 뜨는 즉시 입력을 받는다(대기 시간 없음).
- 단계별 난이도(n = 1, 2, 3 …):
  · 방울 수 = min(12, 5 + n), 구멍 수 = min(5, n − 1), 제한 시간 = max(20, 32 − 2n)초, 구멍 반지름은 [크기] 대로.
  · 바람(3단계부터): tilt 에 더하는 느린 흔들림 크기 min(0.2, 0.06 × (n − 2)), 방향은 sin(t × 0.37 + 시드), cos(t × 0.29 + 시드). 처음 크기 방울은 μs 0.30 이라 바람만으로는 안 움직이고 큰 방울만 밀린다.
  · 1단계(처음 30초)는 구멍이 없고 시간이 넉넉해 거의 지지 않는다. 2단계부터 구멍 1개, 그 뒤 단계마다 구멍 +1, 시간 −2초, 방울 +1.
- 방울 배치: 잎 중심에서 0.33B 안, 서로 틈 0.06B 이상, 구멍과는 hr + 0.05B 이상, 잎 가장자리와 0.06B 이상, 굵은 잎맥 선과는 r + 0.01B 이상(처음부터 홈에 끌려 혼자 움직이는 방울이 없게). 1단계는 왼쪽 절반(x < 0.5)에 방울이 2개 이상 있게 놓는다. 구멍은 잎 중심에서 0.12~0.32B, 서로 0.15B 이상, P0 에서 0.08B 이상, 가장자리에서 0.08B 이상. 배치가 200번 시도 안에 안 되면 조건을 하나씩 늦추되 console.warn 을 남긴다(최후에만).
- 입력이 없으면: 처음 크기 방울은 기울기 0 에서 움직이지 않으므로 1단계 30초가 다 가고 0.8초 증발 뒤 끝 — 약 31초. 어떤 단계에서도 40초를 넘지 않는다(최대 제한 시간 30초 + 연출 2초 안쪽).
- 기대 결과: 기본 설정에서 처음 하는 사람의 첫 판은 대개 2~4단계, 40~120초. 1단계는 보통 8~20초 안에 깬다.

[구경 모드]
- 페이지가 열리자마자 'demo'. 첫 프레임부터 잎과 방울 6개가 다 그려져 있다(빈 화면으로 시작하지 않는다).
- 첫 구경 판은 배치를 고정한다: 큰 방울 r = 0.045 를 (0.60, 0.72) 에, 작은 방울 r = 0.034 를 (0.48, 0.72) 에 두고(두 방울은 아래쪽 두 굵은 잎맥 사이의 빈 쐐기 안), 나머지 4방울과 구멍 1개는 고정 시드로 [규칙] 의 배치 조건대로 놓되 이 두 방울에서 0.12B 이상 떨어뜨린다.
- 구경 판의 기울기 대본: 0~0.4초는 0, 0.4~2.6초는 목표 (−0.5, 0)(왼쪽으로 반만). 작은 방울(μs ≈ 0.23)과 큰 방울(μs ≈ 0.13)이 함께 왼쪽으로 구르지만 큰 방울이 더 빨라(끝 속력 약 0.21 대 0.16 B/s) 뒤에서 따라잡는다 → 약 1.6초에 (0.41, 0.72) 근처에서 합쳐진다(검산: 그때까지 작은 방울은 약 0.12B, 큰 방울은 약 0.16B 굴러 x ≈ 0.36 과 0.44 에서 만나고, 넓이 가중 중심 x ≈ 0.41). 이것이 시그니처 순간이다.
- 2.6초 뒤부터는 컴퓨터가 0.5초마다 판단한다: 가장 큰 방울을 과녁으로, 과녁에서 가장 가까운 다른 방울을 고른 뒤, 그 방울에서 과녁 쪽 방향 × 0.85 를 기울기 목표로 둔다. 구멍에 빠질 수 있는 방울(r < 1.3hr)이 구멍에서 0.12B 안에 있고 그 방울의 움직임이 구멍 쪽(내적 > 0.5)이면 목표를 구멍에서 멀어지는 쪽으로 60° 돌린다. 기울기는 키보드와 같은 속도로 목표를 따라가 사람이 하는 것처럼 보인다.
- 구경 판을 깨면 1.5초 동안 큰 방울이 출렁이는 모습을 보여 준 뒤 시드를 하나 늘려 새 구경 판. 25초 안에 못 깨거나 물을 잃으면 그때도 새 구경 판.
- 판 아래쪽 (0.5, 0.90) 에 「눌러서 시작」(0.045S, #eef0e6, 1.2초 주기로 불투명도 0.55~1), 그 아래 작게 「화살표 · 끌기 · 폰 기울이기로 잎을 기울여 이슬을 한 방울로」. 글자 아래에는 잎 위에서도 읽히게 반투명 어두운 그림자(#232b24, 불투명도 0.5, 흐림 0.01S)를 깐다. 구경 모드에서도 점수 자리는 비워 두고 남은 시간 막대는 보인다.
- 구경 모드에서는 소리를 내지 않는다(첫 입력 전이므로).

[소리]
- 모두 WebAudio 로 합성한다. AudioContext 는 첫 키·탭 때 만들고, 그 전에는 소리를 내지 않는다. 마스터 음량 0.5.
- 합칠 때: 사인파 「톡」 — 주파수 880 × (r0 / 새 r)^0.8 Hz, 어택 5ms·감쇠 0.12초, 곧이어 같은 음에서 0.7 배로 0.2초 내려가는 낮은 「출렁」(음량 절반). 큰 방울일수록 낮은 소리.
- 구멍에 빠질 때: 600 → 150 Hz 로 0.25초 내려가는 사인파 + 짧은 걸러진 잡음.
- 벽에 부딪힐 때: 벽 쪽 속력 > 0.15 B/s 일 때만 아주 작은 딸깍(삼각파 2kHz, 20ms, 음량 0.1).
- 단계 깸: 5음계 세 음 올림(0.08초 간격). 남은 5초부터 1초마다 작은 똑딱. 판 끝: 두 음 내림.
- 오른쪽 위 소리 단추(44×44 CSS px, 반투명 원 안에 스피커 모양을 선으로)와 M 키로 끄고 켠다. 꺼지면 마스터 음량 0.

[구현]
- HTML 파일 하나로 만든다. 바깥 파일·글꼴·라이브러리·네트워크 요청을 쓰지 않는다(미리보기 칸에서 막힌다).
- 첫 <script> 맨 앞에 CONFIG 객체를 두고 [바꿀 곳]의 값과 이 글에 나온 숫자(속도·크기·색·시간)를 이름 붙여 모은다.
- 게임 진행은 requestAnimationFrame 의 타임스탬프로 고정 시간 간격(1/120초) 갱신을 돌린다. 한 프레임에 밀린 시간은 0.1초까지만 따라잡는다. setTimeout·setInterval·CSS 애니메이션으로 움직이지 않는다.
- 난수는 시드 고정 난수(mulberry32 등)만 쓰고, 판마다 시드를 하나씩 늘린다. Math.random 은 쓰지 않는다.
- 캔버스는 늘 창 전체 크기다. 창 크기가 바뀌면 다시 맞추고, 게임판 비율이 정해진 게임은 판을 가운데 두되 남는 곳에도 배경을 그린다(빈 띠를 두지 않는다). 스크롤이 생기지 않게 한다. devicePixelRatio 는 2 까지만 선명도에 반영한다.
- 키보드와 터치를 둘 다 받는다. 키 입력은 window 의 keydown·keyup 으로 받아, 화면을 먼저 누르지 않아도 첫 키가 먹게 한다. 짧게 눌렀다 뗀 키도 놓치지 않게 keydown 때 처리하거나 기록해 둔다. 터치는 페이지 스크롤·확대가 일어나지 않게 막는다(touch-action: none).
- 점수·상태를 window.__game = { state, score } 에 두고 매 프레임 갱신한다. state 는 'demo'(구경 모드)·'play'·'over' 셋 중 하나, score 는 숫자다.
- 열리자마자 'demo' — 컴퓨터가 스스로 플레이하는 구경 모드와 「눌러서 시작」 안내. 첫 키 입력이나 탭이면 새 판 'play'. 판이 끝나면 'over' 화면, 거기서 키 입력이나 탭이면 새 판. 'over' 화면은 뜨자마자 키 입력·탭을 받는다(입력을 막는 대기 시간을 두지 않는다). 끝나는 연출이 있으면 그동안은 state 를 'play' 로 두고, 연출이 끝나 입력을 받을 수 있게 된 때 'over' 로 바꾼다.
- 플레이 중 아무 입력이 없으면 늦어도 40초 안에 판이 끝난다.
- 브라우저 저장소(localStorage·sessionStorage·IndexedDB·쿠키)를 쓰지 않는다 — 미리보기 칸에서 막혀 오류가 난다. 최고 점수는 메모리에만 둔다.
- 소리는 WebAudio 로 합성한 소리만, 첫 입력 뒤에만 낸다. 화면 구석에 소리 끄기 단추(M 키도)를 둔다.
- 탭이 숨으면 멈추고 돌아오면 이어서 한다.
- 글자는 시스템 글꼴만 쓴다: 'Pretendard', 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans KR', sans-serif.
- 모든 함수·상수를 먼저 정의하고, 시작(초기화와 첫 requestAnimationFrame)은 스크립트 맨 끝에서 한 번만 부른다.
- 콘솔에 오류가 나지 않게 한다. 스스로 대조하는 표는 console.table, 어긋남은 console.warn 으로만 낸다.

이 작품만의 구현:
- 그림은 두 겹이다. 아래 겹은 WebGL1 캔버스 하나에 전체 화면 사각형 하나를 그리는 조각 셰이더로 배경·잎·잎맥·구멍·방울을 모두 그린다. 위 겹은 pointer-events: none 인 2D 캔버스로 점수·막대·글자만 그린다. 소리 단추는 DOM 단추(pointerdown 에서 stopPropagation).
- 셰이더 안에 leafColor(p) 함수(판 좌표 p → 배경/잎/잎맥/구멍 색)를 두고, 방울 굴절은 이 함수를 어긋난 좌표에서 한 번 더 불러 만든다. 잎 윤곽 R(θ)·잎맥 각도·P0 는 JS 물리와 셰이더가 같은 CONFIG 값을 쓴다(셰이더 문자열에 CONFIG 값을 끼워 넣는다).
- 판 좌표 변환: 화면 픽셀(CSS px) q 에 대해 p = (q − 판 왼쪽 위) / S. gl_FragCoord 는 y 가 위로 크므로 뒤집는다. 판 밖(p 가 0~1 밖)도 같은 배경 함수로 칠한다.
- uniform: 화면 크기, 판 위치·크기, 시간, tilt, 방울 배열 uDrops[24](vec4: x, y, r, w), uAxis[24](vec2: 늘어남 축 cos·sin), 방울 수, 구멍 배열 uHoles[6](vec3: x, y, hr), 구멍 수, 증발 정도. GLSL 반복문은 상수 상한(24, 6)으로 돌리고 개수를 넘으면 break.
- 메타볼 장(場): 방울 i 마다 늘어남 축으로 국소 좌표를 돌린 뒤 축 방향 성분은 ÷ (1 + w), 수직 성분은 × (1 + w) 해서(w > 0 이면 축 방향으로 길쭉, w < 0 이면 납작; 1 + w 는 0.7 아래로 내리지 않는다), d = 그 국소 거리, Ri = 1.6 × ri 로 fi = max(0, 1 − d²/Ri²)³. f = Σ fi. 문턱 T = (1 − 1/1.6²)³ = 0.609375³ ≈ 0.2263 — 이 문턱이면 홀로 있는 방울의 그림 반지름이 물리 반지름 r 과 정확히 같다(검산: d = r 일 때 1 − 1/2.56 = 0.609375). 같은 크기 두 방울은 틈이 약 0.3r 일 때(중심 거리 2.30r) 목이 생긴다: 각 기여 0.1131 → 1 − x = 0.4835 → x = 0.5165 → d = 1.15r.
- 방울 그리기: f ≥ T 인 곳이 물. 장의 기울기 g = ∇f 를 해석적으로 구하고(각 fi 의 미분 합), 가장자리 정도 e = 1 − smoothstep(T, T × 3.0, f). 굴절 좌표 p' = p + normalize(g) × e × refract 에서 leafColor 를 다시 불러 물 색을 만든다. 하이라이트·어두운 테·빛 자국·그림자는 [장면] 대로. 그림자는 p − (0.25r 쯤의 고정 오프셋 (0.012, 0.012)) 에서 장을 한 번 더 재서 0.6T~T 사이를 부드럽게 어둡게 한다. 물 경계는 1.5px 폭으로 부드럽게 섞는다.
- 출렁임 w 와 속도 늘어남은 JS 에서 방울마다 계산해 uniform 으로 넘긴다: w = 출렁임 + 속도 늘어남, 축은 출렁임 중이면 합친 축, 아니면 속도 방향.
- 물리는 셰이더와 따로 JS 에서 [규칙] 대로 돌린다. 물리 한 단계 함수 stepWorld(world, tilt, dt) 는 그리기·소리·DOM 과 떨어진 순수 함수로 만들고(사건은 반환값 목록으로), 게임·구경 모드·자가 대조가 모두 이것을 쓴다.
- WebGL 을 얻지 못하거나 셰이더 컴파일이 실패하면 — 최후에만, console.warn 과 함께 — 2D 캔버스로 잎·잎맥·구멍과 방사형 그라디언트 원 방울을 그리는 대체 그림으로 이어 간다. webglcontextlost 는 preventDefault 하고 복구되면 다시 만든다.
- 시작할 때 자가 대조를 console.table 로 한 번 내고, 어긋나면 console.warn:
  1) 홀로 있는 방울 문턱: (1 − 1/1.6²)³ 가 0.2263 ± 0.001.
  2) 구경 판 첫 합침 시각: stepWorld 로 구경 판을 기울기 대본대로 4초 돌려 첫 합침이 1.0~2.5초 사이, 위치가 (0.41, 0.72) 에서 0.08B 안.
  3) 1단계 왼쪽 기울이기: 시드 1 의 1단계를 기울기 (−1, 0) 으로 2.5초 돌리면 합침 1번 이상.
  4) 입력 없음: 시드 1 의 1단계를 기울기 0 으로 10초 돌려 어떤 방울도 0.01B 넘게 움직이지 않음, 그리고 제한 시간 30초 + 증발 0.8초 ≤ 40초.
  5) 끝 속력: r0 방울을 기울기 1 로 3초 → 0.34 ± 0.03 B/s.
  6) 최대 방울 수 12 ≤ uniform 상한 24, 최대 구멍 수 5 ≤ 6.
- 렌더 해상도는 devicePixelRatio(최대 2) × 창 크기. 프레임이 계속 느리면(평균 30ms 넘게 2초) 셰이더 해상도만 0.75 배로 낮추고 console.warn 한 번.
- 탭이 숨으면(visibilitychange) 갱신을 멈추고 AudioContext 도 suspend, 돌아오면 밀린 시간을 버리고 이어 간다.

[하지 말 것]
- 반짝이 입자·물보라 입자를 흩뿌리지 않는다 — 방울의 굴절과 출렁임이 주인공인데 입자가 눈을 뺏는다. 구멍에 빠질 때 물결 한 번이 전부다.
- 렌즈 플레어·빛 번짐(bloom)·네온 발광을 넣지 않는다 — 해 질 녘 연못의 차분한 빛이 깨지고 물이 플라스틱처럼 보인다.
- 방울을 테두리 선이 있는 원이나 단색 동그라미로 그리지 않는다 — 메타볼로 이어지는 목과 굴절이 이 작품의 전부다.
- 바탕을 남청색·고채도 색으로 칠하지 않는다 — 잎의 초록과 방울의 투명함이 묻힌다. 강조색 #e2b65c 는 시간 막대와 점수 숫자에만.
- 화면 모서리에 제목·버전·꾸밈 라벨을 붙이지 않는다 — 점수·단계·시간 막대·소리 단추 말고는 글자가 없다.
- 잎을 작게 가운데 두지 않는다 — 잎 지름은 화면 짧은 변의 90%.
- 벌레·개구리·캐릭터를 그리지 않는다 — 잎과 물만으로 된 장면이다. 구멍은 벌레 먹은 자국일 뿐 벌레는 없다.
- 바깥 글꼴·이미지·라이브러리를 불러오지 않는다 — 미리보기 칸에서 막혀 깨진다.
- 방울끼리 당구공처럼 튕기게 하지 않는다 — 닿으면 언제나 합쳐진다.
- Math.random·setTimeout·setInterval·CSS 애니메이션을 쓰지 않는다 — 같은 시드에서 같은 판이 나와야 하고 움직임은 고정 간격 갱신에서만 나온다.
- 'over' 화면에 입력을 막는 대기 시간을 두지 않는다 — 끝나는 연출은 'play' 상태에서 끝낸다.
- console.error 를 쓰지 않는다 — 어긋남은 console.warn 으로만.

사용 방법

필요한 것: claude.ai 계정 — 무료 계정에서도 Claude Opus 5.5 를 고를 수 있습니다

  1. claude.ai 에서 새 대화를 엽니다.
  2. 모델 메뉴에서 Claude Opus 5.5 를 고르고, 같은 메뉴의 Effort(답변 깊이)를 High 로 둡니다.
  3. 복사한 프롬프트를 붙여 넣고 전송합니다. 결과로 나온 HTML 파일을 브라우저로 열면 바로 해 볼 수 있습니다.

추가 요청 예시

결과가 나온 뒤 같은 대화에서 이어서 요청하면 해당 부분만 수정됩니다.

  • 잎을 연잎으로 바꾸고 방울을 조금 더 크게 해 줘
  • 단계가 오를 때마다 빗방울이 떨어져 새 방울이 생기게 해 줘
  • 남은 시간이 10초 아래로 내려가면 화면 가장자리를 붉게 깜빡여 줘

미니게임

같은 분류의 다른 작품

미니게임 전체 보기

모든 게임·3D 보기 AI 레시피 전체 RSS 로 새 글 받기