JS30-30-Whack-A-Mole

打地鼠遊戲

目標

  • 打地鼠遊戲

成品

[DEMO] | [GitHub]


學習紀錄

將此專案拆分成多個小部份,一個一個完成後,再將它們組合起來。
需完成事項清單:

  • 隨機出現哪隻地鼠
  • 地鼠出現停留的時間
  • 如何開始遊戲與結束遊戲
  • 遊戲的總時間
  • 判斷是否有打到地鼠
  • 紀錄打到地鼠的分數
開發的過程順序如下

1.

先完成 隨機出現哪隻地鼠地鼠出現停留的時間 這二個的部份,
所以函式分別為 randomHole()randomTime()

2.

接下來的部份為 如何開始遊戲與結束遊戲遊戲的總時間
所以對照的函式為 peep()startGame()

3.

最後就是 判斷是否有打到地鼠紀錄打到地鼠的分數 了,
對照的函式為 監聽每隻地鼠click事件bonk()

整段程式碼
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
70
71
72
73
74
75
76
77
78
79
const holes = document.querySelectorAll('.hole'); // 地洞
const scoreBoard = document.querySelector('.score'); // 分數
const moles = document.querySelectorAll('.mole'); // 地鼠
let lastHole; // 紀錄 最後一次出現的地洞
let timeUp = false; // 開關遊戲Flag(false:開,true:關)
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) {
console.log('與上次重覆了!!');
return randomHole(holes);
}

// 紀錄 最後一次的地洞
lastHole = hole;
return hole;
}

// 呼叫地鼠出現
function peep() {
const time = randomTime(200, 1000); // 取得 地鼠出現停留的時間
const hole = randomHole(holes); // 隨機取得一個地鼠

// 新增class(地鼠出現)
hole.classList.add('up');

// 出現時間結束後,移除class
setTimeout(() => {
// 移除class(地鼠消失)
hole.classList.remove('up');
// 判斷是否結束遊戲
if (!timeUp) peep();
}, time);
}

// 啟動遊戲
function startGame() {
// 清空遊戲分數
scoreBoard.textContent = 0;
// 開關遊戲Flag(false:開,true:關)
timeUp = false;
// 紀錄遊戲分數
score = 0;
// 啟動遊戲
peep();
// 設定遊戲時間(時間到關掉遊戲)
setTimeout(() => timeUp = true, 10000)
}

// 打地鼠
function bonk(e) {
// e.isTrusted
// 若事件物件是由「使用者操作」而產生,isTrusted 值為 true
// 若事件物件是由程式碼所建立、修改,或是透過 EventTarget.dispatchEvent() 來觸發,則 isTrusted 值為 false。
// https://www.w3schools.com/jsref/event_istrusted.asp

// 防止腳本操作(避免別人用程式呼叫,俗稱外掛)
if(!e.isTrusted) return;

// 加一分
score++;
// 移除class(地鼠消失)
this.parentNode.classList.remove('up');
// 更新UI總分數
scoreBoard.textContent = score;
}

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