🗃️javascript/프로젝트

(클론코딩)테트리스(2)

하얀성 2022. 12. 9. 17:31
//DOM
const playground = document.querySelector(".playground > ul");

//Setting
const GAME_ROWS = 20;
const GAME_COLS = 10;

//variables
let score = 0;
let duration = 500;
let downInterval;
let tempMovingItem;

const BLOCKS = {
  tree: [
      [[2,1],[0,1],[1,0],[1,1]],
      [],
      [],
      [],
  ]
}

const movingItem = {
  type:"tree",
  direction: 0,
  top: 0,
  left: 3,
};

init()

//functions
function init() {
  tempMovingItem = {...movingItem}; // movingItem의 실제 값들만 가져온다.
  for(let i=0; i<GAME_ROWS; i++) {
    prependNewLine();  
  }
  renderBlocks()
}



function prependNewLine(){ //20번 반복됨.
  const li = document.createElement("li"); // list 의 약자, ul의 요소.
  const ul = document.createElement("ul"); //unordered list의 약자. li를 하나라도 포함해야됨.
  for(let j=0; j<10; j++) {
    const matrix = document.createElement("li");
    ul.prepend(matrix); // li 10개 만든거 ul에 다 붙여
  }
  li.prepend(ul); //li 10개 만든거를 붙인, ul 하나를 li에 붙여
  playground.prepend(li); // li 10개 딸린 ul로 접착된 li 한개 붙여.(playground가 아직 배열 요소가 4개라서... 20번 반복해도 4개 나옴.)
}
function renderBlocks() {
  const { type, direction, top, left } = tempMovingItem; // 타입 설정, 이동해 있는 현재 위치값 4개가 저장됨.
  const movingBlocks = document.querySelectorAll(".moving"); // SelectorAll를 통해서 moving클래스를 가진 모든 요소를 불러옴.
  movingBlocks.forEach(moving=>{ // 불러온 moving이라는 것을 가진 요소들에 moving 매개변수로 거기 있는 type 값과 "moving"값 제거(새 값에 moving클래스 부여하기 전, moving클래스를 가진 모든 값들)
  // 이전 moving 싹다 모아서 클래스 제거부터 하고 나서, 밑에서 새로 이동한 값에도 type과 moving 클래스 값 부여. 그래서 여기서 출력 명령해도 아직 새것들은 안준상태라 안뜸.단, 명령 끝나면 부여는 되있지)
    moving.classList.remove(type, "moving"); // 불러들인 moving요소 가진 것들 중 4개의 실질값([,],[,],[,],[,])의 type,moving 빼곤 다 삭제
  })
  BLOCKS[type][direction].forEach(block => {  // block은 forEach로 훑은 요소 하나 하나를 끄집어내서 그 요소에 함수짓해서, 저장하는 매개변수.
   // BLOCKS의 [][] 배열의 몇번째 값은 x번째 배열임. 0번째의 값 [0,0], 1번째의 값 [0, 1].....이런 식으로 구성되있음 이걸 foreach가 요소 하나씩 건드는것.
    const x = block[0] + left; // x는 ul안에 들어 있는 li의 값 -> 몇번째 줄 안의 몇번째 li인지를 알려주는 값.
    const y = block[1] + top; // y는 li의 row값 -> 몇번째 줄인지 알려주는 값.  
    const target = playground.childNodes[y] ? playground.childNodes[y].childNodes[0].childNodes[x] : null; // target의 범위는 y값이 허락되는 부분까지!
    const isAvailable = checkEmpty(target); // target 검사결과 저장
    if(isAvailable){ // y범위 안
      target.classList.add(type, "moving") // target에 클래스 속성값들추가(type으로 tree 타입부여 함. tree타입은 css에 .tree로 지정해둠. moving도 부여해서 moving을 통해 행동제어 가능. )
    }else{// y범위 밖
   tempMovingItem = {...movingItem} // 넘어가면 못넘어가게끔 바로 이전 값으로 되돌림.(색칠 명령 못받았으니, 그만큼 색칠된 공간 갯수가 줄어듬)
      setTimeout(()=>{ // 잠시 renderBlocks를 빼놨다가 실행
        renderBlocks();
      },0) // 0은 몇초간 멈출 건가 물어보는 setTimeout메서드의 고유 요소임.
      // renderBlocks() tempMovingItem으로 원상복구 시키고서 그것을 다시 색칠하는 것으로 끝내려했는데... 재귀함수라서 첫 renderblock()의 하위의 renderblock()으로 독단적 행위가 이어지면서 결국 밑도끝도없이 나가지게됨. 그래서 setTimOut메서드로 하위에서 빠져나와서 동등한 위치에서 다시 실행하게 함.  그래서 저 tempMoving을 무시하지 않은 덕에 되돌리고, 그 값에만 renderBlock() 적용이 가능해짐.
    }
  })
     
      movingItem.left = left; // 값들 계속 증가된것들 저장하는 공간.
      movingItem.top = top;
      movingItem.direction = direction;
   
 
}
function checkEmpty(target){
  if(!target){
    return false;
  }
  return true;
}
function moveBlock(moveType, amount){ // moveType은 tempMoving을 통해 rendering함.
  tempMovingItem[moveType] += amount; // tempmoving 안의 moveType인 top, left 값을 바꿔줌. 실질적 현재 이동한 값들 4개 보유.
  renderBlocks()
}

//event handling (이 event 발생 전에는 )
document.addEventListener("keydown", e=> { // 키보드의 동작을 인식하는 함수
  switch(e.keyCode){
    case 39:
      moveBlock("left", 1); // 0.0에서 시작했으니, left라는 변수에 1을 저장해서, 1만큼 오른쪽이동
      break;
    case 37:
      moveBlock("left", -1)  //0.0에서 시작했으니, left라는 변수에 -1을 저장해서, -1만큼 왼쪽이동
      break;
    case 40:
      moveBlock("top", 1); 
      break;
      default:
      break;  


  }
  // console.log(e)
})

 

이해되는 부분까지만...

 


 

옆으로 나가지 않게끔 만들어줌. 근데 옆으로 나가는 걸 막아주는 기능구현 부분 코드가 이해가 안된다.

 

-> 낮에 이해가 안됬는데 밤에 곰곰히 생각해보고 찾아보니 이해가 됨

 

<몰랐던 부분>

1.setTimeout 메서드(() => {}, 시간) 

시간이 흐른 뒤에 {}를 실행해라. 

 

2.() => {}의 의미는 ()안의 변수를 {}의 매개변수로 사용한다는 뜻이다.

method( ){

이것과 동일함. 그런데 복잡할 때 더 편하게 설정가능해져서 사용함..

 

3. function이 붙지 않은 새로운 메서드는 내가 모르는 고유 메서드이니.. 바로 인터넷에 찾아보도록하자.

 

 

<느낀점>

 

진도는 더딘데 확실히 많이 배운다.

js 기초강의 들어보면 이해가 확 와닿는다. 

일단 cs든 코테든.. 프로젝트든 셋다 제대로 안되는 상황이니... 우선 지금하는 프로젝트에만 집중해야겠단 생각이다.

cs가 쉽더라도 나에겐 아직 어렵다...