Game Size

Since Replay can deploy to multiple platforms, you likely want your game to work at various dimensions, sizes and orientations. Replay has a few tools to make this easier for you.

Game Coordinates#

Your game must have a fixed width and height. This is unitless, not in pixels! You can choose any values you like. When you set the position of a sprite, you are setting it relative to your width and height. The origin (0,0) is in the center of the screen, and the y axis is positive upwards.

origin diagram

Safe Zone#

Your game can also set a margin beyond the fixed width and height to avoid black bars on resolutions that don't match your game's dimensions. Inside the margins is the safe zone where you should render the important visuals in the game. In the margins you can put non-essential visuals like wider backgrounds. Alternatively, you can calculate the total width and height of the device in your render method and position responsively.

safe zone diagram


Sprites have multiple render methods to deal with different orientations and resolutions, as mentioned in Sprites. Only one render method will be chosen based on your settings. You don't need to set them for every Sprite, if they're not present Replay will default to using just render.

size Game Prop#

Your Top-Level Game Sprite accepts a size prop:

id: "Game",
size: {
width: 500,
height: 300,
minWidthXL: 1000,
minHeightXL: 500,
maxWidthMargin: 100,
maxHeightMargin: 100,

size takes the following fields:

  • width: The width of your game, defines the x game coordinates.
  • height: The height of your game, defines the y game coordinates.
  • minWidthXL: (Optional) Set this if you want to use the renderXL methods when the device's width is beyond this value in pixels.
  • minHeightXL: (Optional) Set this if you want to use the renderXL methods when the device's height is beyond this value in pixels.
  • maxWidthMargin: (Optional) Set to allow a margin on the left and right of game in game coordinates (up to this value).
  • maxHeightMargin: (Optional) Set to allow a margin on the top and bottom of game in game coordinates (up to this value).

The example above is for a landscape-only game. If you want portrait-only simply set a height greater than the width.

If you want to support both landscape and portrait, size can accept an object with portrait and landscape fields like below. The orientation is chosen by Replay automatically.

id: "Game",
size: {
portrait: {
width: 300,
height: 500,
landscape: {
width: 500,
height: 300,

If the screen is landscape, Replay will call render and renderXL (if defined). If it's in portrait, Replay will call renderP or renderPXL if they're defined instead.


The size field in the device parameter of the Sprite methods contains properties you can use for layout:

const { size } = device;
// Values passed into game props for current orientation
// The margins of the device
// Will be somewhere between 0 and the max values you set
// The width and height of the device itself in px

Here's how you could render a game's score at the top of the screen on all devices:

render({ props, device }) {
const topY = device.size.height / 2 + device.size.heightMargin;
return [
text: `Score: ${props.score}`,
font: { family: "Courier", size: 16 },
color: "red",
y: topY,
anchorY: 8,