https://orgin00.tistory.com/50
리액트로 테트리스 만들어보자[3]
https://orgin00.tistory.com/49 리액트로 테트리스 만들어보자[2] https://orgin00.tistory.com/48 리액트로 테트리스 만들어보자[1] App.js 전체 코드입니다. 난잡하지만 끊어서 보겠습니다. 첫번째 글에서는 커..
orgin00.tistory.com
블록이 자동으로 떨어지게 만들어 보겠습니다.
useEffect(() => {
const repeatMotion = (timeStamp) => {
if (timeStamp - cur > speed[data.stage]/*시간 1000ms=1s*/) {//현재 시간과 cur의 차이가 1초가되면
if (!validateMove(CurrentBlock, map, 0, 1)) { //만약 현재 블록이 더이상 움직일수 없다면
stack(CurrentBlock, map); //쌓습니다.
ChangeBlocks();//그리고 블록을 바꿉니다.
}
setCur(timeStamp); //1초가 지났으므로 cur에 현재 시간을 저장합니다. 또다시 1초 진행시 반복됩니다.
reDraw(); //redraw.
}
/* setFilledlines(isLineFilled(map));
if (FilledLines.length > 0) {
if (timeForRemoved === 0) {
setTimeForRemoved(timeStamp);
}
if (timeStamp - timeForRemoved > 400) {
setData({
...data,
score: data.score + CalScore(FilledLines.length),
stage: CalStage(data.score + CalScore(FilledLines.length)),
});
lineRemove(FilledLines, map);
setFilledlines([]);
setTimeForRemoved(0);
reDraw();
}
}
if (
JSON.stringify(CurrentBlock.type) === JSON.stringify(NextBlock.type)
) {
setNextBlock(createRandomBlock());
reDraw();
}
if (map[1].some((c) => c > 0)) {
setOnGame(false);
alert("game Over");
}*/
repeatRef.current = requestAnimationFrame(repeatMotion);
};
//if (onGame) repeatRef.current = requestAnimationFrame(repeatMotion);
return () => cancelAnimationFrame(repeatRef.current); //언마운트시 해제해야 recursion에러가 발생하지 않습니다.
});
주석처리한 부분은 이후에 작성할 로직이므로 넘기겠습니다.
기본적으로 callback함수 requestAnimationFrame를 이용해서 함수를 무한반복 할것입니다.
repeatMotion함수를 인자로 받습니다.
validateMove.js
import { copy } from "./common";
import { move, rotate } from "./keyHandler";
/*copy.js
export const copy = (obj) => JSON.parse(JSON.stringify(obj));
//깊은 복사 는 대상 변수값이 바뀔 때 원본 변숫값은 유지된다. 아래 코드는 깊은 복사 의 예이다. 타입 스크립트에서는 number 와 boolean 타입은 깊은 복사 형태로, 객체 와 배열 은 얕은 복사 방식으로 동작한다
//wanna-b.tistory.com/18 참조
*/
export const validate = (block, matrix) => {
let isValid = true;
// some 메서드는 return true일 때 break, return false일 때는 continue 효과를 갖습니다.
block.type.some((row, dy) => {
row.some((value, dx) => {
if (value !== 0) {
if (
block.x + dx < 0 ||
block.x + dx > 9 ||
block.y + dy < 0 ||
block.y + dy > 20 ||
matrix[block.y + dy][block.x + dx] > 0
) {
isValid = false;
return true;
}
}
});
if (!isValid) {
return true;
}
});
return isValid;
};
export const validateMove = (block, matrix, x, y) => {
const newBlock = copy(block);
move(newBlock, x, y);
if (validate(newBlock, matrix)) {
move(block, x, y);
return true;
}
return false;
};
export const validateRotate = (block, matrix) => {
const newBlock = copy(block);
rotate(newBlock);
if (validate(newBlock, matrix)) {
rotate(block);
return true;
}
return false;
};
블록은 validateMove로 움직이게됩니다. 깊은복사를 이용해서 newBlock을 복사해서 움직여보고, 만약 이 움직임이 available하면 실제 블록을 move하고 true를 반환합니다.
move와 rotate함수는 아래와 같습니다.
//move는 단순히 x,y좌표를 더해주면 됩니다.
export const move = (block, x, y) => {
block.x += x;
block.y += y;
};
//rotate경우 조금 복잡합니다.
export const rotate = (block) => {
//x,y좌표를 서로 바꾸어줍니다.
block.type.forEach((row, y) => {
for (let x = 0; x < y; x++) {
const temp = block.type[x][y];
block.type[x][y] = block.type[y][x];
block.type[y][x] = temp;
}
});
//행렬을 뒤집어주면 시계방향으로 회전한 효과가 나옵니다.
block.type.forEach((row) => {
row.reverse();
});
};
//선형대수학
따라서 1초마다 블록이 아래로 떨어지고, 바닥에 닿거나 다른 블록에 닿게되면 블록이 멈추고 새로운 블록으로 바뀌게 됩니다.
이번에는 키입력에 따라 블록이 움직이고 회전하게 만들어보겠습니다.
App.js에 EventHandler를 추가합니다.
useEffect(() => {
const keyHandler = (event) => {
const inputKey = event.keyCode;
const KEY = {
LEFT: 37,
RIGHT: 39,
UP: 38,
DOWN: 40,
SPACE: 32,
};
switch (inputKey) {
case KEY.UP:
validateRotate(CurrentBlock, map);
break;
case KEY.DOWN:
validateMove(CurrentBlock, map, 0, 1);
break;
case KEY.LEFT:
validateMove(CurrentBlock, map, -1, 0);
break;
case KEY.RIGHT:
validateMove(CurrentBlock, map, 1, 0);
break;
case KEY.SPACE:
while (validateMove(CurrentBlock, map, 0, 1));
break;
default:
return;
}
};
if (onGame) window.addEventListener("keydown", keyHandler); //게임시작시 이벤트핸들러를 추가합니다.
return () => window.removeEventListener("keydown", keyHandler); //언마운트시 해제합니다.
});
다음 글에서는 위에 주석처리한 부분을 처리하겠습니다.
https://github.com/Mansook/TetrisBot
GitHub - Mansook/TetrisBot: tetris
tetris. Contribute to Mansook/TetrisBot development by creating an account on GitHub.
github.com
'react.js' 카테고리의 다른 글
[React] Kobart News 처음으로 하는 협업 프로젝트 후기 (0) | 2022.11.22 |
---|---|
리액트로 테트리스 만들어보자[5] (0) | 2022.10.31 |
리액트로 테트리스 만들어보자[3] (0) | 2022.10.31 |
리액트로 테트리스 만들어보자[2] (0) | 2022.10.31 |
리액트로 테트리스 만들어보자[1] (0) | 2022.10.31 |