diff --git a/docs/character-design-guide.md b/docs/character-design-guide.md new file mode 100644 index 0000000..f8bbe60 --- /dev/null +++ b/docs/character-design-guide.md @@ -0,0 +1,260 @@ +# Archetype-FirstSpark 캐릭터 디자인 가이드 + +## 1. 기준 스타일 (Ember_Origin.jpg 기반) + +### 아트 디렉션 +- **스타일**: 카와이(Kawaii) 치비 + 판타지 원소 마스코트 +- **라인아트**: 2~3px 두께 다크 아웃라인 (원소 메인 컬러보다 30~40% 어두운 색) +- **몸체 형태**: 둥글고 통통한 blob 형태, 중력을 무시하는 유체 느낌 +- **눈**: 크고 둥근 두 개의 눈 (흰 하이라이트 포함), 눈의 크기가 몸 대비 1/4~1/5 +- **표정**: 작은 미소 또는 O자 입, 귀엽고 친근한 느낌 +- **이펙트**: 원소 특성에 맞는 파티클/아우라 효과 (Ember처럼 불꽃 파편이 주변에 떠다님) +- **패턴**: 몸체 내부에 소용돌이(swirl) 또는 원소 특성 무늬 + +### 캔버스 규격 +| 사용처 | 해상도 | 파일 형식 | +|--------|--------|---------| +| 원소 카드 (in-game) | 120×120px | PNG (투명 배경) | +| 캐릭터 상세 패널 | 240×240px | PNG (투명 배경) | +| 도감 썸네일 | 80×80px | PNG (투명 배경) | +| 스플래시/상점 이미지 | 480×480px | PNG (흰 배경 가능) | + +--- + +## 2. Tier별 시각적 복잡도 가이드 + +### Tier 1 — 기본 원소 (Common) +- **원칙**: 단순하고 깨끗한 실루엣, 파티클 최소 (2~3개) +- **색상**: 단색 또는 2~3색 그라디언트 +- **아웃라인**: 단일 컬러 아웃라인 +- **이펙트**: 없거나 아주 작은 파티클 + +### Tier 2 — 2차 원소 (Uncommon) +- **원칙**: 복합 원소 특성이 혼합된 실루엣, 파티클 5~7개 +- **색상**: 두 부모 원소 색을 섞은 듀얼 그라디언트 +- **아웃라인**: 메인 컬러 아웃라인 + 서브 컬러 글로우 (낮은 강도) +- **이펙트**: 부모 원소 파티클이 혼합 + +### Tier 3 — 희귀 원소 (Rare) +- **원칙**: 독특한 실루엣, 주변 환경 이펙트 추가 +- **색상**: 풍부한 채도, 3색 그라디언트 +- **아웃라인**: 빛나는(glow) 아웃라인 +- **이펙트**: 지속적인 파티클 루프, 환경 효과 (번개, 파도 등) + +### Tier 4 — 에픽 원소 (Epic) +- **원칙**: 강렬하고 웅장한 존재감, 후광 효과 +- **색상**: 채도 높고 어두운 컬러, 밝은 하이라이트 대비 +- **아웃라인**: 듀얼 레이어 아웃라인 (다크 + 컬러 글로우) +- **이펙트**: 풍부한 파티클, 회전하는 오브, 에너지 링 + +### Tier 5 — 전설 원소 (Legendary) +- **원칙**: 압도적인 화려함, 화면을 가득 채우는 이펙트 +- **색상**: 무지개/홀로그래픽 또는 순수한 빛(흰색/금색) +- **아웃라인**: 무지개 또는 골든 글로우 +- **이펙트**: 레인보우 파티클, 별/성좌 이펙트, 오로라 + +--- + +## 3. 원소별 캐릭터 시트 + +### Tier 1 — 기본 4원소 + +#### 🔥 불 (Fire) — "엠버" +- **몸체**: 역삼각형 불꽃 실루엣, 주황~노랑 그라디언트 +- **컬러**: Primary `#FF4500`, Glow `#FFAA00`, Dark `#8B2000` +- **파티클**: 불씨 3개 (랜덤 떠다니는 작은 불꽃) +- **패턴**: 몸 중앙 스월 패턴 +- **표정 기본**: 활기차고 자신감 있는 눈매 + +#### 💧 물 (Water) — "아쿠아" +- **몸체**: 물방울/눈물 형태, 투명도 있는 청색 계열 +- **컬러**: Primary `#1E90FF`, Glow `#87CEEB`, Dark `#00008B` +- **파티클**: 작은 물방울 3~4개 주변에 떠다님 +- **패턴**: 몸체 내부 파문 링 패턴 +- **표정 기본**: 차분하고 맑은 눈 + +#### 🌪️ 바람 (Wind) — "브리즈" +- **몸체**: 와류형, 투명도 있는 연한 하늘색, 가장자리가 흐릿한 느낌 +- **컬러**: Primary `#87CEEB`, Glow `#FFFFFF`, Dark `#4682B4` +- **파티클**: 작은 선형 바람 스트로크 4~5개 +- **패턴**: 나선형 기류 패턴 +- **표정 기본**: 장난기 있고 자유로운 눈 + +#### 🌱 흙 (Earth) — "테라" +- **몸체**: 구형, 단단하고 묵직한 느낌, 갈색 계열 +- **컬러**: Primary `#8B4513`, Glow `#D2691E`, Dark `#4B2806` +- **파티클**: 작은 흙먼지/돌멩이 3개 +- **패턴**: 나뭇결 또는 대지 균열 패턴 +- **표정 기본**: 믿음직하고 온화한 눈 + +--- + +### Tier 2 — 주요 2차 원소 (선발) + +#### 💨 수증기 (Steam) — "미스티" +- **몸체**: 불과 물 중간 형태, 반투명 흰/회색 구름 느낌 +- **컬러**: Primary `#C0C0C0`, Glow `#FFFFFF`, Dark `#808080` +- **파티클**: 위로 올라가는 수증기 6~8개 +- **패턴**: 안개처럼 흐릿한 경계 + +#### 🌋 용암 (Lava) — "마그마" +- **몸체**: 불에 녹아내리는 구형, 갈라진 틈에서 빛이 새어나옴 +- **컬러**: Primary `#FF2200`, Glow `#FF6600`, Dark `#8B0000`, Crack `#FFAA00` +- **파티클**: 용암 방울 4~5개 (무겁게 아래로 떨어지는 느낌) +- **패턴**: 몸 전체에 용암 균열 라인 + +#### ⛈️ 폭풍 (Storm) — "스콜" +- **몸체**: 물+바람 혼합, 어두운 구름 형태에 번개 흔적 +- **컬러**: Primary `#4169E1`, Glow `#6495ED`, Dark `#191970` +- **파티클**: 비/번개 파티클 5~6개 + +#### ❄️ 얼음 (Ice) — "크리스탈린" +- **레시피**: 물 + 물 (같은 원소 합성) +- **몸체**: 납작한 결정체 형태, 반투명 하늘색 계열 +- **컬러**: Primary `#87CEEB`, Glow `#FFFFFF`, Dark `#5B9BD5` +- **파티클**: 수정 파편 5~6개 (천천히 회전) +- **패턴**: 결정 내부의 다이아몬드 문양 + +#### 🌫️ 연기 (Smoke) — "스모기" +- **레시피**: 불 + 불 (같은 원소 합성) +- **몸체**: 흐릿한 구름형, 회색 반투명 +- **컬러**: Primary `#808080`, Glow `#A9A9A9`, Dark `#505050` +- **파티클**: 연기 동그라미 5~6개 (위로 흩어지는 느낌) +- **패턴**: 소용돌이 패턴 + +--- + +### Tier 3 — 주요 희귀 원소 (선발) + +#### ⚡ 번개 (Lightning) — "볼트" +- **몸체**: 전기 에너지 형태, 지그재그 실루엣 +- **컬러**: Primary `#FFD700`, Glow `#FFFFFF`, Dark `#B8860B` +- **파티클**: 전기 스파크 7~8개, 회전하는 전류링 +- **특수 이펙트**: 주기적인 방전 플래시 + +#### 🌈 무지개 (Rainbow) — "프리즘" +- **몸체**: 아치형 또는 구형 + 7색 선형 무늬 +- **컬러**: 7색 순환 그라디언트 +- **파티클**: 무지개 빛 가루 8~10개 + +#### 💎 수정 (Crystal, Tier 4) — "크리스탈" +- **몸체**: 다각형 결정체 형태, 빛을 굴절하는 느낌 +- **컬러**: Primary `#9400D3`, Glow `#DA70D6`, Dark `#4B0082` +- **파티클**: 결정 파편 6~7개, 내부에서 빛나는 느낌 + +--- + +### Tier 4 — 신규 에픽 원소 (10종) + +#### 🏔️ 빙하 (Glacier) — "글레이시아" +- **레시피**: 구름 + 안개 +- **몸체**: 납작한 산 실루엣, 차가운 청빙색 +- **컬러**: Primary `#B8D8E8`, Glow `#AADDFF`, Dark `#7EB8D8` +- **파티클**: 결정 파편 6~8개 (천천히 떠다님) + +#### 🌴 정글 (Jungle) — "정글리" +- **레시피**: 안개 + 오아시스 +- **몸체**: 풍성한 구형, 짙은 녹색 +- **컬러**: Primary `#1A6B1A`, Glow `#44BB44`, Dark `#0D3D0D` +- **파티클**: 잎사귀 6~8개 (흩날리는 느낌) + +#### 🏜️ 황무지 (Wasteland) — "웨이스트" +- **레시피**: 화산재 + 먼지 +- **몸체**: 넓고 낮은 형태, 갈색 계열 +- **컬러**: Primary `#8B7355`, Glow `#A08060`, Dark `#5A4A35` +- **파티클**: 흙먼지 입자 6~8개 + +#### 🌀 대소용돌이 (Maelstrom) — "말스트롬" +- **레시피**: 번개 + 쓰나미 +- **몸체**: 회오리 형태, 진남색 +- **컬러**: Primary `#1E3A8A`, Glow `#4488FF`, Dark `#0A1E50` +- **파티클**: 바람 선 + 물방울 혼합 6~8개 + +#### 💠 원석 (Gemstone) — "젬스톤" +- **레시피**: 흑요석 + 유리 +- **몸체**: 다각형 결정체, 짙은 보라 +- **컬러**: Primary `#6B21A8`, Glow `#AA66FF`, Dark `#3D0D6B` +- **파티클**: 수정 파편 6~8개 (회전) + +#### 🔮 프리즘 (Prism) — "프리즈미" +- **레시피**: 무지개 + 유리 +- **몸체**: 구형에 무지개 빛 산란 효과 +- **컬러**: Primary `#EC4899`, Glow `#FF88CC`, Rainbow 산란 +- **파티클**: 무지개 빛 입자 6~8개 + +#### 🏛️ 고대 유적 (Ruins) — "루인즈" +- **레시피**: 화산 + 도자기 +- **몸체**: 기둥 실루엣, 바랜 갈색 +- **컬러**: Primary `#92400E`, Glow `#B8793A`, Dark `#5A2506` +- **파티클**: 흙먼지 입자 + 균열 파편 6~8개 + +#### 🌪️ 사이클론 (Cyclone) — "사이클러" +- **레시피**: 먼지 + 폭풍 +- **몸체**: 회오리 형태, 황금빛 갈색 +- **컬러**: Primary `#D97706`, Glow `#FFB84D`, Dark `#8B4A00` +- **파티클**: 바람 선 + 먼지 입자 6~8개 + +#### 🌊 심해 (Deep Sea) — "아비스" +- **레시피**: 쓰나미 + 흑요석 +- **몸체**: 구형 + 어두운 수심 느낌 +- **컬러**: Primary `#1E3A5F`, Glow `#4488BB`, Dark `#0A1828` +- **파티클**: 물방울 6~8개 (천천히 가라앉는 느낌) + +#### 🌾 초원 (Prairie) — "프레리" +- **레시피**: 오아시스 + 도자기 +- **몸체**: 넓고 부드러운 구형, 황록색 +- **컬러**: Primary `#84CC16`, Glow `#AAFE44`, Dark `#4A7A0A` +- **파티클**: 잎사귀 6~8개 (바람에 흩날림) + +--- + +## 4. 감정 표현 가이드 (Emotion States) + +### Idle (대기 상태) +- 가벼운 위아래 호버링 애니메이션 (약 2초 주기) +- 눈 깜빡임 (약 4~6초 간격) +- 파티클 낮은 빈도로 방출 + +### 합성 시 (Fusion) +- 눈이 반짝임 (별/☆ 형태로 변환) +- 몸이 팽창했다가 줄어드는 pulse 효과 +- 파티클 폭발적으로 방출 (2~3배 밀도) +- 입이 O자로 벌어짐 (놀란 표정) + +### 강화 시 (Enhancement) +- 눈이 활기차게 빛남 (하이라이트 증가) +- 몸 주위에 에너지 링 회전 +- 위 방향으로 성장하는 느낌 +- 파티클이 나선형으로 올라감 + +### 잠금 해제 시 (Unlock) +- 어두운 상태에서 점점 밝아지는 reveal 효과 +- 빛나는 aura 순간 폭발 +- 행복한 표정으로 전환 + +### 잠금 상태 (Locked) +- 흑백 또는 낮은 채도 +- 파티클 없음 +- 눈을 가린 실루엣 + +--- + +## 5. 반응형 카드 상태별 비주얼 + +| 상태 | 배경 | 아웃라인 | 투명도 | 이펙트 | +|------|------|---------|--------|--------| +| obtained | 화이트 | `grey200` 1.5px solid | 100% | idle 파티클 | +| locked | `greyBackground` | `grey200` 1.5px solid | 75% | 없음 | +| undiscovered | `greyBackground` | `grey300` 1.5px dashed | 40% | 없음 | + +--- + +## 6. 등급(Rarity) 배지 컬러 + +| 등급 | 배지 컬러 | 텍스트 | 예시 | +|------|---------|--------|------| +| common | `#9E9E9E` | COMMON | 기본 4원소 | +| uncommon | `#4CAF50` | UNCOMMON | Tier 2 원소 | +| rare | `#2196F3` | RARE | Tier 3 원소 | +| epic | `#9C27B0` | EPIC | Tier 4 원소 | +| legendary | `#FF9800` 금색 글로우 | LEGENDARY | Tier 5 원소 | diff --git a/docs/color-system.md b/docs/color-system.md new file mode 100644 index 0000000..80a87df --- /dev/null +++ b/docs/color-system.md @@ -0,0 +1,247 @@ +# Archetype-FirstSpark 색상 시스템 + +## 1. 기반 패키지 + +```bash +yarn add @toss/tds-colors +``` + +`@toss/tds-colors`의 `adaptive` 네임스페이스를 기반으로, 게임 전용 시맨틱 토큰을 추가로 정의합니다. + +--- + +## 2. 게임 시맨틱 색상 토큰 + +### 2-A. CSS 변수 정의 + +```css +/* src/styles/game-tokens.css */ + +/* ===== 라이트 모드 ===== */ +:root { + /* 골드 / 재화 */ + --color-gold-primary: #FFD700; + --color-gold-secondary: #FFAA00; + --color-gold-bg: #FFF8E1; + --color-gold-text: #5A3200; + + /* 원소 등급 (Rarity) */ + --color-rarity-common: #9E9E9E; + --color-rarity-uncommon: #4CAF50; + --color-rarity-rare: #2196F3; + --color-rarity-epic: #9C27B0; + --color-rarity-legendary: #FF9800; + + /* 합성 / 이벤트 */ + --color-fusion-primary: #7C4DFF; + --color-fusion-glow: #B388FF; + --color-enhance-primary: #3182F6; + --color-enhance-glow: #90CAF9; + + /* 원소 — Tier 1 */ + --color-element-fire: #FF4500; + --color-element-water: #1E90FF; + --color-element-wind: #87CEEB; + --color-element-earth: #8B4513; + + /* 원소 — Tier 2 */ + --color-element-steam: #C0C0C0; + --color-element-firestorm: #FF6347; + --color-element-lava: #FF2200; + --color-element-storm: #4169E1; + --color-element-mud: #8B6914; + --color-element-desert: #DEB887; + + /* 원소 — Tier 3 */ + --color-element-cloud: #87CEEB; + --color-element-lightning: #FFD700; + --color-element-volcano: #CC2200; + --color-element-rainbow: #FF69B4; + --color-element-obsidian: #1C1C1C; + + /* 원소 — Tier 4 */ + --color-element-thunderstorm: #191970; + --color-element-crystal: #9400D3; + --color-element-life: #00FF7F; + --color-element-aurora: #7DF9FF; + + /* 원소 — Tier 5 */ + --color-element-creation: #FFFFFF; + --color-element-spirit: #FFD700; + + /* 카드 상태 */ + --color-card-bg-obtained: #FFFFFF; + --color-card-bg-locked: var(--tds-adaptive-greyBackground); + --color-card-border-obtained: var(--tds-adaptive-grey200); + --color-card-border-locked: var(--tds-adaptive-grey200); + + /* 오프라인 보상 */ + --color-offline-bg: #FFFFFF; + --color-offline-overlay: rgba(0, 0, 0, 0.55); + --color-offline-reward-bg: #F7F8FA; + --color-offline-btn-from: #3182F6; + --color-offline-btn-to: #6C4DE6; +} + +/* ===== 다크 모드 ===== */ +@media (prefers-color-scheme: dark) { + :root { + /* 골드 / 재화 */ + --color-gold-bg: #2A2000; + --color-gold-text: #FFD97A; + + /* 원소 등급 (채도 약간 낮춤, 다크에서 과도한 채도 방지) */ + --color-rarity-common: #BDBDBD; + --color-rarity-uncommon: #66BB6A; + --color-rarity-rare: #42A5F5; + --color-rarity-epic: #BA68C8; + --color-rarity-legendary: #FFA726; + + /* 합성 / 이벤트 */ + --color-fusion-primary: #9575CD; + --color-fusion-glow: #D1C4E9; + --color-enhance-primary: #5C9EE8; + --color-enhance-glow: #BBDEFB; + + /* 카드 상태 */ + --color-card-bg-obtained: #1E1E1E; + --color-card-bg-locked: #2A2A2A; + + /* 오프라인 보상 */ + --color-offline-bg: #1E1E1E; + --color-offline-overlay: rgba(0, 0, 0, 0.72); + --color-offline-reward-bg: #2A2A2A; + } +} +``` + +--- + +## 3. TypeScript 토큰 상수 + +```ts +// src/styles/gameColors.ts +import { adaptive } from '@toss/tds-colors'; + +/** 게임 전용 시맨틱 색상 상수 */ +export const gameColors = { + // ── 재화 ────────────────────────────────────────────── + goldPrimary: '#FFD700', + goldSecondary: '#FFAA00', + goldBg: '#FFF8E1', // 다크: var(--color-gold-bg) 사용 + goldText: '#5A3200', + + // ── 등급 ────────────────────────────────────────────── + rarityCommon: '#9E9E9E', + rarityUncommon: '#4CAF50', + rarityRare: '#2196F3', + rarityEpic: '#9C27B0', + rarityLegendary: '#FF9800', + + // ── 이벤트 ──────────────────────────────────────────── + fusionPrimary: '#7C4DFF', + fusionGlow: '#B388FF', + enhancePrimary: '#3182F6', + enhanceGlow: '#90CAF9', + + // ── 원소별 주요 색 ───────────────────────────────────── + elements: { + fire: '#FF4500', + water: '#1E90FF', + wind: '#87CEEB', + earth: '#8B4513', + steam: '#C0C0C0', + firestorm: '#FF6347', + lava: '#FF2200', + storm: '#4169E1', + mud: '#8B6914', + desert: '#DEB887', + cloud: '#87CEEB', + fog: '#DCDCDC', + volcano: '#CC2200', + rainbow: '#FF69B4', + obsidian: '#1C1C1C', + ash: '#696969', + lightning: '#FFD700', + tsunami: '#006994', + ceramic: '#D2691E', + dust: '#BC8F5F', + oasis: '#228B22', + glass: '#E0FFFF', + thunderstorm: '#191970', + island: '#3CB371', + crystal: '#9400D3', + life: '#00FF7F', + magnet: '#A9A9A9', + aurora: '#7DF9FF', + creation: '#FFFFFF', + spirit: '#FFD700', + }, + + // ── TDS Adaptive 색 (자주 쓰는 것만 재노출) ───────────── + bg: adaptive.background, + greyBg: adaptive.greyBackground, + grey200: adaptive.grey200, + grey400: adaptive.grey400, + grey500: adaptive.grey500, + grey900: adaptive.grey900, + blue500: adaptive.blue500, +} as const; + +/** 등급 → 색상 매핑 헬퍼 */ +export function rarityColor(rarity: string): string { + return { + common: gameColors.rarityCommon, + uncommon: gameColors.rarityUncommon, + rare: gameColors.rarityRare, + epic: gameColors.rarityEpic, + legendary: gameColors.rarityLegendary, + }[rarity] ?? gameColors.rarityCommon; +} + +/** 원소 ID → 주요 색상 헬퍼 */ +export function elementColor(id: string): string { + return gameColors.elements[id as keyof typeof gameColors.elements] ?? '#888888'; +} +``` + +--- + +## 4. 다크모드 대응 규칙 + +| 규칙 | 설명 | +|------|------| +| 배경/텍스트 | `adaptive.*` 사용 (자동 대응) | +| 원소 고유 컬러 | 다크모드에서 그대로 사용 (원소 아이덴티티 유지) | +| 골드/재화 | CSS 변수 `--color-gold-*` 사용 (다크에서 어두운 배경) | +| 이펙트/글로우 | 다크에서 밝기 70~80%로 감소 (눈부심 방지) | +| 오버레이 | 다크에서 `rgba(0,0,0,0.72)` (라이트보다 진하게) | + +### emotion/css에서 다크모드 처리 패턴 + +```tsx +import { css } from '@emotion/react'; +import { adaptive } from '@toss/tds-colors'; + +// adaptive를 사용하면 다크모드 자동 대응 +const cardStyle = css` + background: ${adaptive.background}; + color: ${adaptive.grey900}; + border: 1px solid ${adaptive.grey200}; +`; + +// 게임 전용 색은 CSS 변수 사용 +const goldBadgeStyle = css` + background: linear-gradient(135deg, var(--color-gold-primary), var(--color-gold-secondary)); + color: var(--color-gold-text); +`; +``` + +--- + +## 5. 색상 접근성 체크리스트 + +- [ ] 텍스트 대비비 4.5:1 이상 (WCAG AA) +- [ ] 색 외 다른 시각적 단서 병행 (아이콘, 패턴) +- [ ] 등급 구분: 색 + 배지 텍스트 병행 +- [ ] 원소 카드: 색 + 이모지 병행 diff --git a/docs/ui-asset-guide.md b/docs/ui-asset-guide.md new file mode 100644 index 0000000..3898f27 --- /dev/null +++ b/docs/ui-asset-guide.md @@ -0,0 +1,279 @@ +# Archetype-FirstSpark UI 에셋 가이드 + +## 1. 상점 아이템 아이콘 디자인 스펙 + +### 아이콘 규격 +- **크기**: 64×64px (in-game), 36px (리스트 뷰) +- **배경**: 투명 또는 반경 12px 라운드 박스 +- **스타일**: Ember_Origin 캐릭터와 동일한 카와이 치비 스타일 + +### 현재 상점 아이템 → 디자인 스펙 + +| 아이템 ID | 이름 | 이모지 | 아이콘 컨셉 | 주 색상 | +|-----------|------|--------|-----------|--------| +| `fire_boost` | 불꽃 강화석 | 🔥 | 불꽃 문양이 새겨진 붉은 보석 | `#FF4500` → `#FFAA00` 그라디언트 | +| `water_boost` | 물방울 강화석 | 💧 | 물결 문양 파란 보석 | `#1E90FF` → `#87CEEB` 그라디언트 | +| `fusion_scroll` | 합성 두루마리 | 📜 | 원소 문양이 빛나는 양피지 | `#DEB887`, `#FFD700` 잉크 | +| `gold_bag` | 골드 주머니 | 👝 | 빵빵하게 부푼 황금 주머니 | `#FFD700`, `#FF8C00` | + +### 추가 예정 상점 아이템 (기획 확장용) + +| 아이템 ID | 이름 | 아이콘 컨셉 | 설명 | +|-----------|------|-----------|------| +| `exp_crystal` | 경험치 수정 | 빛나는 보라 결정체 | 원소 EXP +100 | +| `speed_potion` | 속도 물약 | 회오리치는 파란 약병 | 생산 속도 2배 (30분) | +| `offline_booster` | 오프라인 부스터 | 달과 별이 새겨진 아이템 | 오프라인 보상 2배 | +| `discovery_ticket` | 발견 티켓 | 빛나는 황금 입장권 | 랜덤 Tier 3 원소 즉시 해금 | +| `legendary_shard` | 전설 파편 | 홀로그래픽 보석 조각 | 전설 원소 합성 확률 +5% | + +### 상점 아이콘 박스 스펙 (컴포넌트 레벨) + +```tsx +// 상점 아이콘 래퍼 (아이템 등급에 따른 배경 글로우) +const shopIconBoxStyle = (rarity: string) => css` + width: 64px; + height: 64px; + border-radius: 16px; + display: flex; + align-items: center; + justify-content: center; + font-size: 36px; + background: ${ + rarity === 'legendary' ? 'linear-gradient(135deg, #FF9800, #FFD700)' : + rarity === 'epic' ? 'linear-gradient(135deg, #7B1FA2, #9C27B0)' : + rarity === 'rare' ? 'linear-gradient(135deg, #1565C0, #2196F3)' : + rarity === 'uncommon' ? 'linear-gradient(135deg, #2E7D32, #4CAF50)' : + 'linear-gradient(135deg, #616161, #9E9E9E)' + }; + box-shadow: 0 2px 8px rgba(0,0,0,0.15); +`; +``` + +--- + +## 2. 도감 뱃지 디자인 (발견율 마일스톤) + +### 뱃지 규격 +- **크기**: 48×48px (도감 화면 내), 24×24px (프로필 미니 뱃지) +- **형태**: 육각형 또는 방패 형태 (수집/달성의 느낌) +- **스타일**: 금속성 질감, 원소 문양 새김 + +### 마일스톤 뱃지 목록 + +| 달성 조건 | 뱃지 이름 | 디자인 | 색상 | +|----------|----------|--------|------| +| 원소 1개 획득 | 첫 번째 불꽃 | 불꽃 모양 동판 뱃지 | Bronze `#CD7F32` | +| 원소 5개 획득 | 원소 탐험가 | 나침반 모양 은판 뱃지 | Silver `#C0C0C0` | +| 원소 10개 획득 | 중급 연금술사 | 플라스크 + 별 뱃지 | Silver `#C0C0C0` | +| 원소 15개 획득 | 고급 연금술사 | 빛나는 금판 + 원소기호 | Gold `#FFD700` | +| 원소 20개 획득 | 원소 마스터 | 왕관 + 4원소 합체 뱃지 | Gold `#FFD700` 글로우 | +| 원소 25개 획득 | 대현자 | 크리스탈 구슬 뱃지 | Purple `#9C27B0` | +| 원소 30개 전부 획득 | 세계의 창조자 | 무지개 오로라 뱃지 | Rainbow 홀로그래픽 | + +### 뱃지 미획득/획득 상태 + +```tsx +const badgeContainerStyle = (achieved: boolean) => css` + width: 48px; + height: 48px; + border-radius: 12px; + display: flex; + align-items: center; + justify-content: center; + font-size: 28px; + background: ${achieved ? 'linear-gradient(135deg, #FFF8E1, #FFE082)' : adaptive.greyBackground}; + border: 2px solid ${achieved ? '#FFD700' : adaptive.grey300}; + opacity: ${achieved ? 1 : 0.4}; + filter: ${achieved ? 'none' : 'grayscale(100%)'}; + box-shadow: ${achieved ? '0 0 8px rgba(255, 215, 0, 0.4)' : 'none'}; +`; +``` + +### 도감 화면 발견률 시각화 + +``` +발견 진행 바: +[████████░░░░░░░░░░░] 8/30 (26.7%) + +색상 구간: +0~33% → grey gradient (초보) +34~66% → blue gradient (중급) +67~99% → purple gradient (고급) +100% → rainbow gradient (전설) +``` + +--- + +## 3. 오프라인 보상 모달 비주얼 개선 + +### 현재 구현의 개선 포인트 +1. 흰 배경 모달 → **배경에 밤하늘 + 별 이미지 또는 달 모티프 추가** +2. 단색 버튼 → **그라디언트 유지하되 별/달 아이콘 추가** +3. 보상 아이템 배경 `#F7F8FA` → **adaptive 색상으로 다크모드 대응** +4. 타이틀 이모지만 → **달과 별이 조합된 헤더 비주얼 추가** + +### 개선된 스타일 스펙 + +```tsx +// 모달 헤더 영역 +const offlineHeaderStyle = css` + text-align: center; + margin-bottom: 20px; +`; + +// 달 아이콘 + 별 파티클 영역 +const moonIconWrapStyle = css` + font-size: 48px; + line-height: 1; + margin-bottom: 8px; + display: block; + /* 별 파티클은 CSS animation으로 처리 */ + position: relative; + + &::before, &::after { + content: '✦'; + position: absolute; + font-size: 14px; + color: #FFD700; + animation: starTwinkle 2s ease-in-out infinite alternate; + } + &::before { top: 0; left: 20%; } + &::after { top: 10%; right: 15%; animation-delay: 0.7s; } +`; + +// 개선된 모달 배경 +const modalStyle = css` + background: ${adaptive.background}; + border-radius: 24px; + padding: 28px 24px 24px; + width: 100%; + max-width: 340px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18); + /* 상단 별밤 느낌 장식 */ + background-image: radial-gradient( + circle at 50% 0%, + rgba(124, 77, 255, 0.08) 0%, + transparent 60% + ); +`; + +// 보상 아이템 배경 (다크 대응) +const rewardItemStyle = css` + display: flex; + align-items: center; + gap: 10px; + background: ${adaptive.greyBackground}; + border-radius: 12px; + padding: 10px 14px; +`; + +// 수령 버튼 개선 +const claimButtonStyle = css` + width: 100%; + padding: 15px; + background: linear-gradient(135deg, #3182F6, #7C4DFF); + color: white; + border: none; + border-radius: 16px; + font-size: 16px; + font-weight: 700; + cursor: pointer; + position: relative; + overflow: hidden; + + /* 버튼 내부 반짝임 효과 */ + &::after { + content: ''; + position: absolute; + top: -50%; + left: -50%; + width: 200%; + height: 200%; + background: linear-gradient( + 45deg, + transparent 40%, + rgba(255,255,255,0.15) 50%, + transparent 60% + ); + animation: shimmer 2.5s ease-in-out infinite; + } + + &:active { + transform: scale(0.97); + } +`; + +// 골드 보상 행 (다크 대응) +const goldRowStyle = css` + display: flex; + align-items: center; + gap: 10px; + background: linear-gradient(135deg, var(--color-gold-bg, #FFF8E1), #FFF3CD); + border-radius: 12px; + padding: 10px 14px; + margin-bottom: 20px; +`; +``` + +### 타이틀 섹션 개선 (JSX) + +```tsx +// 개선된 모달 상단부 +
+ 🌙 +

오프라인 보상

+

+ {formatDuration(pendingOfflineReward.offlineSec)} 동안
+ 원소가 자동 수집되었습니다! +

+
+``` + +--- + +## 4. 화면별 UI 에셋 요약 + +| 화면 | 주요 에셋 | 우선순위 | +|------|----------|---------| +| ShopScreen | 상점 아이템 아이콘 (고화질 PNG) | High | +| ElementsScreen | 도감 뱃지 시스템 | Medium | +| OfflineRewardModal | 달/별 헤더 이미지, 개선된 버튼 | Medium | +| FusionScreen | 합성 이펙트 파티클 | High | +| EvolutionScreen | 강화 에너지 링 이펙트 | Medium | + +--- + +## 5. 애니메이션 스펙 (CSS Keyframes) + +```css +@keyframes starTwinkle { + from { opacity: 0.3; transform: scale(0.8); } + to { opacity: 1.0; transform: scale(1.2); } +} + +@keyframes shimmer { + 0% { transform: translateX(-100%) rotate(45deg); } + 100% { transform: translateX(100%) rotate(45deg); } +} + +@keyframes elementIdle { + 0%, 100% { transform: translateY(0px); } + 50% { transform: translateY(-4px); } +} + +@keyframes fusionPulse { + 0% { transform: scale(1); } + 50% { transform: scale(1.12); } + 100% { transform: scale(1); } +} + +@keyframes enhanceRing { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} + +@keyframes rarityGlow { + 0%, 100% { box-shadow: 0 0 6px currentColor; } + 50% { box-shadow: 0 0 16px currentColor, 0 0 32px currentColor; } +} +``` diff --git a/scripts/generate_icon.py b/scripts/generate_icon.py new file mode 100644 index 0000000..3a47655 --- /dev/null +++ b/scripts/generate_icon.py @@ -0,0 +1,207 @@ +""" +Archetype: First Spark - App Icon Generator +1024x1024 PNG 앱 아이콘 생성 스크립트 +주 색상: #FF6B35 (불꽃-주황) +""" + +from PIL import Image, ImageDraw, ImageFilter +import math + +def hex_to_rgb(hex_color): + hex_color = hex_color.lstrip('#') + return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4)) + +def create_app_icon(size=1024, output_path="app-icon.png"): + img = Image.new('RGBA', (size, size), (0, 0, 0, 0)) + draw = ImageDraw.Draw(img) + + # === 배경: 깊은 다크 네이비 → 다크 퍼플 그라디언트 === + bg = Image.new('RGBA', (size, size)) + bg_draw = ImageDraw.Draw(bg) + for y in range(size): + t = y / size + # #0D0D1A (top) → #1A0A2E (bottom) + r = int(13 + (26 - 13) * t) + g = int(13 + (10 - 13) * t) + b = int(26 + (46 - 26) * t) + bg_draw.line([(0, y), (size, y)], fill=(r, g, b, 255)) + img = Image.alpha_composite(img, bg) + draw = ImageDraw.Draw(img) + + cx, cy = size // 2, size // 2 + + # === 외곽 글로우 링 (주황빛 오라) === + glow_layer = Image.new('RGBA', (size, size), (0, 0, 0, 0)) + glow_draw = ImageDraw.Draw(glow_layer) + for i in range(12, 0, -1): + alpha = int(15 * (i / 12)) + radius = int(size * 0.42) + i * 8 + glow_draw.ellipse( + [cx - radius, cy - radius, cx + radius, cy + radius], + fill=(255, 107, 53, alpha) + ) + img = Image.alpha_composite(img, glow_layer) + draw = ImageDraw.Draw(img) + + # === 메인 원형 배경 (진한 그라디언트 구체) === + circle_layer = Image.new('RGBA', (size, size), (0, 0, 0, 0)) + circle_draw = ImageDraw.Draw(circle_layer) + base_r = int(size * 0.42) + for i in range(base_r, 0, -1): + t = 1 - (i / base_r) + # 어두운 중심부에서 불꽃 주황으로 + r = int(20 + (120 - 20) * (1 - t**2)) + g = int(8 + (40 - 8) * (1 - t**2)) + b = int(35 + (15 - 35) * (1 - t**2)) + circle_draw.ellipse( + [cx - i, cy - i, cx + i, cy + i], + fill=(r, g, b, 255) + ) + img = Image.alpha_composite(img, circle_layer) + draw = ImageDraw.Draw(img) + + # === 불꽃 파티클 (배경 장식) === + spark_layer = Image.new('RGBA', (size, size), (0, 0, 0, 0)) + spark_draw = ImageDraw.Draw(spark_layer) + sparks = [ + (cx - 180, cy - 200, 6, 180), + (cx + 200, cy - 160, 5, 160), + (cx - 220, cy + 100, 4, 140), + (cx + 180, cy + 180, 5, 150), + (cx - 60, cy - 280, 7, 200), + (cx + 80, cy - 260, 6, 180), + (cx - 260, cy - 40, 4, 130), + (cx + 260, cy - 60, 5, 150), + (cx - 100, cy + 270, 6, 160), + (cx + 120, cy + 260, 4, 140), + ] + for sx, sy, sr, alpha in sparks: + for gi in range(sr, 0, -1): + ga = int(alpha * (gi / sr) ** 2) + spark_draw.ellipse( + [sx - gi, sy - gi, sx + gi, sy + gi], + fill=(255, 180, 80, ga) + ) + img = Image.alpha_composite(img, spark_layer) + draw = ImageDraw.Draw(img) + + # === 중앙 불꽃 형상 (메인 심볼) === + flame_layer = Image.new('RGBA', (size, size), (0, 0, 0, 0)) + flame_draw = ImageDraw.Draw(flame_layer) + + # 불꽃 외형 (여러 레이어로 깊이 표현) + # 레이어 1: 큰 불꽃 (오렌지-레드) + flame1 = [ + (cx, cy - 270), # 꼭대기 + (cx + 120, cy - 140), # 오른쪽 상단 + (cx + 160, cy + 30), # 오른쪽 중간 + (cx + 90, cy + 200), # 오른쪽 하단 + (cx, cy + 240), # 바닥 중앙 + (cx - 90, cy + 200), # 왼쪽 하단 + (cx - 160, cy + 30), # 왼쪽 중간 + (cx - 120, cy - 140), # 왼쪽 상단 + ] + flame_draw.polygon(flame1, fill=(255, 90, 20, 230)) + + # 레이어 2: 중간 불꽃 (밝은 오렌지) + flame2 = [ + (cx, cy - 220), + (cx + 90, cy - 100), + (cx + 120, cy + 40), + (cx + 60, cy + 180), + (cx, cy + 200), + (cx - 60, cy + 180), + (cx - 120, cy + 40), + (cx - 90, cy - 100), + ] + flame_draw.polygon(flame2, fill=(255, 140, 40, 220)) + + # 레이어 3: 내부 불꽃 (밝은 노란 오렌지) + flame3 = [ + (cx, cy - 160), + (cx + 60, cy - 60), + (cx + 80, cy + 60), + (cx + 35, cy + 150), + (cx, cy + 160), + (cx - 35, cy + 150), + (cx - 80, cy + 60), + (cx - 60, cy - 60), + ] + flame_draw.polygon(flame3, fill=(255, 200, 80, 210)) + + # 레이어 4: 핵심 (흰색-노란색 빛) + flame4 = [ + (cx, cy - 80), + (cx + 30, cy - 20), + (cx + 40, cy + 50), + (cx, cy + 80), + (cx - 40, cy + 50), + (cx - 30, cy - 20), + ] + flame_draw.polygon(flame4, fill=(255, 240, 180, 200)) + + # 중심 빛 (흰색 글로우) + for i in range(30, 0, -1): + alpha = int(180 * (i / 30) ** 2) + flame_draw.ellipse( + [cx - i, cy + 10 - i, cx + i, cy + 10 + i], + fill=(255, 255, 240, alpha) + ) + + # 불꽃 블러 (부드럽게) + flame_blurred = flame_layer.filter(ImageFilter.GaussianBlur(radius=3)) + img = Image.alpha_composite(img, flame_blurred) + draw = ImageDraw.Draw(img) + + # === 원소 심볼 (아크 형태의 빛나는 링) === + arc_layer = Image.new('RGBA', (size, size), (0, 0, 0, 0)) + arc_draw = ImageDraw.Draw(arc_layer) + + # 4개의 원소 호 (불, 물, 바람, 땅 의미) + ring_r = int(size * 0.35) + element_colors = [ + (255, 80, 20, 180), # 불 + (60, 160, 255, 160), # 물 + (160, 240, 120, 140), # 바람 + (200, 160, 60, 150), # 땅 + ] + for i, color in enumerate(element_colors): + start_angle = i * 90 - 30 + end_angle = start_angle + 60 + for w in range(6, 0, -1): + arc_draw.arc( + [cx - ring_r - w, cy - ring_r - w, cx + ring_r + w, cy + ring_r + w], + start=start_angle, end=end_angle, + fill=(*color[:3], int(color[3] * w / 6)), + width=w * 2 + ) + + arc_blurred = arc_layer.filter(ImageFilter.GaussianBlur(radius=2)) + img = Image.alpha_composite(img, arc_blurred) + draw = ImageDraw.Draw(img) + + # === 상단 광택 효과 (입체감) === + gloss_layer = Image.new('RGBA', (size, size), (0, 0, 0, 0)) + gloss_draw = ImageDraw.Draw(gloss_layer) + gloss_r = int(size * 0.38) + gloss_draw.ellipse( + [cx - gloss_r, cy - gloss_r, cx + gloss_r, cy - gloss_r // 3], + fill=(255, 255, 255, 25) + ) + gloss_blurred = gloss_layer.filter(ImageFilter.GaussianBlur(radius=20)) + img = Image.alpha_composite(img, gloss_blurred) + + # === 저장 === + final = img.convert('RGBA') + final.save(output_path, 'PNG', optimize=True) + print(f"[OK] 아이콘 저장: {output_path} ({size}x{size}px)") + return final + +# 1024x1024 메인 아이콘 +create_app_icon(1024, "C:/Users/jaeoh/Desktop/workspace/Archetype-FirstSpark/app-icon.png") + +# 512x512 앱스토어용 +icon_1024 = Image.open("C:/Users/jaeoh/Desktop/workspace/Archetype-FirstSpark/app-icon.png") +icon_512 = icon_1024.resize((512, 512), Image.LANCZOS) +icon_512.save("C:/Users/jaeoh/Desktop/workspace/Archetype-FirstSpark/app-icon-512.png", 'PNG', optimize=True) +print("[OK] 512x512 앱스토어용 저장 완료")