테트리스 3번째 입니다요 ~ ㅎㅎ
거의 다왔다 조금만 더 하자 !!
1. rotation , 테트리스 돌리기
사진처럼 테트리스 배열을 회전하고 바꿀것이다.
function rotate(matrix, dir){
for(let y = 0; y < matrix.length; ++y){
for(let x = 0; x< y; ++x){
[
matrix[x][y],
matrix[y][x]
] =
[
matrix[y][x],
matrix[x][y]
]
}
}
if(dir > 0){
matrix.forEach(row => row.reverse());
} else {
matrix.reverse();
}
}
/*
우선, 예제를 한번 하자 , 만약 두 객체의 값을 서로 교환하려면 어떻게 해야할까>?
var a = 'aaa'
var b = 'bbb'라면
var temp = a
b=a
a=temp 라고 한다면 a, b의 값이 서로 바뀌어 있을 것이다.
또다른 방법이 있다.
바로 [a, b] = [b, a] 방법이다.
이건 그냥 받아들여야 하는거 같다.
matrix[x][y] == a, matrix[y][x] == b 라고 했을 때,
[a,b] = [b,a] 식대로 성립되어서 rotate의 형태가 나온다.
여기서 x,y의 위치도 바뀌어 있는 것을 알 수 있는데,
[a,b] = [b,a] 형태가 성립될려면
x, y 값을 서로 바꿔놔야 한다.
실제로 값을 넣어보면 확인 할 수 있다.
여기까지가 transpose 부분이다.
transpose만 한다면 모형이 반대로 뒤집혀 출력이 된다.
그래서 그것을 다시 뒤집어 주는 작업을 해야한다.
그것이 바로 reverse 함수이다.
reverse는 말 그대로 뒤집는 함수 이다.
matrix.forEach(row => row.reverse());
matrix.reverse();
의 차이는 왼쪽으로 뒤집느냐 또는 오른쪽으로 뒤집느냐 차이이다.
그림에서도 설명이 되었듯이
transpose(이항하다, 위치를 바꿔 놓다) + reverse(뒤집다) = rotate(회전)
이러한 관계가 성립이 된다.
*/
2. 옆으로 넘어가지 않게 하기
function playerMove(dir){
player.pos.x += dir;
if(collide(arena,player)){
player.pos.x -= dir;
}
}
/*
←를 누르면 -1
→를 누르면 +1 이 dir 값으로 들어가게 된다.
pos.x에 -1을 계속 더하게 되었을 때, arena의 바깥 값과 충돌이 될것이다.
그렇게 되면
player.pos.x -= dir; 에 - + - = + 가 되어서
뒤로 빠꾸,,ㅋㅋㅋ +1이 되고
+1 같은 경우 반대로 -1이 되어서
playerDrop() 과 같이 적용이 될것이다
*/
if(event.keyCode === 37){
// player.pos.x--;
playerMove(-1);
} else if(event.keyCode === 39){
// player.pos.x++;
playerMove(+1);...
3. 옆면 회전, 방지.
function playerRotate(dir){
const pos = player.pos.x;
let offset = 1;
rotate(player.matrix, dir);
while (collide(arena, player)){
console.log("1. Before pos.x : "+player.pos.x)
player.pos.x += offset;
console.log("2. After pos.x : "+player.pos.x)
offset = - (offset + (offset > 0 ? 1 : -1));
console.log("After offset : "+offset);
// 여기까지... 벽에 부딪혔을 때
if( offset > player.matrix[0].length){
console.log("player.matrix[0].length : " + player.matrix[0].length)
console.log("offset : " + offset)
rotate(player.matrix, -dir);
player.pos.x = pos;
return;
}
}
}
이건 그림이랑 보는 것이 더욱 편할 것이다.
우선 보았을 때 벽과 부딪히면 while문이 실행이 된다. offset은 계속 +1에서 시작 했으니,
-2, +3, -4, +5... 이렇게 숫자가 변한다. 그런데 이렇게만 변하는 게 아니라.
player.pos.x - 2, player.pos.x + 3 , player.pos.y - 4,... 이런식으로 빠르게 되는 것이다.
그렇게 연산을 여러번 해서 아래 사진과 같은 노란색 좌표에 player.pos.x 를 위치시킬려고 하는것이었다.
=> rotation 된 것의 좌표를 arena 안쪽에 찍어주기 위해 offset 만큼 더해진 곳에 위치 시킨다.
offset의 숨은 규칙이 있는 거 같은데... 아직 확실하게 찾지는 못했다 .
그렇다면 offset > player.matrix[0].length 일때는 언제일까,
원래느 offset 만큼 더해줘서 위치 시킬려고 했지만 더해주어도 소용이 없을때는 다시 역 Rotation을 하게 된다
그러면 결국 자기 자신이 되어서 , 그대로 내려 앉게 된다. 두번째 아래 사진을 보자
저 알고리즘을 왜 저렇게 짰는지는 정말 한번 더 생각해 봐야겠다.
코드가 쉽지는 않다.
4. 도형 바꾸기
function createPiece(type){
if(type === 'T'){
return [
[0, 0, 0],
[0, 1, 0],
[1, 1, 1],
];
} else if(type === 'O'){
return [
[2, 2],
[2, 2],
];
}else if(type === 'L'){
return [
[0, 3, 0],
[0, 3, 0],
[0, 3, 3],
];
}else if(type === 'J'){
return [
[0, 4, 0],
[0, 4, 0],
[4, 4, 0],
];
}else if(type === 'I'){
return [
[0, 5, 0, 0],
[0, 5, 0, 0],
[0, 5, 0, 0],
[0, 5, 0, 0],
];
}else if(type === 'S'){
return [
[0, 6, 6],
[6, 6, 0],
[0, 0, 0]
];
}else if(type === 'Z'){
return [
[7, 7, 0],
[0, 7, 7],
[0, 0, 0],
];
}
}
function playerReset(){
const pieces = 'ILJOTSZ';
player.matrix = createPiece(pieces[pieces.length * Math.random() | 0]);
player.pos.y = 0;
player.pos.x = (arena[0].length / 2 | 0)-(player.matrix[0].length /2 | 0);
if (collide(arena, player)){
arena.forEach(row => row.fill(0)); //0으로 다 만들어 주는 역할..
player.score = 0;
updateScore();
}
}
// |0 => 소숫점이하를 찍어주지 않는다.
const player = {
pos : { x:5, y:5 },
matrix: createPiece('T'),
}
반응형