JS30 day30 - Whack a Mole Game
作業內容
今天的作業是做出打地鼠的遊戲,這個練習我想主要是可以練習到遞迴的使用比較特別
學到什麼
-
JS
- 第一次在 JS 裡面用到遞迴!我們如果想要每次的洞都跟上一個不同,可以做判斷,如果跟上一個一樣的話就重新跑一次本身這個函數直到不重複為止
1 2 3 4 5 6 7 8 9 10
| 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) }
|
- 要讓地鼠不停出現,在這次也是使用遞迴的做法,在每次上一個地鼠消失的時候,如果時間還沒到就再次觸發一次這個 function 讓地鼠出現
1 2 3 4 5 6 7 8 9
| 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) }
|
- 如果去看
click
這個事件裡面的屬性,有一個 isTrusted
屬性,這個屬性如果是真正 user 點的才會是 true, 如果使用 JS 模擬去點的他預設會是 false
參考資料:
https://github.com/wesbos/JavaScript30
code 內容:
HTML:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| 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 score += 1 this.classList.remove('up') scoreBoard.textContent = score }) )
function startGame(){ scoreBoard.textContent = 0 timeUp = false score = 0 peep() setTimeout(()=>{ timeUp = true }, 10000) }
|