이번 포스트에서는 React와 styled-components를 활용하여 슬라이딩 퍼즐 게임을 구현하는 방법에 대해 알아보겠습니다. 슬라이딩 퍼즐은 사용자가 조각을 이동시켜 원래의 이미지를 재구성하는 게임으로, 이 게임을 구현함으로써 React 컴포넌트와 상태 관리, 이미지 처리 등에 대한 이해를 높일 수 있습니다.
- src
- components
- Puzzle.tsx
- PuzzleContainer.tsx
- PuzzleControls.tsx
- PuzzlePiece.tsx
- PuzzleRow.tsx
- PuzzleUploader.tsx
- RenderPuzzle.tsx
- utils
- util.ts
- atom
- atom.ts
- App.tsx
- index.tsx
Slide Puzzle 게임을 만들기 위해 상태 관리를 위한 Recoil 패키지를 설치하고 설정합니다. Recoil은 React 상태를 관리하기 위한 라이브러리로, 상태를 전역으로 관리하고 컴포넌트 간에 상태를 공유할 수 있게 해줍니다.
npm install recoil
// atom.ts
import { atom } from "recoil";
export const puzzleStateAtom = atom<number[][]>({
key: "puzzleState",
default: [
[1, 2, 3],
[4, 5, 6],
[7, 8, null],
],
});
export const moveCountAtom = atom<number>({
key: "moveCount",
default: 0,
});
export const userImageAtom = atom<string | null>({
key: "userImage",
default: null,
});
export const isChallengeStartedAtom = atom<boolean>({
key: "isChallengeStarted",
default: false,
});
// 다른 atom들도 추가적으로 정의합니다.
PuzzleContainer
컴포넌트를 구현합니다.PuzzleControls
컴포넌트를 구현합니다. 컴포넌트의 주요 기능은 다음과 같습니다:originalPuzzleState
배열을 펼쳐서 각 피스의 인덱스와 이미지를 가진 객체로 변환합니다.undefined
또는 null
값으로 표시됩니다.1
인 경우, 마지막 피스와 빈 피스의 위치를 교환합니다. 이렇게 함으로써 빈 피스를 맨 뒤로 이동시킵니다.PuzzlePiece
컴포넌트를 구현합니다.PuzzleRow
컴포넌트를 구현합니다.PuzzleUploader
컴포넌트를 구현합니다.handleImageUpload
함수가 이미지 파일 선택 이벤트를 처리합니다.event.target.files
를 통해 가져옵니다.resizeImage
함수에 전달하여 리사이징합니다.resizeImage
함수는 이미지를 지정된 최대 너비와 높이에 맞게 조정하고, 리사이즈된 이미지의 데이터 URL을 반환합니다.resizeImage
함수는 Promise를 사용하여 비동기적으로 이미지 리사이징 작업을 처리합니다.splitImage
함수를 통해 퍼즐 조각으로 분할됩니다.splitImage
함수는 canvas를 사용하여 이미지를 3x3 격자로 분할하고, 각 조각의 데이터 URL과 인덱스를 반환합니다.pieces
배열에 객체 형태로 저장됩니다.RenderPuzzle
컴포넌트를 구현합니다.이번 포스트에서는 React를 사용하여 슬라이딩 퍼즐 게임을 구현한 방법에 대해 작성해 보았습니다. 이미지를 불러와서 셔플해서 슬라이드하는 간단한 퍼즐이라고 생각했는데. 생각보다 배열구조를 신경써야하는 부분이 많았던것같아요. 처음엔 useState를 이용해서 관리했는데 점점 파일이 커지면서 컴포넌트를 나누다보니 확실히 리코일을 쓰는게 장점이 있겠다고 생각했고. 좋은 샘플코드가 되었다고 생각합니다.
자세한 코드는 해당리포지토리에서 참고 가능합니다.
https://github.com/woori3104/slidePuzzle.github.io