iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 30
0
Modern Web

JS30 錄系列 第 30

Day 30 - Whack A Mole !

  • 分享至 

  • xImage
  •  

任務目標

今天是最後一天!就以 JS 30 最後一篇打地鼠作結。
範例連結

作法

首先是 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>
    <!-- 中間省略 2 ~ 5 -->
    <div class="hole hole6">
      <div class="mole"></div>
    </div>
  </div>

要怎麼讓打地鼠運行呢?

首先要讓地鼠在隨機的時間內從隨機的洞洞冒出來。地鼠界又把這個規則稱作「地鼠亂竄原理」。

接著,要讓地鼠被打擊到時,獲得分數!

最後,讓遊戲在固定時間內結束,並且有按鈕可以重啟遊戲。

只要滿足這三個條件,就可以得到一台網頁打地鼠機。
來看看要怎麼隨機時間隨機洞洞,首先是隨機時間:

// 隨機時間
function randTime(min, max) {
  return Math.round(Math.random() * (max - min) + min);
}

隨機時間比較單純,傳入最大值跟最小值,計算出最大值跟最小值之間的整數隨機值並回傳即可。

再來是隨機洞洞:

const holes = document.querySelectorAll('.hole');
let lastHole;

// 隨機地洞
function randHole(holes) {
  const idx = Math.floor(Math.random() * holes.length);
  const hole = holes[idx];
  if(hole === lastHole) {
    console.log('Repeat hole.');
    randHole(holes);
  }
  lastHole = hole;
  return hole;
}

隨機洞洞我們另外給個限制,不希望地鼠連續好幾次出現在同個洞洞。為此必須記錄上一個洞洞 lastHole

holes 得到的是所有洞洞元素組成的清單,用 length 屬性取得洞洞總量,接著用 Math.random() 配合 Math.floor() 製造出隨機的洞洞編號,就可以指定隨機洞洞了。

設置條件,如果和最後一次出現的洞重複了,就重跑一次函式,直到跑出新的洞為止。

記得在函式末端將這次的洞記錄為最後一次出現的洞,下次跑函式時才能用來判斷重複。然後回傳洞洞結果。

接著要來利用隨機時間跟隨機洞洞讓地鼠亂竄了。請看以下程式碼:

// 遊戲時間到會顯示 true
let timeUp = false;

function peep() {
  const time = randTime(200, 800);
  const hole = randHole(holes);
  hole.classList.add('up');
  setTimeout(() => {
    hole.classList.remove('up');
    if(!timeUp) peep();
  }, time)
}

peep()函式每次啟動時,會先用 randHole(holes) 選個隨機洞,然後冒出來!在0.2 ~ 0.8秒的隨機時間 randTime(200, 800) 後鑽回去。如果遊戲時間還沒到,就會呼叫新的 peep() 讓新的地鼠冒出來!

棒,來看看怎麼打擊到這些地鼠:

const moles = document.querySelectorAll('.mole');
const scoreBoard = document.querySelector('.score');

function bonk(e) {
  if(!e.isTrusted) return;
  score++;
  this.classList.remove('up');
  scoreBoard.textContent = score;
}

moles.forEach(mole => mole.addEventListener('click', bonk))

讓這些該死的地鼠被點擊到都會讓你的分數增加,並且被打到的地鼠就讓它縮回地洞。

但是如果我寫程式碼狂點地鼠不就好了?這時候可以用滑鼠點擊事件的 isTrusted 屬性來阻止假點擊, isTrusted 可以分辨這個點擊是否為玩家操控,或是自動觸發的。

最後是讓遊戲開始:

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

遊戲開始前一般都會有初始化的動作,例如分數歸零,遊戲時間結束的判斷重置等等,初始化後就設置計時器並讓第一個地鼠冒出來即可。

以上就是 JS 30 最終章!終於完賽了,透過這三十天的練習成長了不少,希望這些成長紀錄也有幫助到擁有同樣困擾的人們!如果有什麼好想法歡迎討論!再會了!謝謝大家!

Reference

isTrusted
完整程式碼


上一篇
Day 29 - Final Countdown
系列文
JS30 錄30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
LeeBoy
iT邦新手 4 級 ‧ 2018-01-18 12:01:33

這個好玩

0
JasonYang
iT邦新手 5 級 ‧ 2018-01-18 12:49:35

喔喔喔喔喔喔喔喔喔喔喔喔喔!!!!
好好玩喔!

我要留言

立即登入留言