728x90
반응형
🧱 1. 블럭 데이터 구조 정의
const TETROMINOS = {
I: { shape: [[1, 1, 1, 1]], color: 'cyan-500' },
J: { shape: [[1, 0, 0], [1, 1, 1]], color: 'blue-500' },
L: { shape: [[0, 0, 1], [1, 1, 1]], color: 'orange-500' },
O: { shape: [[1, 1], [1, 1]], color: 'yellow-500' },
S: { shape: [[0, 1, 1], [1, 1, 0]], color: 'green-500' },
T: { shape: [[0, 1, 0], [1, 1, 1]], color: 'purple-500' },
Z: { shape: [[1, 1, 0], [0, 1, 1]], color: 'red-500' },
};
블럭 모양은 2차원 배열로 표현되고 색상은 Tailwind 클래스 문자열로 지정됩니다.
📀 2. 게임 보드 설정
const BOARD_WIDTH = 10;
const BOARD_HEIGHT = 20;
const createEmptyBoard = () => Array.from({ length: BOARD_HEIGHT }, () => Array(BOARD_WIDTH).fill(0));
10x20 크기의 보드이며, 초기에는 모두 0으로 채워져 있습니다.
🔄 3. 게임 상태 관리
const [board, setBoard] = useState(createEmptyBoard());
const [currentPiece, setCurrentPiece] = useState(null);
const [score, setScore] = useState(0);
const [gameOver, setGameOver] = useState(false);
React의 useState를 이용해 게임 상태(보드, 현재 블럭, 점수, 게임 종료 상태 등)를 관리합니다.
🔀 4. 블럭 생성 및 랜덤 선택
const randomTetromino = () => {
const keys = Object.keys(TETROMINOS);
const randKey = keys[Math.floor(Math.random() * keys.length)];
return TETROMINOS[randKey];
};
새 블럭은 TETROMINOS 객체에서 무작위로 선택됩니다.
🎯 5. 충돌 검사 및 유효성 체크
const checkCollision = (x, y, shape) => {...};
const isValidMove = (x, y, shape) => !checkCollision(x, y, shape);
보드의 경계나 이미 존재하는 블럭과의 충돌 여부를 판단합니다.
🕹️ 6. 키보드 조작 처리
useEffect(() => {
const handleKeyPress = (e) => {
if (gameOver) return;
switch (e.key) {
case 'ArrowLeft': moveLeft(); break;
case 'ArrowRight': moveRight(); break;
case 'ArrowDown': moveDown(); break;
case 'ArrowUp': rotate(); break;
}
};
window.addEventListener('keydown', handleKeyPress);
return () => window.removeEventListener('keydown', handleKeyPress);
}, [moveLeft, moveRight, moveDown, rotate, gameOver]);
키보드 방향키를 통해 블럭을 이동하고 회전시킵니다.
📦 7. 블럭 고정 및 줄 제거
const placePiece = () => {...};
const clearLines = (newBoard) => {...};
블럭이 더 이상 아래로 이동할 수 없을 경우 고정하고, 줄이 가득 찬 경우 해당 줄을 삭제합니다.
📉 8. 레벨과 속도 조절
if (Math.floor(newScore / 500) > level - 1) {
setLevel(prev => prev + 1);
setDropTime(prev => prev * SPEED_INCREASE_FACTOR);
}
점수가 증가하면 레벨이 오르고, 블럭의 낙하 속도가 빨라집니다.
🎵 9. 음악 기능 추가
<audio ref={audioRef} src="https://hebbkx1anhila5yf.public.blob.vercel-storage.com/Tetris-kxnh5j7hpNEcFspAndlU2huV5n6dvk.mp3" />
게임에 배경 음악을 추가하고, 버튼으로 재생/정지할 수 있도록 구성했습니다.
🧱 10. 보드 렌더링
<div style={{ gridTemplateColumns: `repeat(${BOARD_WIDTH}, 1fr)` }}>
{board.map((row, y) =>
row.map((_, x) => (
<motion.div className={...} />
)))}
</div>
각 셀을 Tailwind 스타일의 motion.div로 렌더링하여 애니메이션 효과를 줍니다.
🔁 11. 게임 리셋 기능
const resetGame = () => {
setBoard(createEmptyBoard());
setCurrentPiece(null);
setScore(0);
setGameOver(false);
setDropTime(INITIAL_DROP_TIME);
setLevel(1);
}
게임을 초기 상태로 재시작합니다.
✅ 정리
이 테트리스 프로젝트는 React 학습에 아주 좋은 실습 예제입니다. Tailwind와 framer-motion을 통해 시각적으로도 높은 완성도를 보여줄 수 있습니다.
소스 코드
728x90
반응형
'개발 언어 > Java, Javascript' 카테고리의 다른 글
개발 효율을 2배로! 숨겨진 꿀템, Top 10 무료 Tailwind 기반 UI 라이브러리 (2) | 2025.05.13 |
---|---|
놓치면 후회할 12가지 오픈소스 풀스택 JavaScript 프로젝트 (0) | 2025.05.11 |
[Java] 자바 Graphics - 마우스로 선그리기 소스예제 (0) | 2012.05.14 |
[Java] 자바 Graphics - 원 그래프 그리기 (0) | 2012.05.14 |
[Java Thread Swing] 카운트 업 레이블 만들기 (0) | 2012.05.14 |