일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 항해99
- 항해플러스
- SW
- JavaScript
- redux-toolkit
- react
- Python
- useDispatch
- createSlice
- 테코테코
- 이코테
- redux-saga
- Algorithm
- programmers
- java
- 프로그래머스
- axios
- 코딩테스트합격자되기
- 알고리즘
- 리액트
- react-router
- 매일메일
- 자바
- sw expert academy
- Get
- json-server
- maeil-mail
- C++
- redux
- react-redux
- Today
- Total
Binary Journey
[React][Clone] Chess 게임 만들기 - 3. 체스말 움직이기 본문
이전글
[React][Clone] Chess 게임 만들기 (single-player) - 2. (2) 체스판 모양 갖추기, require 로 image 파일 가져오기
이전 글 2021/02/09 - [React] - [React][Clone] Chess 게임 만들기 (single-player) - 2. (1) board settings [React][Clone] Chess 게임 만들기 (single-player) - 2. (1) board settings 이전 글 2021/02/09 -..
binaryjourney.tistory.com
참고한 영상
www.youtube.com/watch?v=kBR7pDLcC3A&t=2462s
사실 영상 목차를 안 봤는데 정말로 다음 차례가 "Moving the pieces" 였다.
react-dnd (drag and drop) 라이브러리를 이용하여 체스말을 움직여보자..!
나는 몰랐지만 react-dnd 에도 hook이 있다...!
useDrag 라는 훅을 쓸 것이다.
useDrag 가 있으면 useDrop 도 있을까..?
(있음, 궁금해서 확인해 봄)
Piece 에 react-dnd 의 useDrag 를 import 한다.
// /src/Piece.js
// (중략)
import { useDrag } from 'react-dnd';
function Piece({ piece: { type, color } }) {
const [, drag] = useDrag({
item: { type: 'piece', id: `${type}_${color}`}
});
const pieceImg = require(`./assets/${type}_${color}.png`).default;
return (
<div className="piece-container" ref={drag}>
영상에서는 useDrag를 쓸 때 item, type, id는 무조건 (mandatory라고 강조함) useDrag를 쓸 때 필요하다고 말하였다.
이건 나중에 react-dnd 홈페이지 가서 더 알아봐야겠다.
여기까지 하면 이미지가 예쁘게? 깔끔하게 떼서 이동되지만 문제는 뒤에 square까지 같이 붙어서 이동한다.
그래서 DragPreviewImage 를 import 하여 사용해야 한다.
// /src/Piece.js
import { useDrag, DragPreviewImage } from 'react-dnd';
// ...
const [, drag, preview] = useDrag({
item: { type: 'piece', id: `${type}_${color}`}
});
// ...
return (
<>
<DragPreviewImage connect={preview} src={pieceImg} />
<div className="piece-container" ref={drag}>
useDrag hook을 받는 array변수에 preview를 추가하고
DragPreviewImage 컴포넌트를 배치한 다음 추가한 preview와 pieceImg를 property 로 넣어준다
그리고 <></> fragment로 DragPreviewImage와 <img> 태그를 감싸주었다.
말을 옮겨보면 뒤에 상자는 없어지고 유령처럼 떠다닌다.
말이 preview지 뭔가 잔상을 남기는 효과 같다.
말을 옮기면 원래 있던 위치는 텅 비어야 하는데 계속 말이 남아있다. 이를 해결해보겠다.
// /src/Piece.js
// ...
const [{ isDragging }, drag, preview] = useDrag({
item: { type: 'piece', id: `${type}_${color}`},
collect: (monitor) => ({ isDragging: !!monitor.isDragging() })
});
// ...
return (
{/*...*/}
<div className="piece-container" ref={drag} style={{ opacity: isDragging ? 0 : 1}}>
useDrag 를 받는 array변수에 { isDragging } 이라는 객체 변수를 추가해주고
useDrag 안에 들어가는 값 중 collect 값을 변경하여 넣어주는 것 같다.
이는 홈페이지에서 hook이 무슨 역할을 하고 어떻게 사용하는지 더 파악해봐야 할 것 같다.
그리고 변경사항이 반영되어 나온 isDragging 을 style에 조건부와 함께 넣어준다.
컴파일된 화면을 보면
drag하고 난 자리에 말이 없고 빈자리만 남아있는 걸 볼 수 있다.
이제 말을 들어올리는 데까지 했으니 놓는 것도 진행할 것이다.
BoardSquare.js 에 react-dnd 의 useDrop 을 import 한다.
// /src/BoardSquare.js
import { useDrop } from 'react-dnd';
옮기는 위치에 drag한 값 (useDrag에서 넣어준 item 부분)
const [{ isDragging }, drag, preview] = useDrag({
item: { type: 'piece', id: `${type}_${color}`},
collect: (monitor) => ({ isDragging: !!monitor.isDragging() })
});
{ type: 'piece', id: `${type}_${color}`} << 이 값이 잘 들어오는지 콘솔로 먼저 확인부터 해보겠다.
콘솔로 확인할 부분은 useDrop 에 들어갈 drop 부분에 넣어주면 된다.
// /src/BoardSquare.js
// ...
function BoardSquare({piece, black}) {
const [ , drop] = useDrop({
accept: 'piece',
drop: (item) => console.log(item)
});
return (
<div className="board-square" ref={drop}>
<Square black={black} >
{ piece && <Piece piece={piece} /> }
코드 작성 뒤 말들을 움직여 보며 콘솔창을 확인해보면
(나이트-퀸-킹-폰즈 움직여봄)
이제 움직인 위치에 말을 놓을텐데 필요한 함수를 만들어야 한다.
먼저 Board 컴포넌트에 위치를 알려줄 함수를 작성한다. (isBlack 함수 밑에 작성하면 됨)
// /src/Board.js
function getPosition (i) {
const { x, y } = getXYPosition(i);
const letter = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'][x];
return `${letter}${y + 1}`;
}
letter 은 체스판의 가로 자리(x축)를 의미하고
y는 1부터 시작하도록 1을 더해 return 해주는 것 같다.
만든 getPosition 함수는 BoardSquare에 property로 넘겨준다.
<BoardSquare piece={piece} black={isBlack(index)} position={getPosition(index)} />
그리고 Game.js 에 move 라는 함수를 만들어준다.
// /src/Game.js
export function move (from, to) {
// 자리값을 확인하고 싶다면
// console.log(from, to)
const legalMove = chess.move({ from, to });
if (legalMove) {
gameSubject.next({ board: chess.board() });
}
}
내 생각에는 chess.js 에 말과 체스 규칙이 다 들어가있는 것 같다.
그래서 저 move 를 통해서 유효한 움직임인지 파악하여 true/false 값을 주고
유효하면 말을 옮기고 그 상황을 App.js 구독한 지점에서 파악하여 업데이트 해주는 것 같다.
만든 move 함수는 BoardSquare에 import 하여 아까 콘솔창에서 값을 확인한 자리에 넣어준다.
// /src/BoardSquare.js
import React from 'react';
import Square from './Square';
import Piece from './Piece';
import { useDrop } from 'react-dnd';
import { move } from './Game';
function BoardSquare({piece, black, position}) { // position property 추가
const [ , drop] = useDrop({
accept: 'piece',
drop: (item) => move() // 변경된 자리
});
return (
<div className="board-square" ref={drop}>
<Square black={black} >
{ piece && <Piece piece={piece} position={position} /> } {/* position 추가 */}
</Square>
</div>
);
}
export default BoardSquare;
move 함수는 from 과 to 에 위치를 input으로 받아야 하는데 없으므로 Board에서 받은 property position을 Piece 컴포넌트까지 넘겨준다.
Piece는 useDrag 에 넣어준 id 부분에 position을 추가하면 된다.
// /src/Piece.js
item: { type: 'piece', id: `${position}_${type}_${color}`},
그리고 BoardSquare drop 부분에도 반영해주면 된다.
// /src/BoardSquare.js
drop: (item) => {
const [ fromPosition ] = item.id.split('_');
move(fromPosition, position);
}
여기까지 한 경우 화면에서는 체스 말이 움직이는 대로 놓이고 흑백 주고 받으며 대결까지 할 수 있다.
'React' 카테고리의 다른 글
[React][Clone] Chess 게임 만들기 - 4. useDrag 궁금증 풀기 (0) | 2021.04.02 |
---|---|
[React][Clone] Chess 게임 만들기 - 2. (2) 체스판 모양 갖추기, require 로 image 파일 가져오기, default 의 필요성 (0) | 2021.02.10 |
[React][Clone] Chess 게임 만들기 - 2. (1) board settings (0) | 2021.02.09 |
[React][Clone] Chess 게임 만들기 - 1. setting (0) | 2021.02.09 |
[React][react-quickly review #1] 속성(props), 상태(state), 바벨(babel) 상태비저장 컴포넌트 관련 필기 (0) | 2020.09.28 |