Create a single self-contained HTML file that renders an animated pixel art wizard casting a spell, using vanilla JavaScript and Canvas 2D. No external assets, libraries, or network requests.
RENDERING
- Draw everything to an offscreen canvas at a fixed logical resolution of 128x96, then blit to a fullscreen display canvas scaled by the largest integer factor that fits the window, centered, with imageSmoothingEnabled = false and CSS image-rendering: pixelated.
- All drawing snaps to integer coordinates on the logical canvas. No sub-pixel positions, anti-aliasing, gradients, or shadowBlur.
- Fixed palette of ~24 hex colors: deep blues/purples for night sky, warm robe tones, 3-4 bright magic colors. Every pixel comes from this palette.
CHARACTER
- Build the wizard procedurally from filled rects and pixel runs, ~24x32 logical pixels: pointed hat with a bend, long beard, two-shade robe with darker outline, staff with a gem at the tip.
- Parameterize the pose (staff angle, arm raise, head tilt, robe sway). Animate parameters smoothly, then quantize to the pixel grid each frame so motion reads at an 8-12 fps pixel animation feel even though the loop runs at 60fps.
ANIMATION
- Looping state machine: IDLE (2-frame bob, beard sway) -> CHARGE (staff raises, gem flickers, sparks spiral inward) -> CAST (bright burst, projectile fires across the scene, 1-2 pixel screen shake) -> RECOVER (settle back). Ease pose parameters between keyframes.
- Pooled allocation-free particle system: preallocate and reuse. Sparks orbit the gem during CHARGE, explode outward on CAST, each particle stepping its palette index from white to magic color to dark before despawn. Snap particle positions to the grid when drawing.
- Fixed 60hz timestep update with rAF rendering. Zero object allocation inside the loop.
SCENE
- Minimal background: dark sky, a few twinkling 1px stars, moon, stone floor line. Character silhouette must read clearly.
- Subtle 1px rim light on the wizard from the gem, brightening during CHARGE and CAST.
QUALITY BAR
- Crisp pixels at any window size, seamless loop, stable 60fps, readable silhouette. Should look like a polished 16-bit sprite animation, not vector shapes scaled down.
한국어 번역
바닐라 JavaScript와 Canvas 2D를 사용해, 주문을 시전하는 픽셀 아트 마법사의 애니메이션을 렌더링하는 단일 자체 완결형 HTML 파일을 만드세요. 외부 에셋, 라이브러리, 네트워크 요청은 없습니다.
렌더링
- 모든 것을 128x96의 고정 논리 해상도로 오프스크린 캔버스에 그린 다음, 창에 맞는 가장 큰 정수 배율로 확대하고 중앙에 배치한 전체 화면 디스플레이 캔버스로 블릿하세요. imageSmoothingEnabled = false, CSS image-rendering: pixelated를 사용합니다.
- 모든 그리기는 논리 캔버스의 정수 좌표에 스냅됩니다. 서브픽셀 위치, 안티앨리어싱, 그라디언트, shadowBlur는 없습니다.
- 약 24개의 헥스 색상으로 이루어진 고정 팔레트: 밤하늘용 짙은 파랑/보라, 따뜻한 로브 톤, 3-4개의 밝은 마법 색상. 모든 픽셀은 이 팔레트에서 나옵니다.
캐릭터
- 마법사를 채워진 사각형과 픽셀 런으로 절차적으로 구성하세요. 약 24x32 논리 픽셀: 굽은 뾰족 모자, 긴 수염, 더 어두운 외곽선이 있는 두 가지 색조의 로브, 끝에 보석이 달린 지팡이.
- 포즈를 매개변수화하세요(지팡이 각도, 팔 올림, 머리 기울임, 로브 흔들림). 매개변수를 부드럽게 애니메이션한 다음, 매 프레임 픽셀 그리드로 양자화해서 루프가 60fps로 돌더라도 8-12 fps 픽셀 애니메이션 느낌으로 움직임이 읽히게 하세요.
애니메이션
- 루핑 상태 머신: IDLE(2프레임 흔들림, 수염 흔들림) -> CHARGE(지팡이 상승, 보석 깜박임, 불꽃이 안쪽으로 나선형으로 모임) -> CAST(밝은 폭발, 발사체가 장면을 가로질러 발사, 1-2픽셀 화면 흔들림) -> RECOVER(제자리로 복귀). 키프레임 사이에서 포즈 매개변수에 이징을 적용하세요.
- 풀링된 무할당 파티클 시스템: 미리 할당하고 재사용하세요. CHARGE 동안 불꽃이 보석 주위를 궤도로 돌고, CAST에서 바깥으로 폭발하며, 각 파티클은 소멸 전에 팔레트 인덱스를 흰색에서 마법 색상으로, 다시 어두운 색으로 이동시킵니다. 그릴 때 파티클 위치를 그리드에 스냅하세요.
- rAF 렌더링과 함께 고정 60hz 타임스텝 업데이트. 루프 내부에서 객체 할당은 전혀 없습니다.
장면
- 최소한의 배경: 어두운 하늘, 몇 개의 반짝이는 1px 별, 달, 돌 바닥 선. 캐릭터 실루엣이 명확하게 읽혀야 합니다.
- 보석에서 나오는 마법사 위의 미묘한 1px 림 라이트. CHARGE와 CAST 동안 밝아집니다.
품질 기준
- 어떤 창 크기에서도 선명한 픽셀, 매끄러운 루프, 안정적인 60fps, 읽히는 실루엣. 축소된 벡터 도형이 아니라 잘 다듬어진 16비트 스프라이트 애니메이션처럼 보여야 합니다.