feat: achieve 600 files milestone in AI knowledge base

This commit is contained in:
2026-04-20 19:10:32 +09:00
parent ed5140096e
commit ae1627c35b
713 changed files with 21197 additions and 1994 deletions
+110
View File
@@ -0,0 +1,110 @@
/**
* Custom Hook: 웹 워커를 사용하여 고성능 게임 로직을 관리합니다.
* 이 훅은 React의 상태(State)와 생명 주기(Lifecycle)를 이용하여 Web Worker와의 통신을 담당합니다.
* @returns {{ grid: Array<Array<number>>, score: number, isGameRunning: boolean, moveLeft: Function, moveRight: Function, rotate: Function }}
*/
import { useState, useEffect, useCallback } from 'react';
// 🚨 주의: 실제 프로젝트 구조에 따라 경로를 수정해야 합니다.
const worker = new Worker(new URL('../tetris-worker.js', import.meta.url), { type: 'module' });
/**
* Web Worker 기반의 Tetris 게임 로직을 관리하는 커스텀 훅.
*/
export const useGameLogic = () => {
// 초기 상태 설정 (Worker가 INIT 메시지를 보낼 때까지 대기)
const [grid, setGrid] = useState([]);
const [score, setScore] = useState(0);
const [isGameRunning, setIsGameRunning] = useState(false);
/**
* 🌐 Worker로부터 메시지 수신 처리 핸들러
*/
useEffect(() => {
// 워커가 로드되었을 때의 리스너 설정
worker.onmessage = (event) => {
const data = event.data;
switch (data.type) {
case 'READY':
console.log("Worker is ready. Game initialized.");
// 워커가 준비되면 게임 시작 플래그를 활성화할 수 있습니다.
setIsGameRunning(true);
break;
case 'INIT':
setGrid(data.data.grid);
setScore(data.data.score);
console.log("Game initialized successfully.");
// 게임 시작 후 첫 번째 메시지 처리 완료
break;
case 'UPDATE':
// 핵심 상태 업데이트: Worker가 계산한 새로운 그리드와 점수
setGrid(data.data.grid);
setScore(data.data.score);
console.log("Game state updated via worker.");
break;
default:
console.warn('Unknown message type received from worker:', data.type);
}
};
// 컴포넌트 언마운트 시 워커 종료 (메모리 누수 방지)
return () => {
worker.terminate();
};
}, []);
/**
* ⬅️ 이동 로직 호출 (좌측 이동)
*/
const moveLeft = useCallback(() => {
if (!isGameRunning) return;
// Web Worker에게 명령 전송: 충돌 검사 및 상태 업데이트는 워커 내부에서 처리됨.
worker.postMessage({ type: 'MOVE_LEFT', command: 'left' });
}, [isGameRunning]);
/**
* ➡️ 이동 로직 호출 (우측 이동)
*/
const moveRight = useCallback(() => {
if (!isGameRunning) return;
worker.postMessage({ type: 'MOVE_RIGHT', command: 'right' });
}, [isGameRunning]);
/**
* 🔄 회전 로직 호출
*/
const rotate = useCallback(() => {
if (!isGameRunning) return;
worker.postMessage({ type: 'ROTATE', command: 'rotate' });
}, [isGameRunning]);
/**
* ⬇️ 게임 틱 시작 (게임 루프 시작)
*/
const startGameTick = useCallback(() => {
if (!isGameRunning) {
// 초기화 메시지 전송 (혹시 모를 재설정을 위해)
worker.postMessage({ type: 'INIT' });
// 게임 틱을 시작하는 명령 전송
setTimeout(() => {
worker.postMessage({ type: 'TICK' });
}, 50); // 약간의 딜레이 후 첫 틱 실행
}
}, [isGameRunning]);
return {
grid,
score,
isGameRunning,
moveLeft,
moveRight,
rotate,
startGameTick
};
};
export default useGameLogic;
+82
View File
@@ -0,0 +1,82 @@
/**
* Web Worker 파일: Tetris의 모든 무거운 계산(Game Loop, 물리 엔진)을 전담합니다.
*/
// 게임 그리드 상수 정의 (20줄 x 10칸)
const GRID_WIDTH = 10;
const GRID_HEIGHT = 20;
let gridState = []; // 현재 게임 상태를 저장하는 2차원 배열
let score = 0;
/**
* 초기화 함수: 워커가 로드될 때 호출됩니다.
*/
function initializeGame() {
// 빈 그리드로 초기화
gridState = Array(GRID_HEIGHT).fill(null).map(() => Array(GRID_WIDTH).fill(0));
score = 0;
postMessage({
type: 'INIT',
data: { grid: gridState, score: score }
});
}
/**
* 게임 루프 (Game Tick) 시뮬레이션 함수.
* 이 함수가 주기적으로 호출되어 중력과 충돌을 처리합니다.
*/
function gameTick() {
// TODO: 1. 현재 떨어지는 조각(Current Piece)의 위치를 파악하고,
// TODO: 2. 아래 칸이 막혔는지 (충돌 판정), 막혔다면 그릴 그리드 상태를 업데이트해야 합니다.
// 임시 로직: 모든 셀을 한 번씩 '낙하'시키는 시뮬레이션
let newGridState = JSON.parse(JSON.stringify(gridState)); // 깊은 복사
for (let y = GRID_HEIGHT - 2; y >= 0; y--) {
for (let x = 0; x < GRID_WIDTH; x++) {
// 예시: 현재 칸에 무언가 있다면, 한 줄 아래로 내려갑니다.
if (gridState[y][x] !== 0) {
newGridState[y + 1][x] = gridState[y][x]; // 다음 위치에 복사
newGridState[y][x] = 0; // 현재 위치는 비움
}
}
}
gridState = newGridState;
// TODO: 라인 클리어 체크 및 점수 계산 로직 추가
const linesCleared = 1; // 예시 값
if (linesCleared > 0) {
score += linesCleared * 100;
}
postMessage({
type: 'UPDATE',
data: { grid: gridState, score: score }
});
}
// Web Worker 이벤트 리스너 설정 (메인 스레드로부터 메시지 수신)
self.onmessage = function(event) {
const data = event.data;
switch (data.type) {
case 'INIT':
initializeGame();
break;
case 'MOVE_LEFT':
case 'MOVE_RIGHT':
case 'ROTATE':
case 'HARD_DROP':
// TODO: 이동/회전 로직 구현 및 충돌 검사 후 상태 업데이트
console.log(`Received move command: ${data.command}`);
break;
case 'TICK':
gameTick(); // 게임 틱 실행
break;
}
};
// 초기 메시지 전송 (워커가 로드되었음을 알림)
self.postMessage({ type: 'READY' });