iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 27
1
Modern Web

以經典小遊戲為主題之ReactJS應用練習系列 第 27

Day27 - 記憶方塊篇:開始遊戲

禁止自動播放

開始遊戲的時候有一個開始按鈕,一方面可以提示玩家遊戲開始,讓玩家做好準備再開始遊戲。另一方面,由於我們遊戲的一開始就需要播放音樂,但是在2018年4月份發佈的 Chrome 66 宣布正式關掉了聲音自動播放,也就是説

<audio autopaly></audio>
<video autoplay></video> 

在桌面版瀏覽器也會失效(原本是因為考慮到手機的頻寬及電池消耗所以在手機上禁止自動播放,但現在電腦桌面瀏覽器也將無法自動播放)。

Chrome 66禁止聲音自動播放
Google Chrome’s next update will finally block autoplay videos that have sound
Autoplay Policy Changes

所以如果在使用者沒有任何操作下就播放音樂,瀏覽器就會噴錯

DOMException: play() failed because the user didn't interact with the document

為此,我們真的需要一個開始的按鈕。

開始按鈕

Day19 的貪吃蛇一樣的做法,我會先用一個透明的 div tag 當作 wrapper 來把畫面蓋住,然後裡面的開始按鈕再來對這個 wrapper 做定位。
src/containers/MemoryBlocks/index.js

<div className="memory-blocks__panel">
    <button
        className="memory-blocks__start-btn"
        onClick={this.handleOnGameStart}
    >
        Start
    </button>
</div>

由於包住 memory-blocks__panel 這個 div tag 的外容器 memory-blocks__blocks-wrapper 我已經把它設為 position: relative; ,所以我在 memory-blocks__panel 這個 div tag 設為 position: absolute; 的時候,就會讓內元件對外容器做定位
src/containers/MemoryBlocks/Styled.js

.memory-blocks__panel {
    position: absolute;
    width: 100%;
    height: 100%;

    display: flex;
    justify-content: center;
    align-items: center;
}

接著,裡面的按鈕我要對他做一些裝飾
src/containers/MemoryBlocks/Styled.js

.memory-blocks__start-btn {
    ${buttonMixin()}
    width: 150px;
    height: 60px;
    font-size: 2em;
}

我把按鈕主要的樣式寫在 mixin 裡面,理由是因為之後在這個遊戲裡面所有的按鈕,我希望樣式可以統一,所以把調整樣式的地方抽出來,以後就可以重複使用
src/containers/MemoryBlocks/Styled.js

const buttonMixin = () => `
    width: 100px;
    height: 40px;
    background: #000000b3;
    border: 2px solid white;
    color: white;
    border-radius: 40px;
    font-size: 1em;
    font-weight: 700;
    letter-spacing: 1px;
    cursor: pointer;
    outline: none;
    transition: all 0.8s;
    &:hover {
        color: black;
        background: white;
        opacity: 1;
    }
`;

這個按鈕的幾個特色,一個是他是外型圓圓的,像膠囊一樣的按鈕,然後在還沒動作的狀態下,背景是半透明的,background: #000000b3; ,主要也是為了要配合這次記憶的主題,有點神秘感,所以半透明的按鈕可以稍微看到被蓋住的方塊以及他的光暈,有種若隱若現的感覺。但是在 hover 之後,為了不要太突兀,配合光暈的柔和感,按鈕會有漸進式的變色,所以這邊漸進的動畫用 transition: all 0.8s; 來處理,然後 hover 的時候,背景和文字的顏色會互換,黑的變白的,白的變黑的,然後背景就不再是透明了,因為 hover 的時候,重點就會聚焦在按鈕上,所以按鈕是主體,就不需要讓後面的背景來干擾我們的按鈕。

start-button

按下按鈕後之事件

按下按鈕之後,很重要的一件事情就是我們需要把 isGameStart 這個參數從初始的 false 改成 true ,如此一來我們可以來區分遊戲開始或遊戲尚未開始,或遊戲結束。
所以在處理 onclick 的函數當中,我們要發一個 action 到 reducer
src/containers/MemoryBlocks/index.js

handleOnGameStart = () => {
    const {
        handleSetInit,
    } = this.props;
    handleSetInit();
}

src/containers/MemoryBlocks/reducer.js

case SET_INIT: {
    return state.set('isGameStart', true);
}

所以,當 isGameStart 被轉成 true 之後,表示遊戲開始,畫面上的重新開始按鈕就要消失
src/containers/MemoryBlocks/index.js

{
    !isGameStart &&
    <div className="memory-blocks__panel">
        <button
            className="memory-blocks__start-btn"
            onClick={this.handleOnGameStart}
        >
            Start
        </button>
    </div>
}

今日成果展示

下面就是我們今日的成果,明天我們會繼續來處理按下按鈕之後,音樂的播放以及方塊的閃爍
game-start-button

參考程式碼 & 遊戲展示

Memory Blocks - Github


上一篇
Day26 - 記憶方塊篇:按下去有聲音之事件處理
下一篇
Day28 - 記憶方塊篇:音樂播放及對錯判斷
系列文
以經典小遊戲為主題之ReactJS應用練習30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言