우찬쓰 개발블로그

자바스크립트로 웹 테트리스 만들기(5) 본문

테트리스 개발기

자바스크립트로 웹 테트리스 만들기(5)

이우찬 2021. 3. 27. 23:08
반응형

이제 테트리스 게임같긴 한데 뭔가 밋밋하죠?

 

네 맞습니다.. 색상을 입혀야 겠군요.

 

여기까지 만들고나서 지인들에게 조언을 구해보니 중요한 사실이 있었습니다.

 

테트리스의 각 블록은 이미 암묵적으로 정해진 색상이 있더군요(저도 이때 처음 알게되었음)

 

그래서 저도 그 색상을 따다가 블럭의 설계도에 추가해 봤습니다.

 

/**
 ****□□□□****
 **/
class BlockTypeOne {
  constructor() {
    this.widthBlockCount = 4;
    this.widthBlockMarginCount = 0;
    this.heightBlockCount = 1;
    this.heightBlockMarginCount = 1;
    this.blockColor = "#8CD6F3";
    this.shape = [
      [0, 1],
      [1, 1],
      [2, 1],
      [3, 1],
    ];
    this.rotationBlueprint = [
      [
        [2, -1],
        [2, 0],
        [2, 1],
        [2, 2],
      ],
      [
        [-2, 1],
        [-1, 1],
        [0, 1],
        [1, 1],
      ],
    ];
  }
}

/**
 ****□□□*****
 *****□******
 **/
class BlockTypeTwo {
  constructor() {
    this.widthBlockCount = 3;
    this.widthBlockMarginCount = 1;
    this.heightBlockCount = 2;
    this.heightBlockMarginCount = 1;
    this.blockColor = "#BC48A9";
    this.shape = [
      [1, 1],
      [2, 1],
      [2, 2],
      [3, 1],
    ];
    this.rotationBlueprint = [
      [
        [0, 0],
        [1, 1],
        [1, 0],
        [1, -1],
      ],
      [
        [0, 0],
        [1, -1],
        [1, 0],
        [2, 0],
      ],
      [
        [1, -1],
        [1, 0],
        [1, 1],
        [2, 0],
      ],
      [
        [-1, 1],
        [0, 1],
        [0, 2],
        [1, 1],
      ],
    ];
  }
}

...
...

 

그리고 처음의 각 블록을 정의할때 blockArray에는 블록이 쌓여있는지 아닌지 여부인 Boolean으로만 지정했었죠?

 

그렇게 하면 색상을 지정할 수가 없으니, 객체로 변경해 봅시다.

 

function initBlockArray(blockArray) {
  for (let x = 0; x < widthBlockCount; x++) {
    blockArray[x] = new Array(heightBlockCount);
    for (let y = 0; y < heightBlockCount; y++) {
      blockArray[x][y] = {
        isExist: false,
      };
    }
  }

  clearBlockArray(blockArray);
}

 

초기화하는 부분을 객체로 바꾸고, 블럭이 쌓이면서 controlBlock에서 stackedBlock으로 copy될때 해당 블럭의 색상을 입혀줍니다.

 

function copyBlockArray(blockArray) {
  let tmpArray = new Array(widthBlockCount);
  initBlockArray(tmpArray);
  for (let x = 0; x < widthBlockCount; x++) {
    for (let y = 0; y < heightBlockCount; y++) {
      copySingleBlock(tmpArray[x][y], blockArray[x][y]);
    }
  }
  return tmpArray;
}

function copySingleBlock(blockTo, blockFrom) {
  blockTo.isExist = blockFrom.isExist;
  blockTo.blockColor = blockFrom.blockColor;
}

 

그리고 이제보니.. 앞으로 어떤 블럭이 나올것인지 표시를 안해주는 군요.. 이 부분도 추가해봅니다.

 

/**
 * preview block setting
 */
const previewBlockLocation = [
  [430, 50],
  [430, 150],
  [430, 250],
  [430, 350],
];

const justPreviewBlockRadius = 45;
const previewBlockRadius = 30;

class PreviewBlockManager {
  constructor() {
    this.previewBlockArray = new Array(4);
    for (let i = 0; i < previewBlockLocation.length; i++) {
      let radius;
      if (i == 0) {
        radius = justPreviewBlockRadius;
      } else {
        radius = previewBlockRadius;
      }
      this.previewBlockArray[i] = new PreviewBlock(
        previewBlockLocation[i][0],
        previewBlockLocation[i][1],
        radius
      );
    }
  }
  
...
...

앞으로 보여줄 블럭을 4개정도 보여주면 될것 같으니 4개를 array로 추가하고, 앞으로 추가될 controlBlock은 여기서 꺼내오면 되겠죠?

 

그리고 또 이제보니.. 블럭을 임시 저장할 공간이 있으면 좋겠네요. (hold 기능)

 

이 부분도 추가해 봅시다.

 

/**
 * shift block setting
 */
const shiftBlockLocationX = 50;
const shiftBlockLocationY = 50;

const shiftBlockRadius = 45;

class ShiftBlock {
  constructor() {
    this.shiftBorderWidth = shiftBlockRadius / 15;
    this.shiftBlockSize = (shiftBlockRadius * 4) / 15;
    this.shiftedBlock = null;
    this.isAlreadyShiftedThisTime = false;
  }

  setShiftBlock(controlBlockType) {
    this.shiftedBlock = controlBlockType;
    this.refreshData();
  }

  isShiftedBlockEmpty() {
    if (this.shiftedBlock == null) {
      return true;
    } else {
      return false;
    }
  }
  
...
...

 

현재 hold된 블럭이 없으면 그냥 현재 controlBlock을 저장하고 끝나지만, 만약 이미 저장된 블럭이 있다면 현재의 controlBlock과 교환하면 되겠죠?

 

그리고 한 controlBlock 생성당 한번씩만 되도록 제한하는게 좋겠네요.

 

shiftControlBlock() {
  if (this.shiftBlock.isAlreadyShiftedThisTime) {
    return;
  }

  this.shiftBlock.isAlreadyShiftedThisTime = true;

  if (this.shiftBlock.isShiftedBlockEmpty()) {
    this.shiftBlock.setShiftBlock(this.controlBlock.controlBlockType);
    this.controlBlock.addNewControlBlock();
  } else {
    let tmpBlockType = this.shiftBlock.shiftedBlock;
    this.shiftBlock.setShiftBlock(this.controlBlock.controlBlockType);
    this.changeControlBlock(tmpBlockType);
  }

  this.reDraw();
}

 

자 이제 테스트 해볼까요?

 

아니 이렇게 이쁠수가?! (당시의 감정)

 

흑백톤만 보다가 감동이 밀려왔습니다..

 

뭔가 이제 시중에 내놓아도(에바참치) 팔릴것만 같은 뿌듯함이 밀려옵니다.

 

근데 아직 끝난게 아니죠!

 

6부에 계속..

반응형
Comments