Daniel Belohlavek

Scaling my game.

Recommended Posts

My never ending battle with scaling continues. I was reading the ebook "A guide to the scale manager" and I was tryng to replicate the behaviour seen in Spice Quest by goodboydigital: http://www.goodboydigital.com/client/razorfish/McD_PeriPeri/

 

That game has 3 key features I'd like to implement:

 

  • Responsive scaling. Try to resize the browser and you will see that the game will respond.
  • Aspect ratio. The canvas will only grow if the window.innerWidth/height values respect the original game ratio.
  • Full screen support.

This seems to be the system used in Spice Quest:

 

App.prototype.resize = function(w, h) {   this.options.resizeMode === App.resizeModes.DEFUALT ? (this.renderer.resize(w, h), this.view.style.width = "auto", this.view.style.height = "auto") : this.thisoptions.resizeMode === App.resizeModes.CSS_RESIZE_PRESERVE_RATIO || this.options.resizeMode === App.resizeModes.CSS_RESIZE && (this.view.style.width = w + "px", this.view.style.height = h + "px")}

 

Reading the guide I mentioned, I believed that I could achieve this with SHOW_ALL, horizontal and vertical alignment and finally fullscreen activation when the player taps a button. Sadly I was not able to reproduce these features and SHOW_ALL scales outside the viewport.

 

Was anyone able to implement this? Is there any code example somewhere explaining how to do this?

 

Thanks for reading :)

 

P.S. My apologies to GoodboyDigital for snooping around your code. Please tell me if you wish me to remove it from the post.

Share this post


Link to post
Share on other sites

I don't know how your specific game or framework (Phaser?) is set up, but here's some general code that will center and scale an HTML canvas to the maximum browser window size:

var scaleX, scaleY, scale, center;  //1. Scale the canvas to the correct size//Figure out the scale amount on each axisscaleX = window.innerWidth / canvas.width;scaleY = window.innerHeight / canvas.height;//Scale the canvas based on whichever value is less: `scaleX` or `scaleY`scale = Math.min(scaleX, scaleY);canvas.style.transformOrigin = "0 0";canvas.style.transform = "scale(" + scale + ")";//2. Center the canvas.//Decide whether to center the canvas vertically or horizontally.//Wide canvases should be centered vertically, and //square or tall canvases should be centered horizontallyif (canvas.width > canvas.height) {  center = "vertically";} else {  center = "horizontally";}//Center horizontally (for square or tall canvases)if (center === "horizontally") {  var margin = (window.innerWidth - canvas.width * scaleY) / 2;  canvas.style.marginLeft = margin + "px";  canvas.style.marginRight = margin + "px";}//Center vertically (for wide canvases) if (center === "vertically") {  var margin = (window.innerHeight - canvas.height * scaleX) / 2;  canvas.style.marginTop = margin + "px";  canvas.style.marginBottom = margin + "px";}//3. Remove any padding from the canvas and set the canvas//display style to "block"canvas.style.paddingLeft = 0;canvas.style.paddingRight = 0;canvas.style.display = "block";

Also, if you have some kind of mouse or touch pointer, you'll need to scale the pointer's x/y values by the same amount as the canvas.

Something like this:

pointer.x / scale;pointer.y / scale;

This is the general idea - but you'll need to adapt this code to your own environment.

 

To dynamically re-scale the canvas whenever the browser window is re-sized, call your scaling code in a window resize event.

window.addEventListener("resize", function(event){  yourCustomScaleFunction();});

Share this post


Link to post
Share on other sites

SHOW_ALL is not working as expected for me, I use USER_SCALE instead.

 

game.scale.scaleMode = Phaser.ScaleManager.USER_SCALE;

game.scale.setResizeCallback(this.gameResized, this);

 

gameResized(manager: Phaser.ScaleManager, bounds: Phaser.Rectangle)
{
    var scale = Math.min(window.innerWidth / this.game.width, window.innerHeight / this.game.height);
 
    manager.setUserScale(scale, scale, 0, 0);
}

Share this post


Link to post
Share on other sites

@Smrdis' solution worked fine, I just tweaked it a little bit to fit my needs:

static resize(context: any, logging?: boolean) {    var _this = context;    // A value of 1 means no scaling 0.5 means half size, 2 double the size and so on.    var scale = Math.min(window.innerWidth / _this.game.width, window.innerHeight / _this.game.height);    // Resize parent div in order to vertically center the canvas correctly.    document.getElementById("game-canvas").style.minHeight = window.innerHeight.toString() + "px";    // Resize the canvas keeping the original aspect ratio.    _this.game.scale.setUserScale(scale, scale, 0, 0);    if (logging == true) {        var w = Math.floor(_this.game.width * scale),            h = Math.floor(_this.game.height * scale);        console.info("The game has just been resized to: " + w + " x " + h);    }}

Now, when I try to call game.scale.startFullScreen() the game fails to resize and the canvas seems to go outside of the viewport. I'm calling my resize utility method from setResizeCallback(), so why is it failing to update? In fact, the result should be the same, as the width would stay intact and the aspect ratio would be respected, thus the height wouldn't change: only the vertical alignment.

 

This would be different in an real mobile device because the address bar would go away and the height _would_ change. But that's not the case with Chrome's mobile emulation tool.

 

Thanks for the help so far!

Share this post


Link to post
Share on other sites

I worked this afternoon on a game basic template. It's far to be finish yet but I think you will love what I was able to create !

 

My work is here:

Edit: Here's the link updated:  https://mega.nz/#!q8g3nTCQ!b0l3dgR7GMBosBekEZ-gBwoU6E0qh_S2RAgVZkoamyo
Phaser has probably evolve a lot since 1 year so I don't know if it's still working. But at least you will be able to figure out how to do it by adapting what I've done.

You can simply launch the game by typing the command "grunt" when you're in the folder (install grunt with "npm install -g grunt-cli" command).

You will see you can resize the window and the game will keep the same size ratio as we all except :P

You can define the resolution (and by the way the ratio of your game) in config.js.

Let me now if you got any questions :)
PS: I've use the ebook "A guide to the scale manager" too for create this !

Edited by Filozofer
Download link update

Share this post


Link to post
Share on other sites

Finally I got it to work (I was missing a single line). I'll share the complete solution I used based on the answers on this thread.

 

Boot.ts

module Game {    export class Boot extends Phaser.State {        parentElement: HTMLElement = document.getElementById("game-canvas");        preload() {            // preload something        }        create() {            this.game.scale.fullScreenTarget = this.parentElement;            this.game.scale.scaleMode = Phaser.ScaleManager.USER_SCALE;            this.game.scale.fullScreenScaleMode = Phaser.ScaleManager.SHOW_ALL; // Important            this.game.scale.pageAlignHorizontally = true;            this.game.scale.pageAlignVertically = true;            this.game.stage.disableVisibilityChange = true;            this.game.input.maxPointers = 1;            this.game.scale.setResizeCallback(function () {                Utils.Mobile.resize(this.parentElement, this, true);                 // you would probably just use this.game.scale.setResizeCallback(this.resize, this);            }, this);            this.game.state.start('Preload', true, false);        }    }}

Utils.Mobile.resize()

static resize(element: HTMLElement, context: any, logging?: boolean) {    var _this = context;    // A value of 1 means no scaling 0.5 means half size, 2 double the size and so on.    var scale = Math.min(window.innerWidth / _this.game.width, window.innerHeight / _this.game.height);    // Resize parent div in order to vertically center the canvas correctly.    element.style.minHeight = window.innerHeight.toString() + "px";    // Resize the canvas keeping the original aspect ratio.    _this.game.scale.setUserScale(scale, scale, 0, 0);    if (logging == true) {        var w = Math.floor(_this.game.width * scale),            h = Math.floor(_this.game.height * scale);        console.info("The game has just been resized to: " + w + " x " + h);    }}

Then you can call startFullScreen() whenever you want. Personally I'm going yo make it so that the fullscreen is triggered every time the user taps into the game (to prevent the user from exiting fullscreen and continue playing).

 

Thanks everybody for the help  :D

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.