今日任務: 打地鼠
將洞class加上'up'時,地鼠就會出現
.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;
}
Math.random()
: 會回傳一個偽隨機小數 (pseudo-random) 介於 0 到 1 之間(包含 0,不包含 1)。
const holes = document.querySelectorAll('.hole');
const moles = document.querySelectorAll('.mole');
const score = document.querySelector('.score');
function randomTime(min, max) {
return Math.round((max - min) * Math.random() + min);
}
設定lastIdx
是因為不想要地鼠連續兩次都出現在同一個洞。
1.const index = Math.round(Math.random() * (holes.length - 1))
帶入6個洞的話=Math.round(0~4.999)
機率為:
0~0.49=>0號洞
0.5~1.4=>1號洞
...
3.5~4.4=>4號洞
4.5~4.9=>5號洞=> 0號洞和5號洞機率會比較小
2.const index = Math.floor(Math.random() * (holes.length));
帶入6個洞的話=Math.floor(0~5.999)
機率為
0~0.9=>0號洞
1~1.9=>1號洞
...
4~4.9=>4號洞
5~5.9=>5號洞=> 機率一樣
let lastIdx;
function randomHole(holes) {
const index = Math.floor(Math.random() * (holes.length));
if (lastIdx == index) {
console.log('重複了');
return randomHole(holes);
}
const hole = holes[index];
lastIdx = index;
console.log(index);
return hole;
}
function peep() {
const time = randomTime(200, 800);
const hole = randomHole(holes);
hole.classList.add('up');
setTimeout(() => {
hole.classList.remove('up');
}, time);
}
function peep() {
const time = randomTime(200, 800);
const hole = randomHole(holes);
hole.classList.add('up');
setTimeout(() => {
hole.classList.remove('up');
peep();
}, time);
}
let timeUp = false;
function peep() {
const time = randomTime(200, 800);
const hole = randomHole(holes);
hole.classList.add('up');
setTimeout(() => {
hole.classList.remove('up');
if (!timeUp) {
peep();
}
}, time);
}
HTML按鈕已經綁定startGame(),遊戲時間限制10秒內。
HTML:
<button onClick="startGame()">Start!</button>
JS:
function startGame() {
scoreBoard.textContent = 0; //將畫面分數歸零
timeUp = false;
peep();
setTimeout(() => (timeUp = true), 10000);
}
let score = 0; //設定分數
function startGame() {
scoreBoard.textContent = 0;
score = 0; //遊戲開始分數歸零
timeUp = false;
peep();
setTimeout(() => (timeUp = true), 10000);
}
Event.isTrusted
: 若事件物件是由使用者操作而產生,則 isTrusted 值為 true。parentNode
: 返回元素或節點的父節點。
因為class='up' 是加在hole上面,所以使用parentNode
來找到mole的父層(hole),並移除class='up'。
function hit(e) {
if (!e.isTrusted) return;
score++;
this.parentNode.classList.remove('up');
scoreBoard.textContent = score;
}
測試時發現連點會連續加分,使用setTimeout來避免玩家快速連點
let canClick = true; //可以點擊加分
function hit(e) {
if (!e.isTrusted) return;
if (canClick) {
canClick = false;
score++;
}
setTimeout(() => {
canClick = true;
}, 100);
this.parentNode.classList.remove('up');
scoreBoard.textContent = score;
}
另外再加上倒數計時功能和遊戲介面,讓遊戲比較完整一些
function startGame() {
scoreBoard.textContent = 0;
score = 0;
timeUp = false;
modal.style.display = 'none'; //關閉modal
peep();
timer(10);
}
function timer(seconds) {
clearInterval(countDown);
displayTime(seconds);
const now = Date.now();
const then = Date.now() + seconds * 1000;
countDown = setInterval(() => {
let secondsLeft = Math.round((then - Date.now()) / 1000);
if (secondsLeft <= 0) {
displayTime(secondsLeft);
timeUp = true; //時間到
modalText(); //遊戲結束介面文字
modal.style.display = 'block'; //開啟modal
clearInterval(countDown);
return;
}
displayTime(secondsLeft);
}, 1000);
}
timeBoard.addEventListener('transitionend', function () {
timeBoard.classList.remove('warn'); //可以製造縮放效果
});
function displayTime(seconds) {
timeBoard.style.color = 'black';
if (seconds > 0 && seconds <= 3) {
timeBoard.style.color = 'red'; //倒數三秒提醒玩家
timeBoard.classList.add('warn');
}
return (timeBoard.textContent = seconds);
}
function modalText() {
modal.innerHTML = `
<div class="modal-content">
<h1>遊戲結束!</h1>
<h2>成績:${score}</h2>
<button onClick="startGame()">再來一次</button>
</div>`;
}
避免版面太長詳請可以看我的git,還有很多功能可以增加,例如利用Day15的LocalStorage來存最高分,按下開始後倒數3秒再開始,打到地鼠後的特效等等,就留給大家自由發揮吧。
今日學習到的:
Math.random()
: 會回傳一個偽隨機小數 (pseudo-random) 介於 0 到 1 之間(包含 0,不包含 1)Event.isTrusted
: 若事件物件是由使用者操作而產生,則 isTrusted 值為 true。parentNode
: 返回元素或節點的父節點。效果連結:連結
參考連結:
MDN: Math.random()
MDN: Event.isTrusted
JS30
這30天的作品和git可以從這裡看到:Kate's JS30 自學筆記
在開賽之前,覺得要寫技術文章很難,別人會不會覺得我怎麼寫這麼簡單的東西,所以遲遲不敢開始,在截止日前抱著忐忑的心情按下參加,完全不確定能不能成功寫完30天,甚至是抱著「阿不然看看我能堅持幾天好了?」的心情參加的XD。經過這次鐵人賽,發現按下"發表文章"的瞬間超開心的,再看到觀看次數慢慢的增加,瞬間成就感爆棚。
以前筆記都是寫在自己的雲端上面自己享受(?),不需要考慮別人看不看得懂,或是在查資料的過程中,有些點沒有很了解但只是貼個網址想著以後再研究,大概理解後就往下一個前進,但在鐵人賽過程中,會想辦法畫示意圖,或是試著用口語化的方式描述,希望看我文章的人可以快速理解,花的時間比實際寫程式的時間還多,寫完之後對這些技術又有更深一層的認識,突然可以理解為什麼愛因斯坦說:「If you can’t explain it simply, you don’t understand it well enough.」透過整理和寫作,把這些知識點在腦中重新排列整理了一遍,我想受益最多的是我自己。
看到第30天時影片作者影片說:「I won't see you tomorrow.」,竟然有一種捨不得的感覺,雖然很累,但是很滿足。
我想,可以的話,之後還想繼續發文,謝謝看到這邊的你!