React+Reduxで脱出ゲームを作る

服部平次の部屋からの脱出ゲーム作りたい。今までの原作と映画でのトリックをうまく組み合わせて何かできひんかなって考えてる。それと、ちょうどReactをやってみたいと思ってたので、Reactで脱出ゲームがちゃんと作れるのか確かめるために小さいのを作ってみた。

GitHub Pagesで公開してる。

https://shio-yaamaa.github.io/react-escape-room/

ソース: https://github.com/shio-yaamaa/react-escape-room

作った感想とか、作り替えるときにどこを変更したらいいかとかメモしておく。

ゲームの中身

中学生の時くらいにNeutralのMyaさんに激しく憧れてて(今ももちろん憧れてるけど)、何でもいいから一個脱出ゲーム作りたい!ってなってシナリオ考えたんだった気がする。見返してみると、物理法則めっちゃ無視してるしアイテムの鍵率高すぎだし酷いけど、なんか頑張って考えたのは覚えている。当時は吉里吉里のKAGで作ろうとしたけど、書き方が悪かったのか超遅くなったので、諦めてしまったんだった。部屋とかアイテムはそのときにモデリング&レンダリングしたので、その画像は今回そのまま使えた。

Componentの構成

<Provider>
    <App>
        <ScreenSwitch container> manages which screen to display and calls AssetsLoader
            <StartScreen>
            <EndScreen>
            <LoadScreen>
            <div> shows fade effect when switching between screens

            <Game container> manages functions related to the whole game, like save, hint, and cursor
                <div> aligns MainScreen and Sidebar horizontally
                    <MainScreen container> handles click events on MainViewMap, ArrowArea, and ItemDetailWindow
                        <MainView> displays background images
                        <MainViewOverlay> additional images on the MainView like dial numbers
                        <MainViewMap> clickable map
                        <ArrowArea> (x4) fire events when they (not their children!) are clicked
                        <ItemDetailWindow> zoomed view of items
                            <ItemDetailView> displays item images
                            <ItemDetailViewMap> clickable map
                        <Sidebar>
                            <ItemFrameContainer container>
                                <ItemFrame> (x10)
                            <div> aligns SaveButton and HintButton horizontally
                                <SaveButton>
                                <HintButton>
                <Hint>
                <div> // shows fade effect when save button is clicked

どれをcontainerにするかの判断についてはあんまり自信がない。

ゲームごとに書き換えるところ

なるべく後で使えるように作ったつもりなので、他の脱出ゲームを作るときは下記を変更したらたぶん動く。

Assets

assets/images/

  • items: アイテム欄でのアイテムの画像

  • itemDetails: アイテム詳細ウィンドウでのアイテムの画像

  • itemDetailMaps: アイテム詳細ウィンドウのクリッカブルマップ

  • mainViews: 部屋の画像

  • mainViewOverlays: 部屋の画像の上に載せるやつ

  • mainViewMaps: 部屋の画像のクリッカブルマップ

  • endScreenBackground: ゲームクリア画面

assets/sounds/: 全般的に

Program

redux/modules/

  • items: ゲーム内のアイテム

  • itemStatus: アイテム詳細ウィンドウ内でのアイテムの状態

  • status: 部屋の状態

scenario/: stateから背景画像を選択したり、クリック場所から動作を決めたりするスクリプトが入ってるので、全部変える。

Reactを使ってよかったこと

JSXが好き。(けどたまにスタイルをJSXかCSSファイルどっちに書こうかめっちゃ迷う。pseudo classとかはCSSでしかできないみたいだから)

「これがあれやったらそれ表示して」って書いとくだけで初期化も再描画も勝手にやってくれるん嬉しい。

初めCanvasとどうやって折り合いをつけるかわからんくて戸惑ったけど、Componentのライフサイクルに合わせてちゃんと書いたらそこまで大変でもなかった。

アイテム欄みたいな同じコンポーネントいっぱい並べる所がすごい楽。

Reactを使って苦労したところ

  • Assetsを事前に全部requireしておく

    たぶん私がWebpackとかの技術に慣れてなさすぎるんだと思うけど、なんか難しかった。結局このページのmih-kopylovさんの最後のコメントを参考にしたらできた。

  • フェード

    普通は、actionをdispatchしたらstateが更新されて、即座に画面が更新される。だから、「画面を黒くフェードしていって、一番フェードが濃い状態の時に画面を切り替えて、それからフェードを徐々に消していく」みたいなやつはちょっとめんどくさかった。何かいい方法あるんかな。

Reduxを使ってよかったこと

データの矛盾が起きない感じがめっちゃいいし、一方的に決まった方法でしか状態を変更できないのもありがたい。

save/load機能を作るのがめちゃくちゃ簡単だった。saveはstateをlocalStorageにそのままばーんって入れて、loadではそれをまるごと取ってくればいいだけ。


服部の脱出ゲームにもほぼそのまま使えると思うんだけど、まだ部屋のモデリングとか全く進んでないからいつになるかわからなすぎる。

今のところはこんなん。

f:id:YaaMaa:20180609222004p:plain

実際作ってみると、紫だと思ってたベッドが実は彩度の低い赤だったとわかったり、ポスターのバイクの種類を特定できるようになってきたりと、服部の部屋についての学びが多い。