https://orgin00.tistory.com/49
리액트로 테트리스 만들어보자[2]
https://orgin00.tistory.com/48 리액트로 테트리스 만들어보자[1] App.js 전체 코드입니다. 난잡하지만 끊어서 보겠습니다. 첫번째 글에서는 커스텀훅으로 게임화면,크기를 지정하고 canvas를 이용해 게임
orgin00.tistory.com
지금까지 작성한 그림그리기와 기본 상태관리를 바탕으로
이번 글 부터는 그림을 그리고, 게임 로직을 작성하겠습니다.
querySelector와 캔버스 매소드인 getContext를 이용해서 드로잉 컨텍스트를 반환합니다. getContext의 인자는 2d 입니다.
보드와, 다음 블록이 나오는 박스의 컨텍스트를 반환하면 reDraw함수를 작성합니다.
//보드
const board = document.querySelector(".board");
const boardctx = board?.getContext("2d");
//다음블록이 나오는 박스
const box = document.querySelector(".nextBlockBox");
const boxctx = box?.getContext("2d");
//그림 그리기
const reDraw = () => {
drawBlock(CurrentBlock, boardctx);
drawBlock(NextBlock, boxctx, "NextBlockBox");
drawBoard(map, boardctx);
};
drawBlock.js
//함수의 인자로 block,context,그리고 type이 있습니다.
export const drawBlock = (block, ctx, type = "default") => {
if (ctx && block !== undefined) { //ctx가 존재하고 block이 undefined가 아닐경우
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
block.type.forEach((row, y) => { //y열 row열요소
row.forEach((value, x) => { row열 요소에대해 x행
if (value > 0) {
ctx.fillStyle = blockColor(block.type); //block.type(number)에대해 색설정
//nextBlockBox에 들어가는 블록의 경우 x,y좌표가 +1 되어있습니다.
if (type === "NextBlockBox")
roundRect(ctx, 1 + x + block.x, 1 + y + block.y, 1, 1, 0.1);
else roundRect(ctx, x + block.x, y + block.y, 1, 1, 0.1);
} else if (value < 0) {
ctx.fillStyle = blockColor(block.type);
roundRect(ctx, x + block.x, y + block.y, 1, 1, 0.1);
}
});
});
}
};
drawBoard.js
export const drawBoard = (matrix, ctx) => {
if (ctx) {
matrix.forEach((row, y) => {
row.forEach((value, x) => {
if (value > 0) { //배열에 0은 빈칸이고 1보다 큰경우 블록이므로 색을 칠해주어야합니다.
ctx.fillStyle = readColor(value);
roundRect(ctx, x, y, 1, 1, 0.1);
}
});
});
}
};
roundRect.js
export const roundRect = (ctx, x, y, width, height, radius = 1) => {
if (radius !== 0) {
radius = { tl: radius, tr: radius, br: radius, bl: radius };
} else {
radius = { tl: 0, tr: 0, br: 0, bl: 0 };
}
ctx.beginPath();
ctx.moveTo(x + radius.tl, y);
ctx.lineTo(x + width - radius.tr, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius.tr);
ctx.lineTo(x + width, y + height - radius.br);
ctx.quadraticCurveTo(
x + width,
y + height,
x + width - radius.br,
y + height
);
ctx.lineTo(x + radius.bl, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius.bl);
ctx.lineTo(x, y + radius.tl);
ctx.quadraticCurveTo(x, y, x + radius.tl, y);
ctx.closePath();
ctx.fill();
ctx.lineWidth = 0.088;
ctx.strokeStyle = "white";
ctx.stroke();
};
이제 UseEffect를 이용하여 그림을 그립니다.
useEffect(() => {
const setBoard = () => {
if (board) {
board.width = boardWidth;
board.height = boardHeight;
boardctx?.scale(blockSize, blockSize); //1 pixel을 blockSize만큼 scale합니다.
}
if (box) {
box.width = blockSize * 5;
box.height = blockSize * 5;
boxctx?.scale(blockSize, blockSize);
}
reDraw();
};
setBoard();
});
이제 그림을 그렸으므로, 게임로직을 작성하겠습니다.
필요한 함수를 정의합니다.
//현재 블록이 바닥에 정지하는 경우 nextblock으로 바꾸고, nextblock은 랜덤 블록으로 설정합니다.
const ChangeBlocks = () => {
setCurrentBlock({
...NextBlock,
x: NextBlock.x + 3,
});
setShowBlock({
x: NextBlock.x + 3,
y: NextBlock.y,
type: NextBlock.type.map((row) => row.map((c) => c * -1)),
});
setNextBlock(createRandomBlock());
};
페이지가 마운트되면 initMatrix를 실행하고, currentblock을 x축으로 3만큼 이동시킵니다.
useEffect(() => {
setMap(initMatrix());
setCurrentBlock({ ...CurrentBlock, x: CurrentBlock.x + 3 });
setShowBlock({
...CurrentBlock,
});
}, []);
다음 글에서 블록이 시간에 따라 자동으로 떨어지고, 키보드 입력을 받아 움직이게 만들어 보겠습니다.
https://github.com/Mansook/TetrisBot
'react.js' 카테고리의 다른 글
[React] Kobart News 처음으로 하는 협업 프로젝트 후기 (0) | 2022.11.22 |
---|---|
리액트로 테트리스 만들어보자[5] (0) | 2022.10.31 |
리액트로 테트리스 만들어보자[4] (0) | 2022.10.31 |
리액트로 테트리스 만들어보자[2] (0) | 2022.10.31 |
리액트로 테트리스 만들어보자[1] (0) | 2022.10.31 |