Building Phaser 3 games with Create React App
Phaser 3 is a great framework for building modern web games. It comes with tons of documentation, tutorials and examples that let you learn the basics quickly. One thing I’ve struggled with while using it though is figuring out how to use it in bigger projects. Since most examples are presented simply a as a single file it can be difficult to learn how to properly split your code into modules and organize it. In this article I will describe how to do just that. We will use Create React App to handle the build configuration for us and create a simple component that displays our game. This way we can quickly start using JavaScript modules in our game without having to manually set up webpack and babel. As a bonus we’ll be able to easily add HTML overlay to our game. I will describe how to do it in next articles.
If you just want to see the code you can go straight to the repository.
Create React App
Nothing special is needed here. Just follow instructions for create-react-app and create empty application. This will take care of setting up webpack, babel, jest, development server and everything else.
The only additional thing we have to do is to add Phaser dependency:
npm i phaser
Next, we’ll create our Phaser 3 game.
Create Phaser 3 game configuration
We’ll put our game configuration file in src/game
directory. For now it will just start the engine.
import Phaser from 'phaser';
import Boot from './scenes/Boot';
import Play from './scenes/Play';
const config = {
type: Phaser.AUTO,
scale: {
mode: Phaser.Scale.RESIZE,
parent: 'game',
autoCenter: Phaser.Scale.CENTER_BOTH,
width: '100%',
height: '100%',
},
scene: [Boot, Play ],
transparent: false
};
export default config;
We’ll also crate the Boot and Play scenes in src/game/scenes
directory.
In Boot scene we’ll load a single image to demonstrate how assets are handled:
import Phaser from 'phaser';
class Boot extends Phaser.Scene {
constructor() {
super({key: 'Boot'});
}
preload() {
this.load.image('logo', 'assets/images/logo.png');
}
create() {
this.scene.start('Play');
}
}
export default Boot;
As you can see we are loading logo.png
file from assets/images
directory. We’ll put all game assets in public/
directory created by create-react-app so that they’re automatically available for download. Put the logo.png
file in public/assets/images
directory so that it can be accessed by Boot scene.
Next let’s create Play scene. It will only display the previously loaded image:
import Phaser from 'phaser';
class Play extends Phaser.Scene {
constructor() {
super({key: 'Play' });
}
create() {
this.add.image(100, 100, 'logo').setOrigin(0, 0);
}
}
export default Play;
That’s it. We now have a simple Phaser 3 game structure split into multiple JavaScript modules. In future articles we’ll see how to use JavaScript modules for more complex game objects.
Now let’s see how to include our game in the react app bundle and display it on the screen.
Create game component
We’ll include our game by creating a simple component. Let’s put it in the src/components/Game.js
file.
import React, {useEffect} from 'react';
import Phaser from 'phaser';
import gameConfig from '../game/gameConfig';
const Game = () => {
useEffect(() => {
if (process.env.NODE_ENV !== 'test') {
new Phaser.Game(gameConfig);
}
}, []);
return (
<React.Fragment>
<div id='game' role='game-container' style={{width: '100vw', height: '100vh'}}></div>
</React.Fragment>);
};
export default Game;
As you can see we import our gameConfig.js
file here so that our game is included in the bundle. Our component will take care of creating the game and starting Phaser engine. The content is an empty div where Phaser will insert the game canvas. This was configured by specifying parent: 'game'
parameter in the game gameConfig.js
file.
Since we cannot actually start the game renderer in jest context we’re not creating instance of the game while running tests. We’ll get back to testing later.
Now let’s display our component. We’ll modify src/App.js
file to include it:
import './App.css';
import Game from "./components/Game";
function App() {
return (
<div className="App">
<Game/>
</div>
);
}
export default App;
Run the game
We’re ready to run the game. Since we’re using Create React App everything is set up and all we have to do is type:
npm run start
This will start the development server and serve our game. You should be able to see the logo.
Testing
As I mentioned before we can’t actually initialize the game when running tests but we can still test our React components using jest. To do this we just have to add one extra dependency:
npm i phaser3spectorjs
and modify our App.test.js
file:
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByRole('game-container');
expect(linkElement).toBeInTheDocument();
});
That’s it. You can now create tests for your React components and execute them by running
npm run test
Next steps
Using this simple set up we can easily manage big project by splitting them into multiple JavaScript modules. In future articles I will show you how to extend more complex game objects like sprites and how to integrate our game with HTML overlay built with React.