I’m using Ionic, React, and Capacitor to make something with Phaser - it all works perfectly in the browser on desktop, but when I try to run the Android project with an emulator - Ionic and React load just fine, but the Phaser canvas is just a thin black (The background color for the canvas) bar, about 20px tall, with the Phaser logo bouncing up and down (The default scene).
However! When I use Scale: { mode: Phaser.Scale.WIDTH_CONTROLS_HEIGHT }
, the Phaser canvas fits the screen! …Well, and then some. It fits the width properly as far as I can tell, but the canvas goes well off the screen on the bottom, so the Phaser logo bounces off the screen briefly then returns when viewing the default scene.
React game component:
import React, { useState, useRef, useEffect } from 'react';
import {
IonContent, IonFab, IonFabButton,
IonHeader,
IonMenuButton,
IonPage,
IonTitle,
IonToolbar,
} from '@ionic/react';
import { IonPhaser } from '@ion-phaser/react';
import playGame from '../phaser/scene';
const DEFAULT_HEIGHT = window.innerHeight;
const DEFAULT_WIDTH = window.innerWidth;
const gameContentWrapper = {
width: '100%',
height: '100%',
margin: 'auto',
padding: 0,
overflow: 'hidden',
};
const gameCanvas = {
width: '100%',
height: '100%',
margin: 'auto',
imageRendering: 'pixelated',
};
const gameConfig = {
type: Phaser.AUTO,
width: DEFAULT_WIDTH,
height: DEFAULT_HEIGHT,
orientation: Phaser.Scale.LANDSCAPE,
autoRound: true,
autoFocus: true,
// disableContextMenu: true,
render: {
pixelArt: true,
},
scale: {
autoCenter: Phaser.Scale.CENTER_BOTH,
mode: Phaser.Scale.RESIZE,
// mode: Phaser.Scale.WIDTH_CONTROLS_HEIGHT,
},
backgroundColor: '#000',
scene: playGame,
};
function Game() {
const gameRef = useRef(null);
const [initialize, setInitialize] = useState(false);
const destroy = () => {
if (gameRef.current) {
gameRef.current.game.destroy();
}
setInitialize(false);
};
function resize() {
console.log(gameRef.current);
if (!gameRef.current) {
return;
}
const {game} = gameRef.current;
const canvas = gameRef.current.children[0];
game.width = window.innerWidth;
canvas.style.width = window.innerWidth;
game.height = window.innerHeight;
canvas.style.height = window.innerHeight;
}
// Called when the DOM is finished loading
useEffect(() => {
setInitialize(true);
window.addEventListener('resize', resize);
window.addEventListener('load', resize);
return () => {
destroy();
};
}, []);
return (
<IonPage>
<IonFab vertical="top" horizontal="start" slot="fixed">
<IonFabButton>
<IonMenuButton auto-hide="false" menu="mainMenu" mode="md" />
</IonFabButton>
</IonFab>
<IonContent fullscreen>
<div style={gameContentWrapper}>
<IonPhaser ref={gameRef} game={gameConfig} initialize={initialize} style={gameCanvas} />
</div>
</IonContent>
</IonPage>
);
}
export default Game;
scene.js
import Phaser from 'phaser';
import logoImg from '../assets/logo.png';
class playGame extends Phaser.Scene {
constructor() {
super('PlayGame');
}
preload() {
this.load.image('logo', logoImg);
}
create() {
const logo = this.add.image(400, 150, 'logo');
this.tweens.add({
targets: logo,
y: 450,
duration: 2000,
ease: 'Power2',
yoyo: true,
loop: -1,
});
}
}
export default playGame;
I’m just using the basic Ionic menu + React starter template, with the following route added:
<Route path="/game" exact>
<Game />
</Route>
Is there any way to get Phaser.Scale.RESIZE to work properly on Android? WIDTH_CONTROLS_HEIGHT seems problematic and I’d really just like the canvas to fill the screen width and height regardless of aspect ratio.
I’m using the latest versions of Ionic, Capacitor, and Phaser.
If you’re curious what IonPhaser is, check here - I updated it to work with the latest version of React, but other than that it’s exactly the same. It’s just a simple wrapper to make Phaser more React friendly.
The gameRef is a reference to the IonPhaser container, which has the game object and the canvas (children[0]) in an object - everything else is exactly the same as normal Phaser.
edit: The same issue occasionally appears when the devtools are open in Firefox Desktop, but go away when the devtools are closed or the screen is resized