본문 바로가기
카테고리 없음

테트리스 JS - 3

by 인디코더 2018. 12. 8.

테트리스 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'),
}


반응형