create-ax-project 1.0.0 β 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/template/.claude/CLAUDE.md +0 -7
- package/template/.claude/commands/CLAUDE.md +0 -0
- package/template/.claude/hooks/CLAUDE.md +0 -0
- package/template/.claude/skills/ai-collaboration/CLAUDE.md +0 -0
- package/template/.claude/skills/auto-checkpoint/CLAUDE.md +0 -0
- package/template/.claude/skills/context-compression/CLAUDE.md +0 -0
- package/template/.claude/skills/context-compression/prompts/CLAUDE.md +0 -0
- package/template/.claude/skills/output-validator/CLAUDE.md +0 -0
- package/template/.claude/skills/smart-handoff/CLAUDE.md +0 -0
- package/template/.claude/skills/stage-transition/CLAUDE.md +0 -0
- package/template/.claude/skills/stage-transition/prompts/CLAUDE.md +0 -0
- package/template/config/CLAUDE.md +0 -0
- package/template/scripts/CLAUDE.md +0 -0
- package/template/stages/01-brainstorm/HANDOFF.md +0 -110
- package/template/stages/01-brainstorm/inputs/CLAUDE.md +0 -0
- package/template/stages/01-brainstorm/inputs/project_brief.md +0 -40
- package/template/stages/01-brainstorm/outputs/CLAUDE.md +0 -0
- package/template/stages/01-brainstorm/outputs/ideas.md +0 -159
- package/template/stages/01-brainstorm/outputs/requirements_analysis.md +0 -222
- package/template/stages/01-brainstorm/prompts/CLAUDE.md +0 -0
- package/template/stages/01-brainstorm/templates/CLAUDE.md +0 -0
- package/template/stages/02-research/HANDOFF.md +0 -158
- package/template/stages/02-research/outputs/CLAUDE.md +0 -0
- package/template/stages/02-research/outputs/feasibility_report.md +0 -176
- package/template/stages/02-research/outputs/tech_research.md +0 -403
- package/template/stages/02-research/prompts/CLAUDE.md +0 -0
- package/template/stages/03-planning/HANDOFF.md +0 -168
- package/template/stages/03-planning/outputs/CLAUDE.md +0 -0
- package/template/stages/03-planning/outputs/architecture.md +0 -400
- package/template/stages/03-planning/outputs/implementation.yaml +0 -209
- package/template/stages/03-planning/outputs/project_plan.md +0 -204
- package/template/stages/03-planning/outputs/tech_stack.md +0 -176
- package/template/stages/03-planning/prompts/CLAUDE.md +0 -0
- package/template/stages/04-ui-ux/HANDOFF.md +0 -165
- package/template/stages/04-ui-ux/outputs/CLAUDE.md +0 -0
- package/template/stages/04-ui-ux/outputs/design_system.md +0 -449
- package/template/stages/04-ui-ux/outputs/user_flows.md +0 -321
- package/template/stages/04-ui-ux/outputs/wireframes.md +0 -241
- package/template/stages/04-ui-ux/prompts/CLAUDE.md +0 -0
- package/template/stages/05-task-management/HANDOFF.md +0 -187
- package/template/stages/05-task-management/outputs/CLAUDE.md +0 -0
- package/template/stages/05-task-management/outputs/milestones.md +0 -253
- package/template/stages/05-task-management/outputs/sprint_plan.md +0 -203
- package/template/stages/05-task-management/outputs/tasks.md +0 -402
- package/template/stages/05-task-management/prompts/CLAUDE.md +0 -0
- package/template/stages/05-task-management/templates/CLAUDE.md +0 -0
- package/template/stages/06-implementation/HANDOFF.md +0 -184
- package/template/stages/06-implementation/prompts/CLAUDE.md +0 -0
- package/template/stages/07-refactoring/HANDOFF.md +0 -82
- package/template/stages/07-refactoring/outputs/refactoring_report.md +0 -102
- package/template/stages/07-refactoring/prompts/CLAUDE.md +0 -0
- package/template/stages/08-qa/HANDOFF.md +0 -114
- package/template/stages/08-qa/outputs/qa_report.md +0 -138
- package/template/stages/08-qa/prompts/CLAUDE.md +0 -0
- package/template/stages/09-testing/HANDOFF.md +0 -118
- package/template/stages/09-testing/outputs/test_report.md +0 -146
- package/template/stages/09-testing/prompts/CLAUDE.md +0 -0
- package/template/stages/10-deployment/HANDOFF.md +0 -141
- package/template/stages/10-deployment/prompts/CLAUDE.md +0 -0
- package/template/stages/10-deployment/templates/CLAUDE.md +0 -0
- package/template/state/templates/CLAUDE.md +0 -0
|
@@ -1,400 +0,0 @@
|
|
|
1
|
-
# ποΈ Snake Game μμ€ν
μν€ν
μ² μ€κ³μ
|
|
2
|
-
|
|
3
|
-
> μμ±μΌ: 2026-01-21
|
|
4
|
-
> μ€ν
μ΄μ§: 03-planning
|
|
5
|
-
> νλ‘μ νΈ: snake-game
|
|
6
|
-
> AI λꡬ: Gemini CLI
|
|
7
|
-
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
## 1. μ»΄ν¬λνΈ κ΅¬μ‘°
|
|
11
|
-
|
|
12
|
-
μ΄ νλ‘μ νΈλ λ¨μΌ μΊλ²μ€ λ λλ§ λ°©μκ³Ό React UI μ€λ²λ μ΄λ₯Ό κ²°ν©ν **νμ΄λΈλ¦¬λ ꡬ쑰**λ₯Ό μ±νν©λλ€.
|
|
13
|
-
|
|
14
|
-
### 1.1 μ»΄ν¬λνΈ μν
|
|
15
|
-
|
|
16
|
-
| μ»΄ν¬λνΈ | νμ
| μν |
|
|
17
|
-
|---------|------|------|
|
|
18
|
-
| **App** | Container | μ 체 λ μ΄μμ, μ΅μμ μν(ν
λ§ λ±) κ΄λ¦¬ |
|
|
19
|
-
| **GameEngine** | Smart | ν΅μ¬ λΉμ¦λμ€ λ‘μ§ μ°κ²°, Canvas/UI μ‘°μ¨ |
|
|
20
|
-
| **CanvasLayer** | Presentation | Canvas μ κ·Ό, κ²μ λ λλ§ μν |
|
|
21
|
-
| **UIOverlay** | Presentation | HTML/CSS κΈ°λ° UI (μ μ, λͺ¨λ¬ λ±) |
|
|
22
|
-
| **ScoreBoard** | UI | νμ¬ μ μμ μ΅κ³ μ μ νμ |
|
|
23
|
-
| **GameOverModal** | UI | κ²μ μ’
λ£ μ μ¬μμ λ²νΌκ³Ό κ²°κ³Ό |
|
|
24
|
-
| **StartScreen** | UI | κ²μ μμ μ νμ΄ν νλ©΄ |
|
|
25
|
-
| **MobileControls** | UI | λͺ¨λ°μΌ λ°©ν₯ λ²νΌ |
|
|
26
|
-
|
|
27
|
-
### 1.2 κ³μΈ΅ ꡬ쑰 λ€μ΄μ΄κ·Έλ¨
|
|
28
|
-
|
|
29
|
-
```
|
|
30
|
-
+-------------------------------------------------------+
|
|
31
|
-
| App |
|
|
32
|
-
|-------------------------------------------------------|
|
|
33
|
-
| +-------------------------------------------------+ |
|
|
34
|
-
| | GameEngine | |
|
|
35
|
-
| | (Holds Game State, Refs, and Event Listeners) | |
|
|
36
|
-
| |-------------------------------------------------| |
|
|
37
|
-
| | +-------------------+ +-------------------+ | |
|
|
38
|
-
| | | CanvasLayer | | UIOverlay | | |
|
|
39
|
-
| | | (Rendering Target)| | (React Components)| | |
|
|
40
|
-
| | | | | | | |
|
|
41
|
-
| | | [Snake] [Food] | | [ScoreBoard] | | |
|
|
42
|
-
| | | [Grid] [Fx] | | [GameOverModal] | | |
|
|
43
|
-
| | | | | [MobileControls] | | |
|
|
44
|
-
| | +-------------------+ +-------------------+ | |
|
|
45
|
-
| +-------------------------------------------------+ |
|
|
46
|
-
+-------------------------------------------------------+
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### 1.3 μ»΄ν¬λνΈ μμ‘΄μ± κ·Έλν
|
|
50
|
-
|
|
51
|
-
```
|
|
52
|
-
App
|
|
53
|
-
β
|
|
54
|
-
GameEngine
|
|
55
|
-
β
|
|
56
|
-
ββββββββββββββΌβββββββββββββ
|
|
57
|
-
β β β
|
|
58
|
-
CanvasLayer UIOverlay Hooks
|
|
59
|
-
β β β
|
|
60
|
-
β βββββββ΄ββββββ β
|
|
61
|
-
β β β β β
|
|
62
|
-
β Score Modal Mobile β
|
|
63
|
-
β Board Over Controlsβ
|
|
64
|
-
β β
|
|
65
|
-
ββββββββββββββββββββββββββ
|
|
66
|
-
Canvas Context
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
---
|
|
70
|
-
|
|
71
|
-
## 2. λ°μ΄ν° νλ¦
|
|
72
|
-
|
|
73
|
-
Reactμ μ μΈμ μν κ΄λ¦¬μ Canvasμ λͺ
λ Ήν λ λλ§μ μ‘°νμν€λ κ²μ΄ ν΅μ¬μ
λλ€.
|
|
74
|
-
|
|
75
|
-
### 2.1 κ²μ μν νλ¦
|
|
76
|
-
|
|
77
|
-
```
|
|
78
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
79
|
-
β State Flow β
|
|
80
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
|
|
81
|
-
β β
|
|
82
|
-
β useReducer βββββββββββββββββββββββββββββββββββββββ β
|
|
83
|
-
β β β β
|
|
84
|
-
β βΌ β β
|
|
85
|
-
β gameState βββββββββββββββββββββββββββββββββββββΊ β β
|
|
86
|
-
β (snake, food, direction, score, status) β β
|
|
87
|
-
β β β β
|
|
88
|
-
β β requestAnimationFrame β β
|
|
89
|
-
β βΌ β β β
|
|
90
|
-
β gameLoop ββββββ β β
|
|
91
|
-
β β β β
|
|
92
|
-
β ββββΊ dispatch({ type: 'TICK' }) β β
|
|
93
|
-
β β β β
|
|
94
|
-
β βΌ β β
|
|
95
|
-
β Canvas.draw() ββββββββββββββββββββββββββββββββββββ β
|
|
96
|
-
β β
|
|
97
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
### 2.2 μ΄λ²€νΈ μ²λ¦¬ νλ¦
|
|
101
|
-
|
|
102
|
-
```
|
|
103
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
104
|
-
β Event Flow β
|
|
105
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
|
|
106
|
-
β β
|
|
107
|
-
β User Input β
|
|
108
|
-
β β β
|
|
109
|
-
β ββββΊ Keyboard (useKeyboard) βββ β
|
|
110
|
-
β β β β
|
|
111
|
-
β ββββΊ Touch (useSwipe) βββββββββ€ β
|
|
112
|
-
β β β
|
|
113
|
-
β βΌ β
|
|
114
|
-
β Direction Normalized β
|
|
115
|
-
β (UP/DOWN/LEFT/RIGHT) β
|
|
116
|
-
β β β
|
|
117
|
-
β βΌ β
|
|
118
|
-
β dispatch({ type: 'CHANGE_DIRECTION' }) β
|
|
119
|
-
β β β
|
|
120
|
-
β βΌ β
|
|
121
|
-
β Collision Check β
|
|
122
|
-
β β β
|
|
123
|
-
β ββββββββββββββββββΌβββββββββββββ β
|
|
124
|
-
β β β β β
|
|
125
|
-
β βΌ βΌ βΌ β
|
|
126
|
-
β Wall Hit Self Hit Eat Food β
|
|
127
|
-
β β β β β
|
|
128
|
-
β βΌ βΌ βΌ β
|
|
129
|
-
β GAME_OVER GAME_OVER Grow +10 β
|
|
130
|
-
β β
|
|
131
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
### 2.3 μν vs μ°Έμ‘° λΆλ¦¬
|
|
135
|
-
|
|
136
|
-
| λ°μ΄ν° | κ΄λ¦¬ λ°©μ | μ΄μ |
|
|
137
|
-
|--------|----------|------|
|
|
138
|
-
| snake, food, score | `useReducer` | UI 리λ λλ§ νμ |
|
|
139
|
-
| direction (λ²νΌ) | `useRef` | λΉ λ₯Έ μ
λ ₯ μ²λ¦¬, 리λ λλ§ λ°©μ§ |
|
|
140
|
-
| canvasRef | `useRef` | DOM μ°Έμ‘° |
|
|
141
|
-
| animationFrameId | `useRef` | 루ν κ΄λ¦¬ |
|
|
142
|
-
|
|
143
|
-
---
|
|
144
|
-
|
|
145
|
-
## 3. 컀μ€ν
ν
μ€κ³
|
|
146
|
-
|
|
147
|
-
### 3.1 useGameLoop
|
|
148
|
-
|
|
149
|
-
```typescript
|
|
150
|
-
/**
|
|
151
|
-
* requestAnimationFrame κΈ°λ° κ²μ 루ν κ΄λ¦¬
|
|
152
|
-
* @param callback λ§€ νλ μ μ€νλ ν¨μ
|
|
153
|
-
* @param isRunning 루ν μ€ν μ¬λΆ
|
|
154
|
-
*/
|
|
155
|
-
const useGameLoop = (
|
|
156
|
-
callback: (deltaTime: number) => void,
|
|
157
|
-
isRunning: boolean
|
|
158
|
-
) => void;
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
**νΉμ§**:
|
|
162
|
-
- μ»΄ν¬λνΈ μΈλ§μ΄νΈ μ μλ μ 리
|
|
163
|
-
- deltaTime κ³μ°νμ¬ νλ μ λ
립μ μ λλ©μ΄μ
|
|
164
|
-
- isRunningμΌλ‘ μΌμμ μ§/μ¬κ° μ μ΄
|
|
165
|
-
|
|
166
|
-
### 3.2 useKeyboard
|
|
167
|
-
|
|
168
|
-
```typescript
|
|
169
|
-
/**
|
|
170
|
-
* ν€λ³΄λ μ
λ ₯ κ°μ§ λ° λ°©ν₯ λ³ν
|
|
171
|
-
* @param onDirectionChange λ°©ν₯ λ³κ²½ μ μ½λ°±
|
|
172
|
-
* @param onPause μΌμμ μ§ ν κΈ μ½λ°±
|
|
173
|
-
* @param onRestart μ¬μμ μ½λ°±
|
|
174
|
-
*/
|
|
175
|
-
const useKeyboard = (
|
|
176
|
-
onDirectionChange: (direction: Direction) => void,
|
|
177
|
-
onPause?: () => void,
|
|
178
|
-
onRestart?: () => void
|
|
179
|
-
) => void;
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
**μ§μ ν€**:
|
|
183
|
-
- Arrow Keys: λ°©ν₯ μ΄λ
|
|
184
|
-
- WASD: λ°©ν₯ μ΄λ (λμ)
|
|
185
|
-
- P / Escape: μΌμμ μ§
|
|
186
|
-
- R / Space: μ¬μμ
|
|
187
|
-
|
|
188
|
-
### 3.3 useSwipe
|
|
189
|
-
|
|
190
|
-
```typescript
|
|
191
|
-
/**
|
|
192
|
-
* ν°μΉ μ€μμ΄ν μ μ€μ² κ°μ§
|
|
193
|
-
* @param handlers κ° λ°©ν₯λ³ νΈλ€λ¬
|
|
194
|
-
*/
|
|
195
|
-
const useSwipe = (handlers: {
|
|
196
|
-
left?: () => void;
|
|
197
|
-
right?: () => void;
|
|
198
|
-
up?: () => void;
|
|
199
|
-
down?: () => void;
|
|
200
|
-
}) => void;
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
**νΉμ§**:
|
|
204
|
-
- μ΅μ μ€μμ΄ν 거리 (threshold): 50px
|
|
205
|
-
- μ΅λ μ€μμ΄ν μκ°: 500ms
|
|
206
|
-
- passive 리μ€λλ‘ μ±λ₯ μ΅μ ν
|
|
207
|
-
|
|
208
|
-
### 3.4 useHighScore
|
|
209
|
-
|
|
210
|
-
```typescript
|
|
211
|
-
/**
|
|
212
|
-
* localStorage κΈ°λ° μ΅κ³ μ μ κ΄λ¦¬
|
|
213
|
-
*/
|
|
214
|
-
const useHighScore = () => {
|
|
215
|
-
highScore: number;
|
|
216
|
-
updateHighScore: (score: number) => boolean; // κ°±μ μ¬λΆ λ°ν
|
|
217
|
-
resetHighScore: () => void;
|
|
218
|
-
};
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
---
|
|
222
|
-
|
|
223
|
-
## 4. νμΌ/ν΄λ ꡬ쑰
|
|
224
|
-
|
|
225
|
-
```
|
|
226
|
-
snake-game/
|
|
227
|
-
βββ public/
|
|
228
|
-
β βββ favicon.svg
|
|
229
|
-
βββ src/
|
|
230
|
-
β βββ assets/ # μ μ μμ°
|
|
231
|
-
β β βββ sounds/ # ν¨κ³Όμ (μ ν)
|
|
232
|
-
β β
|
|
233
|
-
β βββ components/ # React UI μ»΄ν¬λνΈ
|
|
234
|
-
β β βββ CanvasLayer.tsx # Canvas λνΌ
|
|
235
|
-
β β βββ GameOverlay.tsx # UI μ€λ²λ μ΄ μ»¨ν
μ΄λ
|
|
236
|
-
β β βββ ScoreBoard.tsx # μ μν
|
|
237
|
-
β β βββ StartScreen.tsx # μμ νλ©΄
|
|
238
|
-
β β βββ GameOverModal.tsx # κ²μ μ€λ² λͺ¨λ¬
|
|
239
|
-
β β βββ MobileControls.tsx # λͺ¨λ°μΌ λ²νΌ
|
|
240
|
-
β β
|
|
241
|
-
β βββ hooks/ # 컀μ€ν
ν
|
|
242
|
-
β β βββ useGameLoop.ts
|
|
243
|
-
β β βββ useKeyboard.ts
|
|
244
|
-
β β βββ useSwipe.ts
|
|
245
|
-
β β βββ useHighScore.ts
|
|
246
|
-
β β
|
|
247
|
-
β βββ engine/ # κ²μ ν΅μ¬ λ‘μ§
|
|
248
|
-
β β βββ gameReducer.ts # μν κ΄λ¦¬ 리λμ
|
|
249
|
-
β β βββ collision.ts # μΆ©λ κ°μ§
|
|
250
|
-
β β βββ renderer.ts # Canvas λ λλ§
|
|
251
|
-
β β
|
|
252
|
-
β βββ types/ # TypeScript νμ
|
|
253
|
-
β β βββ index.ts
|
|
254
|
-
β β
|
|
255
|
-
β βββ utils/ # μ νΈλ¦¬ν° ν¨μ
|
|
256
|
-
β β βββ random.ts # λλ€ μ’ν μμ±
|
|
257
|
-
β β
|
|
258
|
-
β βββ constants/ # μμ μ μ
|
|
259
|
-
β β βββ config.ts
|
|
260
|
-
β β
|
|
261
|
-
β βββ styles/ # μ€νμΌ
|
|
262
|
-
β β βββ index.css
|
|
263
|
-
β β
|
|
264
|
-
β βββ App.tsx # λ£¨νΈ μ»΄ν¬λνΈ
|
|
265
|
-
β βββ GameEngine.tsx # κ²μ μμ§ μ»΄ν¬λνΈ
|
|
266
|
-
β βββ main.tsx # μ§μ
μ
|
|
267
|
-
β
|
|
268
|
-
βββ index.html
|
|
269
|
-
βββ package.json
|
|
270
|
-
βββ tsconfig.json
|
|
271
|
-
βββ vite.config.ts
|
|
272
|
-
βββ README.md
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
---
|
|
276
|
-
|
|
277
|
-
## 5. νμ
μ μ
|
|
278
|
-
|
|
279
|
-
```typescript
|
|
280
|
-
// types/index.ts
|
|
281
|
-
|
|
282
|
-
/** μ’ν νμ
*/
|
|
283
|
-
export interface Point {
|
|
284
|
-
x: number;
|
|
285
|
-
y: number;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/** μ΄λ λ°©ν₯ */
|
|
289
|
-
export type Direction = 'UP' | 'DOWN' | 'LEFT' | 'RIGHT';
|
|
290
|
-
|
|
291
|
-
/** κ²μ μ§ν μν */
|
|
292
|
-
export type GameStatus = 'IDLE' | 'PLAYING' | 'PAUSED' | 'GAME_OVER';
|
|
293
|
-
|
|
294
|
-
/** μ 체 κ²μ μν (Reducer State) */
|
|
295
|
-
export interface GameState {
|
|
296
|
-
status: GameStatus;
|
|
297
|
-
snake: Point[]; // λ± λͺΈν΅ (0λ²μ΄ 머리)
|
|
298
|
-
food: Point; // λ¨Ήμ΄ μμΉ
|
|
299
|
-
direction: Direction; // νμ¬ λ°©ν₯
|
|
300
|
-
nextDirection: Direction; // μ
λ ₯ λ²νΌ (λ€μ ν±μ μ μ©)
|
|
301
|
-
score: number;
|
|
302
|
-
level: number;
|
|
303
|
-
speed: number; // νμ¬ μλ (ms)
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/** Reducer Actions */
|
|
307
|
-
export type GameAction =
|
|
308
|
-
| { type: 'START_GAME' }
|
|
309
|
-
| { type: 'PAUSE_GAME' }
|
|
310
|
-
| { type: 'RESUME_GAME' }
|
|
311
|
-
| { type: 'GAME_OVER' }
|
|
312
|
-
| { type: 'TICK' }
|
|
313
|
-
| { type: 'CHANGE_DIRECTION'; payload: Direction }
|
|
314
|
-
| { type: 'EAT_FOOD' }
|
|
315
|
-
| { type: 'RESTART' };
|
|
316
|
-
|
|
317
|
-
/** κ²μ μ€μ */
|
|
318
|
-
export interface GameConfig {
|
|
319
|
-
boardSize: number; // 그리λ ν¬κΈ° (20x20)
|
|
320
|
-
cellSize: number; // μ
ν½μ
ν¬κΈ°
|
|
321
|
-
initialSpeed: number; // μ΄κΈ° μλ (ms)
|
|
322
|
-
speedDecrement: number; // λ 벨μ
μ μλ κ°μλ
|
|
323
|
-
minSpeed: number; // μ΅μ μλ (μ΅λ λμ΄λ)
|
|
324
|
-
pointsPerFood: number; // λ¨Ήμ΄λΉ μ μ
|
|
325
|
-
pointsForLevelUp: number; // λ 벨μ
νμ μ μ
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
/** ν€λ³΄λ νΈλ€λ¬ */
|
|
329
|
-
export interface KeyboardHandlers {
|
|
330
|
-
onDirectionChange: (direction: Direction) => void;
|
|
331
|
-
onPause?: () => void;
|
|
332
|
-
onRestart?: () => void;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/** μ€μμ΄ν νΈλ€λ¬ */
|
|
336
|
-
export interface SwipeHandlers {
|
|
337
|
-
left?: () => void;
|
|
338
|
-
right?: () => void;
|
|
339
|
-
up?: () => void;
|
|
340
|
-
down?: () => void;
|
|
341
|
-
}
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
---
|
|
345
|
-
|
|
346
|
-
## 6. κ²μ μ€μ μμ
|
|
347
|
-
|
|
348
|
-
```typescript
|
|
349
|
-
// constants/config.ts
|
|
350
|
-
|
|
351
|
-
export const GAME_CONFIG: GameConfig = {
|
|
352
|
-
boardSize: 20, // 20x20 그리λ
|
|
353
|
-
cellSize: 20, // κ° μ
20px
|
|
354
|
-
initialSpeed: 150, // 150ms (μ΄κΈ°)
|
|
355
|
-
speedDecrement: 10, // λ 벨μ
μ 10ms κ°μ
|
|
356
|
-
minSpeed: 50, // μ΅μ 50ms (μ΅κ³ λμ΄λ)
|
|
357
|
-
pointsPerFood: 10, // λ¨Ήμ΄λΉ 10μ
|
|
358
|
-
pointsForLevelUp: 50, // 50μ λ§λ€ λ 벨μ
|
|
359
|
-
};
|
|
360
|
-
|
|
361
|
-
export const COLORS = {
|
|
362
|
-
background: '#1a1a2e',
|
|
363
|
-
grid: '#16213e',
|
|
364
|
-
snake: '#00ff88',
|
|
365
|
-
snakeHead: '#00cc6a',
|
|
366
|
-
food: '#ff6b6b',
|
|
367
|
-
text: '#ffffff',
|
|
368
|
-
};
|
|
369
|
-
|
|
370
|
-
export const INITIAL_SNAKE: Point[] = [
|
|
371
|
-
{ x: 10, y: 10 }, // 머리
|
|
372
|
-
{ x: 9, y: 10 },
|
|
373
|
-
{ x: 8, y: 10 },
|
|
374
|
-
];
|
|
375
|
-
|
|
376
|
-
export const DIRECTION_VECTORS: Record<Direction, Point> = {
|
|
377
|
-
UP: { x: 0, y: -1 },
|
|
378
|
-
DOWN: { x: 0, y: 1 },
|
|
379
|
-
LEFT: { x: -1, y: 0 },
|
|
380
|
-
RIGHT: { x: 1, y: 0 },
|
|
381
|
-
};
|
|
382
|
-
|
|
383
|
-
export const OPPOSITE_DIRECTIONS: Record<Direction, Direction> = {
|
|
384
|
-
UP: 'DOWN',
|
|
385
|
-
DOWN: 'UP',
|
|
386
|
-
LEFT: 'RIGHT',
|
|
387
|
-
RIGHT: 'LEFT',
|
|
388
|
-
};
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
---
|
|
392
|
-
|
|
393
|
-
## β
μν€ν
μ² μ²΄ν¬λ¦¬μ€νΈ
|
|
394
|
-
|
|
395
|
-
- [x] μ»΄ν¬λνΈ κ΅¬μ‘° μ μ
|
|
396
|
-
- [x] λ°μ΄ν° νλ¦ μ€κ³
|
|
397
|
-
- [x] 컀μ€ν
ν
μ€κ³
|
|
398
|
-
- [x] νμΌ/ν΄λ ꡬ쑰 μ μ
|
|
399
|
-
- [x] νμ
μ μ
|
|
400
|
-
- [x] κ²μ μ€μ μμ μ μ
|
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
# Snake Game - Implementation Rules
|
|
2
|
-
# μμ±μΌ: 2026-01-21
|
|
3
|
-
# μ€ν
μ΄μ§: 03-planning
|
|
4
|
-
|
|
5
|
-
project:
|
|
6
|
-
name: snake-game
|
|
7
|
-
type: game
|
|
8
|
-
framework: react
|
|
9
|
-
language: typescript
|
|
10
|
-
|
|
11
|
-
# μ»΄ν¬λνΈ κ·μΉ
|
|
12
|
-
components:
|
|
13
|
-
type: functional # functional | class
|
|
14
|
-
naming: PascalCase
|
|
15
|
-
file_extension: tsx
|
|
16
|
-
|
|
17
|
-
# μ»΄ν¬λνΈ κ΅¬μ‘°
|
|
18
|
-
structure:
|
|
19
|
-
- props_interface # Props μΈν°νμ΄μ€ μ μ
|
|
20
|
-
- component_function
|
|
21
|
-
- exports
|
|
22
|
-
|
|
23
|
-
# μ»΄ν¬λνΈ μΉ΄ν
κ³ λ¦¬
|
|
24
|
-
categories:
|
|
25
|
-
- name: containers
|
|
26
|
-
path: src/
|
|
27
|
-
examples: [App.tsx, GameEngine.tsx]
|
|
28
|
-
- name: presentation
|
|
29
|
-
path: src/components/
|
|
30
|
-
examples: [CanvasLayer.tsx, ScoreBoard.tsx]
|
|
31
|
-
- name: ui
|
|
32
|
-
path: src/components/
|
|
33
|
-
examples: [GameOverModal.tsx, MobileControls.tsx]
|
|
34
|
-
|
|
35
|
-
# μ€νμΌλ§ κ·μΉ
|
|
36
|
-
styling:
|
|
37
|
-
method: css-modules # css-modules | tailwind | styled-components
|
|
38
|
-
naming: kebab-case
|
|
39
|
-
file_pattern: "{ComponentName}.module.css"
|
|
40
|
-
|
|
41
|
-
# μμ λ³μ (CSS Custom Properties)
|
|
42
|
-
colors:
|
|
43
|
-
background: "#1a1a2e"
|
|
44
|
-
grid: "#16213e"
|
|
45
|
-
snake: "#00ff88"
|
|
46
|
-
snake_head: "#00cc6a"
|
|
47
|
-
food: "#ff6b6b"
|
|
48
|
-
text: "#ffffff"
|
|
49
|
-
|
|
50
|
-
# μν κ΄λ¦¬
|
|
51
|
-
state_management:
|
|
52
|
-
global: useReducer # context | redux | zustand | useReducer
|
|
53
|
-
local: useState
|
|
54
|
-
refs: useRef # κ²μ 루ν, Canvas ref
|
|
55
|
-
|
|
56
|
-
# μν λΆλ¦¬ μμΉ
|
|
57
|
-
principles:
|
|
58
|
-
- "UI 리λ λλ§ νμν μν β useReducer"
|
|
59
|
-
- "λΉ λ₯Έ μ
λ°μ΄νΈ νμν μν β useRef"
|
|
60
|
-
- "Canvas DOM μ°Έμ‘° β useRef"
|
|
61
|
-
|
|
62
|
-
# ν
κ·μΉ
|
|
63
|
-
hooks:
|
|
64
|
-
naming: "use{Name}"
|
|
65
|
-
location: src/hooks/
|
|
66
|
-
|
|
67
|
-
# 컀μ€ν
ν
λͺ©λ‘
|
|
68
|
-
custom:
|
|
69
|
-
- name: useGameLoop
|
|
70
|
-
purpose: requestAnimationFrame κΈ°λ° κ²μ 루ν
|
|
71
|
-
- name: useKeyboard
|
|
72
|
-
purpose: ν€λ³΄λ μ
λ ₯ μ²λ¦¬
|
|
73
|
-
- name: useSwipe
|
|
74
|
-
purpose: ν°μΉ μ€μμ΄ν κ°μ§
|
|
75
|
-
- name: useHighScore
|
|
76
|
-
purpose: localStorage μ΅κ³ μ μ κ΄λ¦¬
|
|
77
|
-
|
|
78
|
-
# νμ
μ μ κ·μΉ
|
|
79
|
-
types:
|
|
80
|
-
location: src/types/
|
|
81
|
-
naming: PascalCase
|
|
82
|
-
|
|
83
|
-
# ν΅μ¬ νμ
|
|
84
|
-
core:
|
|
85
|
-
- Point
|
|
86
|
-
- Direction
|
|
87
|
-
- GameStatus
|
|
88
|
-
- GameState
|
|
89
|
-
- GameAction
|
|
90
|
-
- GameConfig
|
|
91
|
-
|
|
92
|
-
# μμ κ·μΉ
|
|
93
|
-
constants:
|
|
94
|
-
location: src/constants/
|
|
95
|
-
naming: SCREAMING_SNAKE_CASE
|
|
96
|
-
|
|
97
|
-
# ν΅μ¬ μμ
|
|
98
|
-
core:
|
|
99
|
-
- GAME_CONFIG
|
|
100
|
-
- COLORS
|
|
101
|
-
- INITIAL_SNAKE
|
|
102
|
-
- DIRECTION_VECTORS
|
|
103
|
-
- OPPOSITE_DIRECTIONS
|
|
104
|
-
|
|
105
|
-
# μ νΈλ¦¬ν° κ·μΉ
|
|
106
|
-
utilities:
|
|
107
|
-
location: src/utils/
|
|
108
|
-
naming: camelCase
|
|
109
|
-
|
|
110
|
-
# μ νΈλ¦¬ν° ν¨μ
|
|
111
|
-
functions:
|
|
112
|
-
- generateRandomPosition
|
|
113
|
-
- isCollision
|
|
114
|
-
- isValidDirection
|
|
115
|
-
|
|
116
|
-
# ν΄λ ꡬ쑰
|
|
117
|
-
folder_structure:
|
|
118
|
-
type: type-based # feature-based | type-based
|
|
119
|
-
|
|
120
|
-
structure:
|
|
121
|
-
src:
|
|
122
|
-
- components/ # React μ»΄ν¬λνΈ
|
|
123
|
-
- hooks/ # 컀μ€ν
ν
|
|
124
|
-
- engine/ # κ²μ λ‘μ§ (reducer, collision, renderer)
|
|
125
|
-
- types/ # TypeScript νμ
|
|
126
|
-
- constants/ # μμ
|
|
127
|
-
- utils/ # μ νΈλ¦¬ν° ν¨μ
|
|
128
|
-
- styles/ # κΈλ‘λ² μ€νμΌ
|
|
129
|
-
- assets/ # μ μ μμ°
|
|
130
|
-
|
|
131
|
-
# νμΌ λͺ
λͺ
κ·μΉ
|
|
132
|
-
file_naming:
|
|
133
|
-
components: PascalCase.tsx
|
|
134
|
-
hooks: camelCase.ts
|
|
135
|
-
types: index.ts # λ¨μΌ νμΌ λλ camelCase.ts
|
|
136
|
-
constants: camelCase.ts
|
|
137
|
-
utils: camelCase.ts
|
|
138
|
-
styles: index.css λλ {Component}.module.css
|
|
139
|
-
|
|
140
|
-
# μν¬νΈ κ·μΉ
|
|
141
|
-
imports:
|
|
142
|
-
order:
|
|
143
|
-
- react # React κ΄λ ¨
|
|
144
|
-
- external # μΈλΆ λΌμ΄λΈλ¬λ¦¬
|
|
145
|
-
- internal # λ΄λΆ λͺ¨λ (μ λ κ²½λ‘)
|
|
146
|
-
- relative # μλ κ²½λ‘
|
|
147
|
-
- styles # μ€νμΌ
|
|
148
|
-
- types # νμ
|
|
149
|
-
|
|
150
|
-
alias:
|
|
151
|
-
"@": src/
|
|
152
|
-
|
|
153
|
-
# μ½λ νμ§
|
|
154
|
-
code_quality:
|
|
155
|
-
eslint: true
|
|
156
|
-
prettier: true
|
|
157
|
-
typescript_strict: true
|
|
158
|
-
|
|
159
|
-
rules:
|
|
160
|
-
- "no-any: κ°λ₯ν ν any νμ
μ¬μ© κΈμ§"
|
|
161
|
-
- "explicit-return-types: ν¨μ λ°ν νμ
λͺ
μ"
|
|
162
|
-
- "no-unused-vars: λ―Έμ¬μ© λ³μ κΈμ§"
|
|
163
|
-
|
|
164
|
-
# ν
μ€νΈ κ·μΉ
|
|
165
|
-
testing:
|
|
166
|
-
framework: vitest
|
|
167
|
-
location: src/__tests__/ λλ μ»΄ν¬λνΈ μ {name}.test.ts
|
|
168
|
-
|
|
169
|
-
coverage_target: 80%
|
|
170
|
-
|
|
171
|
-
naming:
|
|
172
|
-
unit: "{name}.test.ts"
|
|
173
|
-
e2e: "{feature}.e2e.ts"
|
|
174
|
-
|
|
175
|
-
# μ±λ₯ κ·μΉ
|
|
176
|
-
performance:
|
|
177
|
-
# Canvas μ΅μ ν
|
|
178
|
-
canvas:
|
|
179
|
-
- "requestAnimationFrame μ¬μ©"
|
|
180
|
-
- "μ€νμ€ν¬λ¦° μΊλ²μ€ κ³ λ €"
|
|
181
|
-
- "λΆνμν 리λ λλ§ λ°©μ§"
|
|
182
|
-
|
|
183
|
-
# React μ΅μ ν
|
|
184
|
-
react:
|
|
185
|
-
- "React.memo νμμ μ¬μ©"
|
|
186
|
-
- "useCallback/useMemo κ³Όλν μ¬μ© μμ "
|
|
187
|
-
- "κ²μ μνλ useRefλ‘ κ΄λ¦¬"
|
|
188
|
-
|
|
189
|
-
# Git μ»€λ° κ·μΉ
|
|
190
|
-
git:
|
|
191
|
-
conventional_commits: true
|
|
192
|
-
|
|
193
|
-
types:
|
|
194
|
-
feat: μ κΈ°λ₯
|
|
195
|
-
fix: λ²κ·Έ μμ
|
|
196
|
-
refactor: 리ν©ν λ§
|
|
197
|
-
test: ν
μ€νΈ
|
|
198
|
-
docs: λ¬Έμ
|
|
199
|
-
style: ν¬λ§·ν
|
|
200
|
-
chore: κΈ°ν
|
|
201
|
-
|
|
202
|
-
# κΈμ§ μ¬ν
|
|
203
|
-
prohibited:
|
|
204
|
-
- "μΈλΆ κ²μ μμ§ (Phaser, PixiJS λ±)"
|
|
205
|
-
- "jQuery"
|
|
206
|
-
- "Class μ»΄ν¬λνΈ (ν¨μνλ§ μ¬μ©)"
|
|
207
|
-
- "any νμ
λ¨μ©"
|
|
208
|
-
- "μ μ λ³μ"
|
|
209
|
-
- "setInterval (requestAnimationFrame λμ μ¬μ©)"
|