iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 26
1

人除了視覺的記憶以外,也有聽覺的記憶,Day25 我們已經讓方塊有了迷幻的動畫,並且點擊的時候可以發亮,今天我們希望除了發亮之外,點擊的時候也可以發出聲音。

抓到被點擊的方塊

所以第一件事情,我希望點擊的時候可以先抓到被點擊的方塊的 id。跟之前 Tic Tac Toe 井字棋
Day05 和貪吃蛇 Day20 一樣的手法,我分別給每一個方塊資料屬性(data-* attribute),data-id={blockId},把方塊的 id 存在 data-id 這個資料屬性裡面。
src/containers/MemoryBlocks/components/Block/index.js

<div
    id={`block-${blockId}`}
    data-id={blockId}
    className="block__block-item"
    onClick={handleOnClick}
/>

我們把函數 this.handleOnBlockClick 當做 props 傳進來,藉此來取得 data-id 的資料
src/containers/MemoryBlocks/index.js

<Block
    key={block.get('id')}
    blockId={block.get('id')}
    sideLength={sideLength}
    handleOnClick={this.handleOnBlockClick}
/>

如下程式碼,透過 getAttribute 我們可以拿到指定資料屬性(data-* attribute)資料屬性的值,也就是點擊哪個方塊,我們就可以拿到那一個方塊的 id。
src/containers/MemoryBlocks/index.js

const blockId = event.target.getAttribute('data-id');

拿到 id 之後,我們就可以來做兩件事情,一件事是把聲音播出來,另一件事是把答案存起來。

把聲音播出來

首先,我們來播放音樂,在 Day24 的時候,我們已經讓 blocks 這個陣列裡面,每個 block 都擁有它相對應的 Audio Object,我們現在要使用它,只要把它直接拿出來就可以了
src/containers/MemoryBlocks/index.js

const audioObject = blocks.getIn([blockId, 'audio'])();

拿到的這個 audioObject 內容如下:

audioObject = <audio preload="auto" src="https://awiclass.monoame.com/pianosound/set/1.wav"></audio>

這時候我們只要執行 audioObject.play(); 就可以把聲音播放出來了。但是值得一提的是,因為我們不想要每次播放的時候,都一直產生新的物件,這樣有點浪費資源,所以當我們重複播放的時候,會把 currentTime 設為 0。
src/containers/MemoryBlocks/index.js

const blockId = event.target.getAttribute('data-id');
const audioObject = blocks.getIn([blockId, 'audio'])();
audioObject.currentTime = 0;
audioObject.play();

把答案存起來

第二件事情,我們要把答案存起來,這樣我們之後就可以比對玩家回答是否正確。由於我們這邊是使用 React + Redux 的架構,所以我們要做的事情就是把取得的 block id 發一個 action 到 reducer 把它存起來就可以了。

所以在這個 onclick 之後所觸發的函式裡面,要同時播放音樂且把答案存起來,完整代碼如下:
src/containers/MemoryBlocks/index.js

handleOnBlockClick = (event) => {
    const {
        blocks,
        handleUpdateAnswer,
    } = this.props;
    const blockId = event.target.getAttribute('data-id');
    const audioObject = blocks.getIn([blockId, 'audio'])();
    handleUpdateAnswer(parseInt(blockId, 10));
    audioObject.currentTime = 0;
    audioObject.play();
}

在 reducer 裡面,我們的作法如下
src/containers/MemoryBlocks/reducer.js

case UPDATE_ANSWER: {
    const updatedAnswer = state.get('answer').push(action.payload);
    return state.set('answer', updatedAnswer);
}

今日成果展示

以下就是我們今天的成果,由於聲音有點難 demo ,所以這邊先印出來在螢幕上示意
click-blocks

參考程式碼 & 遊戲展示

Memory Blocks - Github


上一篇
Day25 - 記憶方塊篇:幫方塊做出炫炮又迷幻的動畫
下一篇
Day27 - 記憶方塊篇:開始遊戲
系列文
以經典小遊戲為主題之ReactJS應用練習30

尚未有邦友留言

立即登入留言