30 - Whack A Mole
俗話說的好,一天一蘋果,醫生遠離我
一天一 JS,What the f*ck JavaScript?
small steps every day - 記錄著新手村日記
完成目標
做一個打地鼠的遊戲
- 功能
- 一個關卡要幾分鐘要固定
- 地鼠冒出來、自動縮下去的時間間隔要不一樣
- 畫面
- 畫面要顯示目前的關卡
- 地鼠要自動冒出來、縮下去
- 地鼠被點到要縮下去、數量要增加
index_START.html
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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Whack A Mole!</title> <link href='https://fonts.googleapis.com/css?family=Amatic+SC:400,700' rel='stylesheet' type='text/css'> <link rel="stylesheet" href="style.css"> </head> <body>
<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>
<script> const holes = document.querySelectorAll('.hole'); const scoreBoard = document.querySelector('.score'); const moles = document.querySelectorAll('.mole');
</script> </body> </html>
|
style.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 - step by step
首先,我們先將需要的元素選取起來,必須先找到地鼠洞的List、地鼠圖的List、 span
的數量
1 2 3 4 5 6 7 8 9
| <script> const holes = document.querySelectorAll('.hole'); const scoreBoard = document.querySelector('.score'); const moles = document.querySelectorAll('.mole'); console.log(holes) console.log(scoreBoard) console.log(moles)
</script>
|
先來製作一個函式,讓這個函式執行後有一個上下限的隨機時間
1 2 3 4 5 6 7 8 9 10
| <script> const holes = document.querySelectorAll('.hole'); const scoreBoard = document.querySelector('.score'); const moles = document.querySelectorAll('.mole');
function randomTime(min, max) { let time = Math.floor(Math.random() * (max - min) + min); return time }; </script>
|
接下來,我們來取得隨機一個 hole
元素,如果與上一次取到的相同,我們就再次執行一次隨機選取的函式,不同的話就把現在的Hole指定給變數 lastHole
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <script> const holes = document.querySelectorAll('.hole'); const scoreBoard = document.querySelector('.score'); const moles = document.querySelectorAll('.mole');
function randomTime(min, max) { let time = Math.floor(Math.random() * (max - min) + min); return time };
let lastHole; function randomHole(holes) { const idx = Math.floor(Math.random() * holes.length); const hole = holes[idx]; if (hole === lastHole) { console.log('Ah nah thats the same one bud'); return randomHole(holes); } lastHole = hole; return hole; } </script>
|
時間都處理完畢後,我們要來來地鼠可以從地鼠洞跑出來,在前面的CSS當中可以知道,地鼠的一開始是被做了相對定位並 top:100%
及 overflow:hidden
起來了!因此剛開始的時候地鼠其實是偷偷躲在底下的w
現在只要判斷什麼時候加上一個 Class 讓地鼠從地鼠洞出來以及多久會從地鼠洞出來一次,要新增&移除 Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <script> let timeUp = false;
function peep() { const time = randomTime(200, 1000); const hole = randomHole(holes); hole.classList.add('up'); setTimeout(() => { hole.classList.remove('up'); if (!timeUp) peep(); }, time); } </script>
|
最後,再加上遊戲開始及點到一個就增加分數吧!這部分比較單純只要將 score
宣告變數出來,以及點到分數++就可以,然後趕緊來打地鼠吧w
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <script> moles.forEach(mole => mole.addEventListener('click', bonk));
function bonk(e) { if(!e.isTrusted) return; score++; this.parentNode.classList.remove('up'); scoreBoard.textContent = score; }
function startGame() { scoreBoard.textContent = 0; timeUp = false; score = 0; peep(); setTimeout(() => timeUp = true, 10000) } </script>
|
就大功告成啦!
JS - final
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
| <script> const holes = document.querySelectorAll('.hole'); const scoreBoard = document.querySelector('.score'); const moles = document.querySelectorAll('.mole');
function randomTime(min, max) { let time = Math.floor(Math.random() * (max - min) + min); return time };
let lastHole;
function randomHole(holes) { const idx = Math.floor(Math.random() * holes.length); const hole = holes[idx]; if (hole === lastHole) { console.log('Ah nah thats the same one bud'); return randomHole(holes); } lastHole = hole; return hole; }
function peep() { const time = randomTime(200, 1000); const hole = randomHole(holes); hole.classList.add('up'); setTimeout(() => { hole.classList.remove('up'); if (!timeUp) peep(); }, time); }
moles.forEach(mole => mole.addEventListener('click', bonk));
function bonk(e) { if(!e.isTrusted) return; score++; this.parentNode.classList.remove('up'); scoreBoard.textContent = score; }
function startGame() { scoreBoard.textContent = 0; timeUp = false; score = 0; peep(); setTimeout(() => timeUp = true, 10000) } </script>
|
本刊同步於個人網站:http://chestertang.site/
本次範例程式碼原作者來源:https://tinyurl.com/yavm5f5n