H5 게임 에셋 파이프라인 종합 스킬. AI 이미지 생성 (나노바나나) + 이중 LLM + 픽셀아트 + SVG/Canvas/CSS 패턴. 에셋 품질 최우선.
game-developer 에이전트가 게임 에셋을 생성하고 빌드 결과물을 배포할 때 참조하는 통합 스킬입니다. 기술 스택 무관 — Phaser, PixiJS, 순수 Canvas, DOM+CSS 모두 지원합니다.
사이즈 제약이 해제되었습니다. 에셋 품질이 최우선입니다.
| 우선순위 | 방법 | 적합한 에셋 | 품질 |
|---|---|---|---|
| 1순위 | AI 이미지 생성 (나노바나나) | 캐릭터, 적, 배경, 아이콘 | ★★★★★ |
| 2순위 | 이중 LLM 파이프라인 (generate-assets.sh) | SVG 아이콘, UI 요소, 간단한 스프라이트 | ★★★★ |
| 3순위 | 픽셀아트 (Pattern A-Pixel) | 레트로풍 캐릭터, 작은 스프라이트 | ★★★★ |
| 4순위 | Canvas Graphics / SVG inline | 파티클, 이펙트, 기하학적 UI | ★★★ |
| 5순위 (최후) | 단순 도형 조합 |
| 프로토타입 전용 — 배포 금지 |
| ★ |
절대 금지: 단순 fillCircle + fillRect 조합만으로 캐릭터/적 에셋을 만들어 배포하지 마세요.
nanobanana-gen.sh 스크립트로 호출합니다. 무료이므로 적극 사용하세요.
# 게임 캐릭터 생성
zsh /opt/h5dir/scripts/nanobanana-gen.sh \
--prompt "pixel art vampire lord character, gothic style, dark red cape, glowing red eyes, game sprite, transparent background" \
--output "$RUN_DIR/games/$SLUG/src/assets/player.png"
# 배경 생성
zsh /opt/h5dir/scripts/nanobanana-gen.sh \
--prompt "dark gothic castle interior, eerie purple lighting, game background" \
--output "$RUN_DIR/games/$SLUG/src/assets/bg.png" \
--aspect-ratio "9:16"
# 적 캐릭터 생성
zsh /opt/h5dir/scripts/nanobanana-gen.sh \
--prompt "holy knight character, white armor, golden cross shield, game sprite, transparent background" \
--output "$RUN_DIR/games/$SLUG/src/assets/enemy-knight.png"
# Recraft (벡터/아이콘 특화)
zsh /opt/h5dir/scripts/nanobanana-gen.sh \
--prompt "blood orb icon, red glowing sphere, game UI" \
--output "$RUN_DIR/games/$SLUG/src/assets/blood-orb.png" \
--provider recraft
| Provider | 엔드포인트 | 특징 | 추천 용도 |
|---|---|---|---|
| gemini (기본) | gen/request/image/gemini | 빠름, 범용 | 캐릭터, 배경, 스프라이트 |
| recraft | gen/request/image/recraft | 벡터/아이콘 특화 | UI 아이콘, 아이템 |
| grok | gen/request/image/grok | 창의적 | 컨셉 아트, 특수 이펙트 |
| gpt | gen/request/image/gpt | 고품질 | 메인 캐릭터, 키 비주얼 |
| alibaba | gen/request/image/alibaba | 다양한 스타일 | 배경, 환경 |
| modelark | gen/request/image/modelark | Seedream | 실험적 |
// Phaser에서 AI 생성 이미지 로드
preload() {
this.load.image('player', 'assets/player.png');
this.load.image('enemy_knight', 'assets/enemy-knight.png');
this.load.image('bg_castle', 'assets/bg.png');
}
게임 에셋 생성 시 프롬프트에 반드시 포함:
나노바나나 실패 시:
02-spec.md의 Assets Needed 테이블
→ Grok: 창의적 에셋 코드 생성 (SVG/Canvas Graphics/CSS)
→ Claude: 기술 검증 + 위생 검사 (sanitization)
→ {RUN_DIR}/assets/ 에 저장
→ 게임 로딩 단계에서 로드 (Phaser LoadScene, 순수 JS 초기화, CSS import 등)
zsh /opt/h5dir/scripts/generate-assets.sh "$RUN_DIR"
실행 후 {RUN_DIR}/assets/manifest.json 생성 여부 확인.
| manifest status | 의미 | 사용 패턴 |
|---|---|---|
dual_reviewed | Grok 생성 + Claude 검증 완료 | Pattern D (Vite ?raw import) |
grok_only | Grok 생성만 완료 (Claude 검증 실패) | Pattern D (주의하여 사용) |
grok_failed | Grok 생성 실패 | Pattern A/B/C 폴백 |
sanitization_failed | 위생 검사 실패 | Pattern A/B/C 폴백 |
| manifest 없음 | generate-assets.sh 미실행 또는 실패 | Pattern A/B/C 폴백 |
기술 스택에 맞는 방법을 선택합니다. 스펙의 Generation Method 컬럼이 최우선.
| 에셋 유형 | Phaser/Canvas | DOM+CSS | 이유 |
|---|---|---|---|
| 플레이어/적 캐릭터 | Pixel Art / SVG inline | CSS shape + SVG | 경량, 캐릭터성 |
| 배경, 타일 | Canvas Graphics / Pixel Art | CSS gradient / background-image | 반복 패턴 |
| 아이콘, UI 요소 | SVG inline | CSS + HTML (unicode, SVG) | 해상도 독립 |
| 폭발, 불꽃, 파티클 | Canvas particle / Phaser.Particles | CSS animation + JS | 성능 중요 |
| 총알, 투사체 | Pixel Art / fillRect | CSS border-radius | 2-4px로 충분 |
스펙의 Generation Method 컬럼을 항상 최우선 — 이 테이블은 스펙에 없는 경우의 기본값.
아트 스타일이 02-spec.md에 별도 명시되어 있으면 그 스타일을 따름.
모든 게임 엔티티는 형태(shape) + 색상(hue) + 크기(size) 세 가지 모두로 구분 필수.
| 에셋 역할 | 형태(Shape) | 권장 색상 | 절대 금지 |
|---|---|---|---|
| 플레이어 | polygon/path (비대칭 권장) | 파란/흰 (#00aaff) | 단순 원 단독 사용 |
| 적/장애물 | 플레이어와 다른 형태 | 빨간/주황 (#ff4444) | 플레이어와 동일 형태 |
| 수집/보너스 | 위 둘과 다른 형태 | 노란/초록 (#ffdd00) | 위 형태 재사용 |
| 배경 | rect 허용 | 어두운 (#0a0a1a) | 게임 오브젝트와 명도차 < 30% |
밝기 계층:
Phaser 사용 시 LoadScene의 create(), 순수 Canvas 사용 시 초기화 함수에서 fillRect를 1px 단위로 찍어 픽셀아트를 생성.
도트 스프라이트는 작은 해상도(8×8 ~ 32×32)로 만들고 NEAREST 스케일링으로 확대.
create() {
const gfx = this.make.graphics({ add: false });
// --- 도트 플레이어 (16x16 → 게임에서 32x32로 표시) ---
const playerPixels = [
'....BBBB....',
'...BBWWBB...',
'..BBWWWWBB..',
'..BWWCCWWB..',
'..BWCCCWWB..',
'..BBWWWWBB..',
'...BWWWB....',
'..BBBWBBBB..',
'.BB.BWB.BB..',
'BB..BWB..BB.',
'B...BBB...B.',
'....B.B.....',
'...BB.BB....',
];
// 색상 맵: B=outline, W=skin, C=eye
const colorMap = { B: 0x1a1a2e, W: 0x55ccff, C: 0xffffff };
playerPixels.forEach((row, y) => {
[...row].forEach((ch, x) => {
if (ch !== '.' && colorMap[ch]) {
gfx.fillStyle(colorMap[ch]);
gfx.fillRect(x, y, 1, 1);
}
});
});
gfx.generateTexture('player', 16, 16);
gfx.clear();
// --- 도트 적 (12x12) ---
const enemyPixels = [
'..RRRRRR..',
'.RROORROOR.',
'RRRRRRRRRR',
'RRRRRRRRRR',
'R.RRRRRR.R',
'..R.RR.R..',
];
const eColorMap = { R: 0xff4444, O: 0xffffff };
enemyPixels.forEach((row, y) => {
[...row].forEach((ch, x) => {
if (ch !== '.' && eColorMap[ch]) {
gfx.fillStyle(eColorMap[ch]);
gfx.fillRect(x, y, 1, 1);
}
});
});
gfx.generateTexture('enemy', 12, 12);
gfx.clear();
// --- 도트 수집 아이템 (8x8) ---
gfx.fillStyle(0xffdd00);
[
[3,0],[4,0],
[2,1],[3,1],[4,1],[5,1],
[1,2],[2,2],[3,2],[4,2],[5,2],[6,2],
[1,3],[2,3],[3,3],[4,3],[5,3],[6,3],
[2,4],[3,4],[4,4],[5,4],
[3,5],[4,5],
].forEach(([x,y]) => gfx.fillRect(x, y, 1, 1));
gfx.generateTexture('coin', 8, 8);
gfx.clear();
gfx.destroy();
this.scene.start('MenuScene');
}
도트 에셋 필수 설정 — Phaser config 또는 개별 스프라이트:
// 방법 1: 글로벌 (main.js Phaser config)