DEV Community

Nikita Galadiy
Nikita Galadiy

Posted on

Render UI for Phaser via React

Creating a game interface using pure Phaser can be challenging, as working with UI through a canvas can be extremely inconvenient, especially when it comes to responsive design.

One great option for rendering the interface is using React. This not only simplifies the creation of the UI but also allows for flexible handling of components, state updates, and responsiveness. Integrating React with Phaser is not particularly difficult, and in this article, we will explore how to do it.


Step 1 - Installing the necessary libraries

First, we need to install React and the required library for integration with Phaser:

  • Install React:
npm install react react-dom
Enter fullscreen mode Exit fullscreen mode
  • Install the additional library phaser-react-ui, which will allow us to connect Phaser and React:
npm install phaser-react-ui
Enter fullscreen mode Exit fullscreen mode

Step 2 - Creating the interface Component

Now, let's create the main scene component that will later render the game's interface elements.

import React from 'react';

const SceneUI: React.FC = () => {
  return (
    <div>
      {/* TODO */}
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

Step 3 - Integration with Phaser

To display our component on the Phaser scene, we need to use the Interface object from phaser-react-ui. In the scene's create method, we will create an instance of this interface and render our SceneUI component.

import Phaser from 'phaser';
import { Interface } from 'phaser-react-ui';
import { SceneUI } from './ui';

class MyScene extends Phaser.Scene {
  private ui: Interface;

  create() {
    this.ui = new Interface(this);
    this.ui.render(SceneUI, {
       // Component props values
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

It's not necessary to remove the interface when the scene is destroyed, as this happens automatically.


Step 4 - Displaying data from the scene

To display data stored in the scene, we can use useCurrentScene or useScene hook to access the scene itself, and useSceneUpdate hook to synchronize data between the scene and the React component.

import React, { useState } from 'react';
import { useCurrentScene, useSceneUpdate } from 'phaser-react-ui';

const SceneUI: React.FC = () => {
  const scene = useCurrentScene();
  const [value, setValue] = useState('');

  useSceneUpdate(scene, () => {
    setValue(scene.someField);
  }, []);

  return (
    <div>
      Synced value from scene: {value}
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

We can also use a custom scene event to update the value by useEvent hook.

useEvent(scene.customEmitter, 'updateSomeValue', (newValue) => {
  setValue(newValue);
}, []);
Enter fullscreen mode Exit fullscreen mode
class MyScene extends Phaser.Scene {
  // ...

  public customEmitter = new Phaser.Events.EventEmitter();

  updateSomeValue(newValue) {
    this.customEmitter.emit('updateSomeValue', newValue);
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 5 - Adapting UI to the canvas size

To ensure that the UI elements scale correctly relative to the canvas size, you should use RelativeScale component

import React from 'react';
import { RelativeScale } from 'phaser-react-ui';

const SceneUI: React.FC = () => {
  // ...

  return (
    <RelativeScale
      target={1280} // Target canvas size, when scale will be 1.0
      min={0.5} // Minimal ui scale
      max={1.5} // Maximal ui scale
      round={true} // Flag to round of ui scale
    >
      {/* ... */}
    </RelativeScale>
  );
};
Enter fullscreen mode Exit fullscreen mode

Step 6 - Displaying UI elements relative to the camera

If you need to render an element relative to world coordinates (for example, a character's health bar), you should use RelativePosition component.

import React from 'react';
import { RelativePosition } from 'phaser-react-ui';

const SceneUI: React.FC = () => {
  // ...

  return (
    <RelativePosition
      x={100} // World X coordinate
      y={400} // World Y coordinate
    >
      {/* ... */}
    </RelativePosition>
  );
};
Enter fullscreen mode Exit fullscreen mode

By integrating React with Phaser, we can easily create and manage responsive game interfaces. The combination of React's component-based approach with Phaser's powerful game engine gives us the flexibility to build dynamic, interactive UIs that are perfectly synced with the game world.

You can find the source code and documentation for phaser-react-ui library here

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs