Talking about Game development, HTML5, iOS, Javascript and Phaser.
When you design an HTML5 game to be played on smartphones, unfortunately you can’t lock the orientation, so if the players are playing your game with the wrong orientation, you have to tell them to change orientation. This is quite easy, until you are making a responsive game which uses every single pixel of your device browser window.
The following example, made with Phaser, will show you how to “lock” orientation in a portrait responsive HTML5 game.
Let’s start from the index:
<!DOCTYPE html> <html> <head> <title>My responsive Portrait</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, minimal-ui" /> <script src="phaser.min.js"></script> <script src = "game.js"></script> <style> body{ margin:0px; padding:0px; } #turn{ width:100%; height:100%; position:fixed; top:0px; left:0px; background-color:white; background-image:url('playportrait.png'); background-repeat:no-repeat; background-position: center center; display:none; } </style> </head> <body> <div id = "turn"></div> </body> </html>
Apart from viewport meta which is used on iOS devices, there’s a div
whose id is turn
which will be used to display a white background covering everything on the screen, with this image in the center:
This is what we are going to show when the player tries to play the game in portrait mode.
Back to the game, we said we are going to make it responsive, so we will use every available pixel of the browser.
Here is the source code of game.js
:
window.onload = function() { var gameRatio = window.innerWidth/window.innerHeight; var game = new Phaser.Game(Math.ceil(640*gameRatio), 640, Phaser.CANVAS); var play = function(game){} play.prototype = { preload:function(){ game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL; game.load.image("topleft", "topleft.png"); game.load.image("center", "center.png"); game.load.image("bottomright", "bottomright.png"); }, create:function(){ game.add.sprite(0,0,"topleft"); game.add.sprite(game.width/2,game.height/2,"center").anchor.set(0.5,0.5); game.add.sprite(game.width,game.height,"bottomright").anchor.set(1,1); } } game.state.add("Play",play); game.state.start("Play"); }
The script is really simple, as I only place three images, one at the top left of the stage, one at the center and one at the bottom right of the stage. Also look at how I am defining game size: assuming my game is optimized for 640 pixels height, I set the width according to screen ratio.
When you start the game in portrait mode everything looks fine, until you turn the telephone in landscape:
But it’s not a problem since we are going to show the “turn your device” image.
window.onload = function() { var gameRatio = window.innerWidth/window.innerHeight; var game = new Phaser.Game(Math.ceil(640*gameRatio), 640, Phaser.CANVAS); var play = function(game){} play.prototype = { preload:function(){ game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL; game.scale.forceOrientation(false, true); game.scale.enterIncorrectOrientation.add(handleIncorrect); game.scale.leaveIncorrectOrientation.add(handleCorrect); game.load.image("topleft", "topleft.png"); game.load.image("center", "center.png"); game.load.image("bottomright", "bottomright.png"); }, create:function(){ game.add.sprite(0,0,"topleft"); game.add.sprite(game.width/2,game.height/2,"center").anchor.set(0.5,0.5); game.add.sprite(game.width,game.height,"bottomright").anchor.set(1,1); } } function handleIncorrect(){ if(!game.device.desktop){ document.getElementById("turn").style.display="block"; } } function handleCorrect(){ if(!game.device.desktop){ document.getElementById("turn").style.display="none"; } } game.state.add("Play",play); game.state.start("Play"); }
With forceOrientation
(line 10) we say we want not to be able to play in landscape (the first false
argument) but only in portrait (the second true
argument).
Then at lines 11 and 12 we listen to enter correct or incorrect orientation calling respectively handleIncorrect
and handleCorrect
functions.
These function, at lines 24-28 and 30-34 simply show or hide “turn” element setting its CSS display property to “block” (visible) or “none” (invisible).
And that’s what happens when you play in portrait then go to landscape:
Everything seems to be fine, until you start playing in landscape, being told to rotate your device:
The game starts correctly telling you to rotate the device, but unfortunately game dimensions have already been set when you rotate the device, so you will find a tiny landscape game in your portrait device.
Let’s make another change to the code:
window.onload = function() { var gameRatio = window.innerWidth/window.innerHeight; var game = new Phaser.Game(Math.ceil(640*gameRatio), 640, Phaser.CANVAS); var firstRunLandscape; var play = function(game){} play.prototype = { preload:function(){ firstRunLandscape = game.scale.isGameLandscape; game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL; game.scale.forceOrientation(false, true); game.scale.enterIncorrectOrientation.add(handleIncorrect); game.scale.leaveIncorrectOrientation.add(handleCorrect); game.load.image("topleft", "topleft.png"); game.load.image("center", "center.png"); game.load.image("bottomright", "bottomright.png"); }, create:function(){ game.add.sprite(0,0,"topleft"); game.add.sprite(game.width/2,game.height/2,"center").anchor.set(0.5,0.5); game.add.sprite(game.width,game.height,"bottomright").anchor.set(1,1); } } function handleIncorrect(){ if(!game.device.desktop){ document.getElementById("turn").style.display="block"; } } function handleCorrect(){ if(!game.device.desktop){ if(firstRunLandscape){ gameRatio = window.innerWidth/window.innerHeight; game.width = Math.ceil(640*gameRatio); game.height = 640; game.renderer.resize(game.width,game.height); game.state.start("Play"); } document.getElementById("turn").style.display="none"; } } game.state.add("Play",play); game.state.start("Play"); }
We have to know if the game was launched in landscape mode, so I have a firstRunLandscape
variable (line 4) which gets a Boolean value which is true
if the game was launched in landscape mode (line 10), then when the device is rotated in its correct position, if we know we are coming from a landscape start (line 34), we recalculate game ratio, width and height then resize the renderer and start the state again (lines 35-41).
Now everything will work fine.
You can test it by yourself at http://emanueleferonato.com/wp-content/uploads/2015/04/resp/ if you have a mobile device, or download the source code.
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.