한국어 번역
Vanilla JavaScript와 Canvas 2D를 사용해, 주황색 픽셀 캐릭터가 우주 공간의 무지개 바닥을 초고속으로 달려 나가며, 잇따라 덮쳐오는 운석과 빔을 멋지게 계속 회피하는 애니메이션을 단일 자기 완결형 HTML 파일로 만들어 주세요. 외부 에셋, 라이브러리, 네트워크 요청은 일절 사용하지 마세요. 조작은 필요 없으며, 캐릭터가 자동으로 계속 회피하는 데모로서 매끄럽게 루프되게 하세요.
렌더링
- 모든 것을 160x90의 고정 논리 해상도 오프스크린 캔버스에 그린 뒤, 그것을 풀스크린 표시용 캔버스로 전사한다. 확대율은 창에 들어가는 최대 정수배로 하고, 중앙에 배치한다. 여백은 검정으로 채운다. imageSmoothingEnabled = false, CSS는 image-rendering: pixelated를 지정할 것.
- 모든 드로잉은 논리 캔버스 위의 정수 좌표에 스냅시킨다. 서브픽셀 위치, 안티에일리어싱, 그라디언트, shadowBlur, 회전 드로잉은 사용하지 않는다.
- 약 32색의 고정 팔레트를 사용한다: 우주 배경용 검정~짙은 남색·보라 계열, 캐릭터용 주황 계열 3단계(본체 #CD7B5E 부근, 밝은 하이라이트, 어두운 그림자)와 눈의 검정, 무지개 바닥용 7색(빨강·주황·노랑·초록·하늘색·파랑·보라)과 각각의 어두운 색, 운석용 암석색·용암색, 빔용 흰색·시안·마젠타. 모든 픽셀은 이 팔레트의 색에서만 가져올 것.
캐릭터
- 다음 12x8 픽셀 실루엣을 정확히 재현한다(1칸 = 논리 1픽셀):
- 몸통은 너비 8 × 높이 8의 사각형(열 2~9).
- 팔은 몸통의 좌우로 너비 2 × 높이 2로 튀어나온다(열 0~1과 열 10~11, 행 2~3).
- 눈은 검정 1x1 픽셀 두 개, 행 1의 열 3과 열 8.
- 다리는 행 6~7에 4개, 각 너비 1(열 2·4·7·9). 다리 사이는 배경색으로 비운다.
- 단색 채우기가 아니라, 위쪽 변과 왼쪽 변에 1px 하이라이트, 아래쪽 변과 오른쪽 변에 1px 그림자색을 넣어 16비트풍 입체감을 낸다.
- 달리기 모션은 다리 4개를 2개씩 번갈아 위아래로 움직이는 4프레임 사이클. 속도에 따라 사이클을 빠르게 한다.
- 포즈를 파라미터화한다(상하 바운스, 앞쪽 기울기, 스쿼시 앤 스트레치, 팔의 상하). 스쿼시 앤 스트레치는 너비·높이를 정수 픽셀 단위로 1~2px 바꾸는 것만으로 표현한다. 파라미터는 매끄럽게 보간하면서도 매 프레임 픽셀 그리드에 양자화해, 60fps 루프에서도 12fps 전후의 도트 애니메이션처럼 보이게 할 것.
무지개 바닥
- 캐릭터는 화면 왼쪽 1/3 부근에서 오른쪽 방향으로 달리는 횡스크롤 구성. 바닥은 7색 가로 줄무늬로 된 무지개 띠(각 색 1~2px)이며, 화면을 가로질러 뻗고, 완만하게 굽이친다(사인파로 위아래로 커브).
- 바닥의 세로 방향으로 일정 간격의 구분선(어두운 색 세로 라인)을 넣고, 속도에 따라 왼쪽으로 고속 스크롤시켜 질주감을 낸다.
- 바닥 아랫변에서는 무지개색 빛 입자가 뒤쪽으로 흘러 떨어져, 바닥이 우주에 떠 있음을 보여준다.
- 때때로 바닥에 점프대(위쪽으로 굽은 커브)나 끊김(갭)을 내어 점프의 볼거리를 만든다.
장애물
- 운석: 대·중·소 3가지 크기. 도트 그림 암석(아웃라인 + 2단계 음영 + 용암색 균열)으로, 화면 오른쪽 위에서 대각선으로 날아온다. 뒤에 용암색→어두운 색으로 변하는 불꽃 꼬리를 끈다. 피한 운석은 바닥에 충돌하지 않고 화면 밖으로 빠져나가거나, 뒤쪽에서 파편으로 부서져 흩어진다.
- 빔: 출현 전 예고로 1px 점멸 라인(마젠타)을 0.5초 정도 표시하고, 그 뒤에 흰색 심 + 시안 외곽으로 된 두께 3~5px의 빔이 수평 또는 대각선으로 조사된다. 조사 중에는 끝이 지지직거리며 흔들린다.
- 장애물은 무작위가 아니라, 미리 정한 '공격 패턴'을 순서대로 흘려보내고, 전체가 일정 시간에 루프되도록 설계한다(예: 운석 단발 → 운석 3연속 → 낮은 빔 → 높은 빔 → 빔과 운석의 복합 → 대형 운석 + 바닥 갭).
회피 액션
- 점프: 스쿼시로 모았다가 → 스트레치로 도약 → 공중에서 몸을 움츠림 → 착지에서 스쿼시 + 모래 먼지 아닌 무지개색 불꽃.
- 2단 점프: 공중에서 잠깐 멈췄다가 재가속. 캐릭터 주위로 무지개색 링이 1px로 퍼진다.
- 슬라이딩: 높이를 거의 절반까지 스쿼시해 저공 자세로 미끄러지고, 바닥과의 접지면에서 불꽃을 튀긴다.
- 대시 회피: 한순간만 속도를 크게 올리고, 뒤쪽에 잔상을 3~4개 남긴다. 잔상은 무지개 7색을 차례로 사용하며, 팔레트의 어두운 색으로 단계적으로 사라진다.
- 각 공격 패턴에는 그것에 가장 멋져 보이는 회피 액션을 할당한다. 회피는 아슬아슬한 타이밍(니어 미스)에 할 것.
상태 머신
- RUN(보통 질주) → WARN(예고 표시, 캐릭터가 잠깐 앞을 보는 듯 눈을 1px 움직인다) → DODGE(회피 액션) → NEAR_MISS(연출) → RUN으로 복귀, 를 공격 패턴마다 반복한다.
- 루프의 마지막에는 BOOST(전력 가속) → WARP(화면 전체가 흰색→무지개색으로 한순간 플래시)를 넣고, 그대로 시작 부분의 RUN에 자연스럽게 이어지게 한다.
- 포즈나 카메라의 파라미터는 키프레임 사이에서 이징을 건다.
카메라워크
- 카메라는 논리 좌표 위의 정수 오프셋으로 다룬다. 줌이나 회전은 쓰지 않고, 위치 이동과 흔들림만으로 표현한다.
- 추종: 캐릭터의 상하 이동을 댐핑을 걸어 늦게 따라가고, 점프 시에는 조금 늦게 올라간다.
- 선행: 속도가 올라갈수록 카메라를 진행 방향으로 수 px 앞서게 해, 캐릭터가 화면 왼쪽으로 밀리게 하여 가속감을 낸다.
- 히트스톱: 니어 미스 순간에 3~4프레임만 전체를 정지시키고, 그 뒤 0.3초 정도 슬로모션(업데이트 스텝을 솎아냄)으로 만든 뒤 보통 속도로 돌아간다.
- 셰이크: 대형 운석의 통과나 빔 조사 시작 시 1~2px의 화면 흔들림. 흔들림은 정해진 패턴 배열에서 읽어 오고, 난수는 쓰지 않는다.
- BOOST 중에는 카메라를 약간 내려, 바닥이 차지하는 면적을 늘려 속도감을 강조한다.
질주감을 내는 이펙트
- 다층 패럴랙스: 먼 별(거의 움직이지 않는 1px 점), 중경 별(속도에 따라 옆으로 2~6px의 선으로 늘어남), 근경 스피드 라인(밝은 색 가로선이 화면을 고속으로 가로지름)의 3층.
- 스피드 라인의 개수와 길이는 속도에 비례시키고, BOOST 중에는 최대로 한다.
- 배경에 큰 행성이나 성운을 도트 그림으로 1~2개 배치하고, 아주 천천히 스크롤시켜 스케일감을 낸다.
- 니어 미스 시에는 캐릭터 윤곽을 1px 흰색으로 테두리 치고, 운석·빔에 가까운 쪽만 한순간 빛나게 한다.
- 착지·슬라이딩·대시의 불꽃, 운석의 꼬리, 파편, 바닥에서 흘러 떨어지는 빛 입자는 모두 같은 파티클 시스템으로 다룬다.
파티클 시스템
- 풀 방식으로 할당이 없는 파티클 시스템: 미리 확보해 재사용한다.
- 각 파티클은 종류별로 색 전이 테이블(팔레트 인덱스 열)을 가지고, 수명에 따라 단계적으로 색을 바꾸며 소멸한다(예: 불꽃은 흰색 → 노랑 → 주황 → 어두운 색, 잔상은 무지개색 → 어두운 색).
- 그릴 때에는 파티클 위치를 그리드에 스냅시킨다.
- 60Hz 고정 타임스텝으로 업데이트하고, 그리기는 rAF로 한다. 루프 내에서의 객체 생성은 0으로 할 것(배열·클로저·문자열 연결 생성도 포함).
씬
- 배경은 깊은 우주: 검정에서 남색으로의 단계적 띠(디더링으로 색 경계를 표현), 반짝이는 별, 먼 행성.
- 캐릭터·장애물·바닥의 색이 배경에 묻히지 않도록 명도차를 뚜렷하게 한다. 화면이 아무리 요란해도 캐릭터의 실루엣이 한눈에 읽혀야 한다.
품질 기준
- 어떤 창 크기에서도 픽셀이 또렷할 것, 루프가 끊기지 않을 것, 안정된 60fps, 읽기 쉬운 실루엣.
- 벡터 도형을 축소한 것이 아니라, 세련된 16비트 시대 액션 게임의 데모 화면처럼 보일 것.
- '빠르다', '아슬아슬하게 피했다', '멋있다' 세 가지가 매번의 회피에서 전달될 것.