Sokoban Series: Part 4, Creating an Overlay in React
In this part of our Sokoban Series we will create an overlay for our game. The overlay contains our menu in which the user can select different levels, and a volume control. The end result looks like this:
We tried making a simple menu in Phaser, but we found that Phaser is not suited to do this in a straight-forward manner. It would take us a lot less work in simple HTML, so that’s what we did.
Enter React and material-ui. React is a JS library to create user interfaces. Material-UI provide react components that implemnet Google’s Material Design, and that simply look a lot better than I can design myself. We will not explain React in this post, that could be a whole book on its own. We focus on how you can communicate with your Phaser game from outside of Phaser.
So let’s hook React and Material-UI up to our Phaser game. Phaser itself is also just Javascript. So, we want to create a React app that renders a DOM, and in that DOM will be our Phaser game.
We create a React Component that renders a container for our game, and that creates our game in componentDidMount(). componenDidMount is the earliest point in which we are sure that our game div exists.
let game: Game; exportfunctioncreateGame() { game = new Game(config); }
exportfunctiongetGame(): Game{ return game; }
That’s all we had to do. Of course we must be careful that our GameContainer is always present in our React application, if not it will be unmounted, and our game would get destroyed. To this end, we render the overlay on top of the game. The game will still be available in the DOM, it will just be hidden behind an overlay.
What are the components our overlay and menu needs:
A way to open the menu
A way to select and load a level
A way to control the volume
Let’s start with the volume control. We want to have a component that, when clicked opens a slider. The slider indicates the current volume, and when slidered (yes, that’s a word from now on) it changes the volume of our game. As Phaser is simple JS, we can also call function from “outside” Phaser. By accessing our game we can simple access the sound.volume and modify it:
Next, let’s create a LoadLevel component that renders a thumbnail of each level, and that when clicks loads that level. All of our levels are stored in a JSON that is loaded inside Phaser. We can also access the cache of Phaser from outside. Simply get the intance of your game and call .cache, and you can get all your loaded resources.
The following component renders a grid with LevelTiles. The LevelTile itself simply renders a thumbnail of the level, the name of the level etc. You can export a thumbnail of a map in the Tiled map editor.
We enforce that our overlay is always rendered on a fixed position, and by using a higher z-index than our game it is rendered above our game.
Conclusion
In my opinion Phaser is ill suited to render complex interactive user interfaces. The DOM-tree is made specifically to create such interfaces, so I prefer to use that. In this episode we combined React with Material-UI to render a menu on top of our game. As Phaser is, in the end, simply Javascript interacting with your game from ‘the outside world’ is not that hard.
This completes our game. The only thing left to do is to publish our game. We will show you how to publish your game on CrazyGames in the next episode.