iT邦幫忙

2023 iThome 鐵人賽

DAY 30
0
Modern Web

JS30 x 鐵人30 x MDN doc系列 第 30

[Day30] - Whack A Mole(JS30 x 鐵人 30 x MDN)

  • 分享至 

  • xImage
  •  

做一個打地鼠遊戲網站,按下開始後可以開啟遊戲(約 10 秒)、有計分功能、地鼠會隨機出現,腳本作弊點擊不計分

觀察 index-Start.html 結構可以發現六個洞口,各裝著一隻地鼠,並且我們轉往 css 觀察可以發現當洞口有.upclass 時地鼠則會出現。

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

且作者也已將我們今天需要使用的節點都寫好了,因此我們要做的事就是讓地鼠於遊戲時間內隨機短暫出現再消失,,被使用者點擊會的話計分並消失。

// 所有洞口
const holes = document.querySelectorAll(".hole");
// 所有地鼠
const moles = document.querySelectorAll(".mole");
//  計分板
const scoreBoard = document.querySelector(".score");

我這邊的作法與作者不同,不是用 setTimout 切換一個變數的 Boolean 值去判斷遞迴要不要繼續執行,我選用週期執行 setInterval,並於 setTimout 後清除週期執行 clearInterval,且當使用者重複點擊開始遊戲時,都要清掉上次的週期執行 setInterval 以及結束遊戲的 setTimout,因此我需要宣告兩個全域變數來供存放。

  1. 全域變數供儲放、刪除 setInterval 及 setTimout 用
//  用以儲存週期執行冒出地鼠的setInterval
let interval;
//  用以儲存時間到後要結束遊戲的setTimout
let timeout;
  1. 遊戲開始函式:因為作者於button遊戲開始按鈕上寫了另一種事件觸發函式的方法,因此我們不需要再於 javascript 中寫這個點擊事件監聽器,直皆著手寫startGame函式即可。
  <button onClick="startGame()">Start the game!</button>
function startGame() {
  // 遊戲時間/單位毫秒
  const gameTime = 10000;
  // 地鼠出現間隔/單位毫秒
  const circleTime = 500;
  scoreBoard.textContent = "0";
  // 清除上次遊戲的重複執行
  clearInterval(interval);
  // 清除上次遊戲的結束遊戲setTimeout
  clearTimeout(timeout);

  //  開始重複執行冒出地鼠函式
  interval = setInterval(() => {
    moleUp(circleTime);
  }, circleTime);
  //  設定延時後要結束遊戲
  timeout = setTimeout(() => {
    clearInterval(interval);
  }, gameTime);
}
  1. 地鼠冒出函式:隨機產生要冒出頭的地鼠,並只有短暫出現。
function moleUp(circleTime) {
  //  依照地鼠NodeList長度去隨機產生index
  const randomIndex = Math.floor(Math.random() * holes.length);
  //  隨機index的那個地數 掛上 up class
  holes[randomIndex].classList.add("up");
  //  指定延時候移除 up class ,達到地鼠短暫出現的效果
  setTimeout(() => {
    holes[randomIndex].classList.remove("up");
  }, circleTime);
}
  1. 計分方式:將每個地鼠都新增點擊事件監聽器
moles.forEach((mole) => mole.addEventListener("click", countScore));
  1. countScore 函式:透過事件的 isTrusted 屬性是否為 true 來確認事件由用戶實際的操作觸發的,不是透過程式、腳本點擊,那麼才會計分。
function countScore(e) {
  if (e.isTrusted) scoreBoard.textContent = Number(scoreBoard.textContent) + 1;
  this.closest(".hole").classList.remove("up");
}

👉Github Demo 頁面 👈

👉 好想工作室 15th 鐵人賽看板 👈

參考資料

  1. Javascript 30 官網
    https://javascript30.com/
  2. MDN 官網
    https://developer.mozilla.org/en-US/

上一篇
[Day29] - Countdown Timer(JS30 x 鐵人 30 x MDN)
系列文
JS30 x 鐵人30 x MDN doc30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
Jessie
iT邦新手 5 級 ‧ 2023-10-15 10:31:31

恭喜完賽/images/emoticon/emoticon12.gif

我要留言

立即登入留言