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

테트리스 JS - 2

by 인디코더 2018. 12. 8.

테트리스 2번째...


1. 제한 구역 정하기_ createMatrix

function createMatrix(w, h){
const matrix = [];
while(h--){
matrix.push(new Array(w).fill(0));
}
return matrix;
}
/*
Q. createMatrix의 용도는 무엇일까?
알아두어야 할 것.
while(h--) : h가 0이 될때까지 반복문 수행됨.
matrix.push(new Array(w).fill(0));
: push라는 메서드는 값을 넣을 수 있다.
: new Array()새로운 배열 값의 길이가 w만큼 0을 넣어준다.*/

const arena = createMatrix(12,20);
console.log(arena); console.table(arena);

arena의 구역은 12, 20의 크기이다. 실행을 하고 f12를 눌러서 콘솔로 확인해보면 

알 수 있다. 


2. 플레이어의 값을 아레나에 전달하기_merge

merge 함수의 목적은 플레이어의 값을 arena에 모두 넣어 줄 것이다. 
arena의 좌표와 player의 좌표에 맞게. 

function merge(arena, player){
player.matrix.forEach((row,y)=>{
row.forEach((value, x) =>{
if(value !== 0){
arena[y + player.pos.y][x + player.pos.x] =value;
}
})
})
}

우선, player의 matrix 값을 읽어서 arena의 해당 값을 넣어준다.

결과값을 보면 ... merge(matrix,player)를 하게 되면, 하고conole.table(arena)를 하게 되면

값이 입혀지는 것을 알 수 있다.

하지만 merge로는 블럭을 멈출 수 없다. 

그래서 우리는 블럭을 멈추기 위해서

collide(충돌하다) 함수를 만들 것이다. 


3. 테트리스 조각 멈추기 _collide


[원래 코드]
function collide(arena, player){
const [m,o] = [player.matrix, player.pos];
for(let y = 0; y <m.length ; ++y){
for(let x = 0; x < m[y].length; ++x){
if(m[y][x] !== 0 &&
(arena[y + o.y]&&
arena[y + o.y][x + o.x]) !==0){
return true;
}
}
}
return false;
}

[이해하기 쉽게 바꾼 코드]
function collide(arena, player){
const [m,o] = [player.matrix, player.pos];
//Q1. 왜 배열에 배열들을 넣어주었을까? => alias라고 생각하자
//player.pos의 값은 어떻게 읽히는가?
for(let y = 0; y <player.matrix.length ; ++y){
for(let x = 0; x < player.matrix[y].length; ++x){
if(player.matrix[y][x] !== 0 && //사용자 피스가 존재여부 분별
(arena[y + player.pos.y]&&
arena[y + player.pos.y][x + player.pos.x]) !==0){
return true;
}
}
}
return false;
}
/*
arena는 12, 20 크기의 배열의 0으로 채워져 있다.
collide함수에서 arena와 player의 matrix를 받아들이게 된다.
*/


function playerDrop(){
player.pos.y++;
if( collide(arena, player)){
//if 아래 부분은 collide 함수가 true값을 반환해주면 나타나게 되는 것이다.
player.pos.y--;
merge(arena, player);
player.pos.y = 0;
}
dropCounter = 0;
}


collide는 arena의 값이 1인지 아닌지 여부를 판단한다.

merge는 player의 값을 arena에 그대로 넣어준다.

1을 감지하고 merge가 되면 늦기때문에 y를 -- 해준다.

createMatrix에서 우리는 앞서 12, 20만큼만 0으로 채워주었다. 

그 외의 값은 0이 아닌 다른 값 

그래서 , arena의 영역 밖에 나아가게 되면 테트리스 조각은 멈추고 merge를 실행하게 된다.


이부분은 정말 헷갈리기도 하다 앞에 JS-1 에서 타이머도 어려웠지만 이부분도 자세하게 이해하려면 그림을 그려보는 것을 추천한다.

여기 까지 하면 이제 arena의 값을 넣어 주는것까지 되었다. 하지만 실제로 해보면

그림과 같이 된다. 조각들의 그림이 입혀지지가 않는다. 그래서 이것을 입히는 작업을 할 것이다.

function draw(){
context.fillStyle ="#000";
context.fillRect(0,0,canvas.width,canvas.height);
drawMatrix(arena, {x:0, y:0}) //*** 추가한 부분
drawMatrix(player.matrix, player.pos);
}

앞서, 사용자의 matrix를 그려주었다면 이번에는 arena를 그려주면 끝, x, y는 이동좌표가 없으니 0으로 ..

collide의 연장선으로 


function playerMove(dir){
player.pos.x += dir;
if(collide(arena,player)){
player.pos.x -= dir;
}
}

//http://pomle.github.io/keycode/
document.addEventListener('keydown', event => {
if(event.keyCode === 37){
// player.pos.x--;
playerMove(-1);
} else if(event.keyCode === 39){
// player.pos.x++;
playerMove(+1);
} else if(event.keyCode === 40){
/*
player.pos.y++;
dropCounter = 0; */ //=> 같은 동작을 통합하는 작업을 함. playerDrop()함수로.
playerDrop();
}
});

결국, matrix는 바깥영역을 벗어나면 다시 한자리 돌아오게 되는것을 반복하게 된다. 

하지만 사람눈에만 보이지 않을 뿐이다.

아마 밀리세컨드초 단위로 나눠지는 카메라로 촬영을 한다면 알아볼지도 모른다.

반응형