Anthony Chao

JS30 day30 Whack a Mole Game

#Javascript

JS30 day30 - Whack a Mole Game

作業內容

今天的作業是做出打地鼠的遊戲,這個練習我想主要是可以練習到遞迴的使用比較特別

學到什麼

  • JS
    1. 第一次在 JS 裡面用到遞迴!我們如果想要每次的洞都跟上一個不同,可以做判斷,如果跟上一個一樣的話就重新跑一次本身這個函數直到不重複為止
    function randomHole(holes){
      const idx = Math.floor(Math.random() * holes.length)
      const hole = holes[idx]
      if(hole === lastHole){
        console.log("重複了")
        return randomHole(holes);
      } 
      lastHole = hole
      console.log(hole)
    }
    1. 要讓地鼠不停出現,在這次也是使用遞迴的做法,在每次上一個地鼠消失的時候,如果時間還沒到就再次觸發一次這個 function 讓地鼠出現
    function peep(){
      const hole = randomHole(holes)
      const time = randomTime(200, 1000)
      hole.classList.add('up')
      setTimeout(function(){
        hole.classList.remove('up')
        if(!timeUp) peep()
      }, time)
    }
    1. 如果去看 click 這個事件裡面的屬性,有一個 isTrusted 屬性,這個屬性如果是真正 user 點的才會是 true, 如果使用 JS 模擬去點的他預設會是 false

參考資料:
https://github.com/wesbos/JavaScript30

code 內容:

HTML:

<h1>Whack-a-mole! <span class="score">0</span></h1>
<button onClick="startGame()">Start!</button>

<div class="game">
  <div class="hole hole1">
    <div class="mole"></div>
  </div>
  <div class="hole hole2">
    <div class="mole"></div>
  </div>
  <div class="hole hole3">
    <div class="mole"></div>
  </div>
  <div class="hole hole4">
    <div class="mole"></div>
  </div>
  <div class="hole hole5">
    <div class="mole"></div>
  </div>
  <div class="hole hole6">
    <div class="mole"></div>
  </div>
</div>

CSS:

html {
  box-sizing: border-box;
  font-size: 10px;
  background: #ffc600;
}

*, *:before, *:after {
  box-sizing: inherit;
}

body {
  padding: 0;
  margin: 0;
  font-family: 'Amatic SC', cursive;
}

h1 {
  text-align: center;
  font-size: 10rem;
  line-height: 1;
  margin-bottom: 0;
}

.score {
  background: rgba(255,255,255,0.2);
  padding: 0 3rem;
  line-height: 1;
  border-radius: 1rem;
}

.game {
  width: 600px;
  height: 400px;
  display: flex;
  flex-wrap: wrap;
  margin: 0 auto;
}

.hole {
  flex: 1 0 33.33%;
  overflow: hidden;
  position: relative;
}

.hole:after {
  display: block;
  background: url(dirt.svg) bottom center no-repeat;
  background-size: contain;
  content: '';
  width: 100%;
  height:70px;
  position: absolute;
  z-index: 2;
  bottom: -30px;
}

.mole {
  background: url('mole.svg') bottom center no-repeat;
  background-size: 60%;
  position: absolute;
  top: 100%;
  width: 100%;
  height: 100%;
  transition:all 0.4s;
}

.hole.up .mole {
  top: 0;
}

JS:

  const holes = document.querySelectorAll('.hole');
  const scoreBoard = document.querySelector('.score');
  const moles = document.querySelectorAll('.mole');
  let lastHole
  let timeUp = false
  let score = 0

  // 以微秒顯示,這時間是決定地鼠會出現多久才消失的時間
  function randomTime(min, max){
    return Math.round(Math.random() * (max - min) + min)
  }

  function randomHole(holes){
    const idx = Math.floor(Math.random() * holes.length)
    const hole = holes[idx]
    if(hole === lastHole){
      return randomHole(holes);
    } 
    lastHole = hole
    return hole
  }

  function peep(){
    const hole = randomHole(holes)
    const time = randomTime(200, 1000)
    hole.classList.add('up')
    setTimeout(function(){
      hole.classList.remove('up')
      if(!timeUp) peep()
    }, time)
  }

  moles.forEach( mole => mole.addEventListener('click', (e)=>{
    if(!e.isTrusted) return //如果不是真的 user 點的, isTrusted 這個屬性 = false(比方說 JS 點的)
    score += 1
    this.classList.remove('up')
    scoreBoard.textContent = score
  }) )

  function startGame(){
    scoreBoard.textContent = 0
    timeUp = false
    score = 0
    peep()
    setTimeout(()=>{ timeUp = true }, 10000)
  }