昨天 Day17 我們已經讓食物可以隨機產生,食物還會炫砲的發光,蛇也可以順利吃到食物,而且吃到之後身體會變長,速度會變快。
但是讓蛇這樣一直吃下去,一直變長下去就會沒完沒了,然後在我們這次的遊戲當中,蛇是設定可以穿牆的,也就是碰到牆壁不會死,那唯一會死的辦法,就是自食惡果,也就是吃到自己的身體,遊戲結束。
在 Day17 當中,我們知道,當頭的位置與食物的位置重疊的時候,就判定為吃到食物。同樣的道理,當頭的位置跟身體任何一個位置重疊的時候,就表示蛇吃到自己的身體,遊戲終止。
containers/SnakeGame/reducer.js
const eatSelf = snakeBody.find((body) => (
body.get('x') === updatedPositionX && body.get('y') === updatedPositionY
));
這裏我們用到 find()
這個方法,這個方法可幫助我們檢查蛇的身體中的每一個元素,其元素的位置是不是跟頭的位置相等,如果相等的話,就會返回那個元素,否則返回 undefined。
The find() method returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.
判斷蛇是不是吃到自己其實蠻容易的,但是吃到自己之後,我們還有一些事情要做。
首先,記得我們蛇是怎麼移動的嗎?我們是透過 setInterval() 這個方法,不斷的在間隔時間調用裡面的函數,也就是我們讓蛇前進的函數,所以蛇才會一直不斷的前進,但是當我們的蛇吃到自己的身體,遊戲結束的時候,以目前的機制,這個 setInterval() 所調用的方法還是會不斷地執行。所以這邊我們需要有一個判斷依據,讓我們知道遊戲已經結束了, setInterval() 你也可以休息了,不用再一直消耗電腦的資源了。
另外,當遊戲結束之後,如果要再次挑戰,再玩一局要怎辦呢?如果每次遊戲結束,要重新開始的話需要再重新整理網頁,一定會感到非常的麻煩,所以我們需要實作遊戲重新開始的功能。
為了滿足上面兩個願望,我們這邊再多設計一個參數,我命名為 isGameStart ,這是一個布林值,如果為 true ,表示遊戲仍然正在進行中,假設我們未來要實作暫停功能,雖然遊戲暫停,但是遊戲仍然在進行中,我們也需要透過這個參數來判斷。因此為了要幫助我們判斷遊戲是不是仍然在進行?是不是應該要把 setInterval() 清理掉了?還有我們的蛇吃到自己讓遊戲結束了,是不是要重新開始遊戲了?我們來加入 isGameStart 這個值。
所以當蛇吃到自己的時候,我們會把 isGameStart 設為 false ,當遊戲初始化,或是由戲重新開始的時候,我們會把 isGameStart 設為 true。今天我們先把這個參數準備好,明天我們要開始實作相關的功能。
const eatSelf = snakeBody.find((body) => (
body.get('x') === updatedPositionX && body.get('y') === updatedPositionY
));
if (eatSelf) {
return state.set('isGameStart', false);
}
明天我們會來實作重新開始
的按鈕,今天我們先展示一下蛇吃到自己導致遊戲結束的功能。