ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 지뢰찾기를 만들어보자 #8 - 사용자 인터페이스 변경 1/4
    기술 관련/etc 2022. 10. 9. 20:19

    지난번 글에서 지뢰찾기의 점수에 대해 이야기 했었다. https://mc500.tistory.com/674 이번 글에서는 몇 가지 사용자 인터페이스 변경을 해 보도록 하겠다.

    1. 지뢰 및 깃발 크기 조절

    현재 지뢰와 깃발의 이미지 원본에도 약간의 공간이 있다. 하지만 상자에 너무 가득 찬 느낌이 있어 상하좌우 약간의 공간을 두어 크기를 조절하도록 하자.

    ctx.drawImage(this.sprite, 0, 0, 1162, 1162, x+offset, y+offset, w-offset*2, w-offset*2)

    상자 크기와 1:1
    3px씩 줄어든 크기 적용


    2. 게임 시작 버튼 및 성공 실패 시 alert 대체

    Windows 에 있던 지뢰 찾기 게임는 노란색 스마일 아이콘이 게임의 시작과 상태 및 종료를 표시하고 있었다. 이걸 구현해 보고자 한다.
    지뢰와 깃발 이미지처럼 게임 상태를 나타내는 다음과 같은 이미지 파일을 만들고 이용해 보도록 하자.

    스마일

    각각의 이미지는 다음과 같은 경우에 표시된다.

    • 왼쪽 위 : 게임 전 / 사용자 입력 대기
    • 오른쪽 위 : 클릭 시 지뢰가 없는 경우
    • 오른쪽 아래 : 클릭 시 지뢰가 있는 경우
    • 왼쪽 아래 : 게임에 성공한 경우

    먼저 이미지를 위한 새로운 Canvas를 만들어 보자

    <canvas id="header" width="260" height="30"></canvas>

    그리고, Box에서와 같이 변수와 초기화 코드를 작성한다.

      header: {
        canvas: undefined,
        ctx: undefined,
        sprite: undefined,
      },
      header_width: 260,
      header_height: 30,
    let header = this.header
    header.canvas = document.getElementById("header");
    header.ctx = header.canvas.getContext("2d");
    header.sprite = new Image()
    header.sprite.src = "/faces.png";
    header.sprite.addEventListener('load', function() {
      self.drawFace()
    }, false)
    
    header.canvas.addEventListener("mouseup", function(evt) {
      let x = Number.parseInt(evt.offsetX)
      let y = Number.parseInt(evt.offsetY)
      evt.preventDefault()
      evt.stopPropagation()
    
      console.log('mouse up: '+evt.button+': '+x+','+y)
      return false
    }, false)
    header.canvas.addEventListener("mousedown", function(evt) {
      let x = Number.parseInt(evt.offsetX)
      let y = Number.parseInt(evt.offsetY)
      evt.preventDefault()
      evt.stopPropagation()
    
      console.log('mouse down: '+evt.button+': '+x+','+y)
      return false
    }, false)

    그리고, 스마일 얼굴을 헤더 중간에 그리는 method를 마저 추가한다.

    drawFace() {
      let header = this.header
    
      let w = 30
      let x = (this.header_width-w)/2
      let y = (this.header_height-w)/2
      header.ctx.drawImage(header.sprite, 0, 0, 618, 618, x, y, w, w)
    },

    이제 기존 버튼을 삭제하고 저 얼굴을 클릭하면 게임이 시작되도록 해보자.

    header.canvas.addEventListener("mousedown", function(evt) {
      let x = Number.parseInt(evt.offsetX)
      let y = Number.parseInt(evt.offsetY)
      evt.preventDefault()
      evt.stopPropagation()
    
      console.log('mouse down: '+evt.button+': '+x+','+y)
    
      let w = self.box_width
      let lx = (self.header_width-w)/2
      let ly = (self.header_height-w)/2
      let mx = lx + w
      let my = ly + w
    
      if (lx < x && x < mx && ly < y && y < my) {
        self.onClickMainButton()
      }
    
      return false
    }, false)


    다음은 처음 의도했던 대로 클릭을 했을 때 얼굴이 변할 수 있도록 drawFace() method를 수정하고 필요한 경우 호출한다.

    drawFace(type) {
      let header = this.header
    
      let w = 30
      let x = (this.header_width-w)/2
      let y = (this.header_height-w)/2
      let offset_x = 0
      let offset_y = 0
      switch(type) {
      default:
      case CONST_FACE.smile:
        break;
      case CONST_FACE.surprise:
        offset_x = 618
        break;
      case CONST_FACE.win:
        offset_y = 618
        break;
      case CONST_FACE.lose:
        offset_x = 618
        offset_y = 618
        break;
      }
      header.ctx.drawImage(header.sprite, offset_x, offset_y, 618, 618, x, y, w, w)
    },
      if (win) {
        this.highscores[this.level] = record
        this.drawFace(CONST_FACE.win)
      } else {
        this.drawFace(CONST_FACE.lose)
      }

    그리고, 추가적으로 클릭했을 때 지뢰를 건드리지 않았을 때 표정이 변하도록 수정한다.

      if (evt.button == 0) { // left
        self.drawFace(CONST_FACE.surprise)
    
        if (self.rightTimerId) {
          self.drawFace()
          clearTimeout(self.rightTimerId)
          self.rightTimerId = undefined
          self.examine(x, y)
          return false
        }
        self.leftTimerId = setTimeout(() => {
          self.drawFace()
          self.leftTimerId = undefined
          self.dig(x, y)
        }, dblclick_wait)
      }
      else if (evt.button == 2) { // right
        if (self.leftTimerId) {
          self.drawFace()
          clearTimeout(self.leftTimerId)
          self.leftTimerId = undefined
          self.examine(x, y)
          return false
        }
        self.rightTimerId = setTimeout(() => {
          self.rightTimerId = undefined
          self.flagup(x, y)
        }, dblclick_wait)
      }

    그리고, 눈에 잘 띄게 만들었던 빨간색 Canvas 배경을 없애준다.

    canvas {
      /* background: red; */
      display: block;
      margin: 0 auto;
    }


    그 다음으로 바꿔 볼 만한 부분으로 현재 점수와 남은 깃발의 갯수를 표시하는 부분이 있는데, 이는 다음 글에서 다뤄보도록 하겠다.

Designed by Tistory.