これを読み返しながら、ふと「今だったら、ReactでWeb版を作っておけばネイティブアプリ化も結構簡単に出来るし色々と応用が効くのでは?」と思い付きました。
そこで、作り始めて見ました。
現時点で動作しているものはこちらで試せます。
https://reversi-d1kqojbar.now.sh/
ソースコードはこちら:
https://github.com/mikehibm/reversi-react/tree/blog-1
まだ画面をクリックして石を置くことが出来るようになっただけでゲームのルールが何も実装されていません。
しかし、リバーシゲーム作りは楽しいですね!
以下、ここまでに書いたコードの大まかな説明です。
今のところ下のような階層になっています。
アプリケーションの状態は store.ts ファイルで一括管理しています。
ここでエクスポートしている Store クラスが EventEmitter を継承しており、状態に変更があったときにイベントを発生(emit)することでそれを各コンポーネントに通知して、各コンポーネントが画面を更新するという流れになっています。
例えば、メニュー画面でスタートボタンが押されたときには、setPage()メソッドが呼ばれて Store クラス内で保持している page 変数の値が変更されるので、その際に 'page_changed' というイベントを発生させています。
このイベントは App コンポーネントが監視していて、イベント発生時に最新の page の値を受け取って メニュー画面を表示するのかゲーム画面を表示するのかを切り替えています。
Boardコンポーネントでは、SVGを使ってボードの緑色の背景や縦と横の罫線などを描画しています。
また重要なのは、Cellコンポーネントの配列を作成してそれを子コンポーネントとして描画していることです。ボード上には 8 x 8 で64個のCellコンポーネントが配置されることになります。
Cellコンポーネントでは、propsとして渡された座標値にしたがってSVGのRectangleを描画します。このRectangleがマウスのクリックイベントを受け取る入り口になります。
また、propsのひとつとしてcolorが渡されますが、これはそのセルが空白なのか、黒の石が配置されているのか、または白の石が配置されているのか、を示します。
Cellコンポーネントではその値によって黒または白の円を描画する処理を行っています。
あるセル上でマウスがクリックされた時は、次の流れで最終的にセルに石が描画されるようになっています。
こんな感じで、ひとまずボードの描画と石の配置までは出来るようになりました。
次回は、リバーシゲームとしてのルールを実装して実際に遊べるようになるまでを作ってみたいと思います!
React/TypeScriptでリバーシゲームを作る
(1) - ボードの描画と石の配置
https://blog.makotoishida.com/2018/10/reacttypescript.html
(2) - ゲームロジック
https://blog.makotoishida.com/2018/11/reacttypescript-2.html
(3) - 思考ルーチンその1
https://blog.makotoishida.com/2019/01/reacttypescript-3-1.html
(4) - 思考ルーチンその2
https://blog.makotoishida.com/2019/03/reacttypescript-3-2.html
(5) - アニメーション
https://blog.makotoishida.com/2019/03/reacttypescript-5.html
タイトル画面 |
ゲーム画面 |
ソースコードはこちら:
https://github.com/mikehibm/reversi-react/tree/blog-1
まだ画面をクリックして石を置くことが出来るようになっただけでゲームのルールが何も実装されていません。
しかし、リバーシゲーム作りは楽しいですね!
以下、ここまでに書いたコードの大まかな説明です。
コンポーネント階層
今のところ下のような階層になっています。
- App (アプリケーションの大枠)
- Menu (メニュー画面)
- Game (ゲーム画面)
- Board (ボードの背景や枠線などを描画するコンポーネント)
- Cell (一つのセルを描画するコンポーネント)
状態管理
アプリケーションの状態は store.ts ファイルで一括管理しています。
ここでエクスポートしている Store クラスが EventEmitter を継承しており、状態に変更があったときにイベントを発生(emit)することでそれを各コンポーネントに通知して、各コンポーネントが画面を更新するという流れになっています。
例えば、メニュー画面でスタートボタンが押されたときには、setPage()メソッドが呼ばれて Store クラス内で保持している page 変数の値が変更されるので、その際に 'page_changed' というイベントを発生させています。
このイベントは App コンポーネントが監視していて、イベント発生時に最新の page の値を受け取って メニュー画面を表示するのかゲーム画面を表示するのかを切り替えています。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class App extends React.Component<Props, State> { | |
state = { page: 'menu' }; | |
onChangeStore = () => { | |
const { page } = store.getState(); | |
this.setState({ page }); | |
}; | |
componentDidMount() { | |
store.on('page_changed', this.onChangeStore); | |
} | |
componentWillUnmount() { | |
store.off('page_changed', this.onChangeStore); | |
} | |
public render() { | |
const { page } = this.state; | |
return ( | |
<div className="App"> | |
<header className="App-header"> | |
<h1 className="App-title">Reversi</h1> | |
</header> | |
{page === 'menu' ? <Menu /> : <Game />} | |
</div> | |
); | |
} | |
} |
ボードとセルの描画
Boardコンポーネントでは、SVGを使ってボードの緑色の背景や縦と横の罫線などを描画しています。
また重要なのは、Cellコンポーネントの配列を作成してそれを子コンポーネントとして描画していることです。ボード上には 8 x 8 で64個のCellコンポーネントが配置されることになります。
Cellコンポーネントでは、propsとして渡された座標値にしたがってSVGのRectangleを描画します。このRectangleがマウスのクリックイベントを受け取る入り口になります。
また、propsのひとつとしてcolorが渡されますが、これはそのセルが空白なのか、黒の石が配置されているのか、または白の石が配置されているのか、を示します。
Cellコンポーネントではその値によって黒または白の円を描画する処理を行っています。
あるセル上でマウスがクリックされた時は、次の流れで最終的にセルに石が描画されるようになっています。
- handleClick()メソッドが呼ばれる。
- Storeクラスの setStone()メソッドが呼ばれる。
- クリックされた場所に石が無ければ、その場所の colorプロパティを現在の手番の色に変更する。
- Storeクラスが'board_changed'イベントを発生する。
- Boardコンポーネントがイベントを受け取り、ボード全体を再描画する。
- クリックされた場所に対応するCellコンポーネントが石を描画する。
こんな感じで、ひとまずボードの描画と石の配置までは出来るようになりました。
次回は、リバーシゲームとしてのルールを実装して実際に遊べるようになるまでを作ってみたいと思います!
React/TypeScriptでリバーシゲームを作る
(1) - ボードの描画と石の配置
https://blog.makotoishida.com/2018/10/reacttypescript.html
(2) - ゲームロジック
https://blog.makotoishida.com/2018/11/reacttypescript-2.html
https://blog.makotoishida.com/2019/01/reacttypescript-3-1.html
(4) - 思考ルーチンその2
https://blog.makotoishida.com/2019/03/reacttypescript-3-2.html
(5) - アニメーション
https://blog.makotoishida.com/2019/03/reacttypescript-5.html