collinhover / impactplusplus

Impact++ is a collection of additions to ImpactJS with full featured physics, dynamic lighting, UI, abilities, and more.
http://collinhover.github.com/impactplusplus
MIT License
276 stars 58 forks source link

No scaling on Chrome Mobile (Android). #117

Closed Pattentrick closed 10 years ago

Pattentrick commented 10 years ago

Hi @collinhover,

my game does not scale on my chrome mobile (android). But the supercollider demo does, so i think that i just missed something. I already compared the config-user.js and main.js from the supercollider to my game without any success.

But when i do an alert(ig.system.scale)on chrome mobile it will print a 3. However the game stays in it's smallest size (320px x 200px). Strange :-/

Do you have any idea how i could fix this?

In case i just messed up my config-user:

javascript ig.CONFIG_USER = {

        // set to true for a top down game
        TOP_DOWN: true,

        // enable fullscreen
        GAME_WIDTH_PCT: 1,
        GAME_HEIGHT_PCT: 1,

        // start resolution that will be dynamically scaled
        GAME_WIDTH_VIEW: 320,
        GAME_HEIGHT_VIEW: 200,

        // show transition between levels
        TRANSITION_LEVELS: false,

        // font and text settings
        FONT: {
            CHAT_NAME: "monologue_font_10px.png"
        },

        // camera settings
        CAMERA: {
            AUTO_FOLLOW_PLAYER : false
        },

        // character movement speed
        CHARACTER: {
            MAX_VEL_GROUNDED_Y: 30,
            MAX_VEL_GROUNDED_X: 30
        }

    };
collinhover commented 10 years ago

Have you tried editing the max/min scale config options? Something like:

// clamped scaling is still dynamic, but within a range
// so we can't get too big or too small
SCALE_MIN: 1,
SCALE_MAX: 4,

If this fixes it, there is a bug in the scaling as it should scale up to infinity by default.

Pattentrick commented 10 years ago

The max scale gets ignored when i edit the config options. But changing the min scale in the options does have an effect on the game. Setting the min scale to 4 for example, will scale the game as expected.

But after loading a new level, it scales back to the original size of 320 x 200.

I have no idea what the cause of this problem is. The only thing that maybe could be related to this, is my custom resize-method.

javascript resize : function(){

        this.parent();

        // Check for game instance
        if( ig.game !== null ){

            // Center camera on gamescreen
            this.centerStaticCamera();

        }

    },


But i highly doubt it, because the centerStaticCamera-method just alters the screen position. The Problem also occurs at the demo i posted at Issue #112, if you want to see this in action.
collinhover commented 10 years ago

This is hard for me to test myself as it only appears on Android + Chrome, correct? What value do you get for ig.ua.pixelRatio? Can you add an alert here, https://github.com/collinhover/impactplusplus/blob/dev/lib/plusplus/core/game.js#L2509, and tell me what the values of the local variable scale, _c.SCALE_MIN, and _c.SCALE_MAX are?

Pattentrick commented 10 years ago

On further inspection the problem also occurs on Firefox for Android and on the default browser for Android (don't know if it has a name ). On iOS everything seems to be fine.

Here are the values you requested:

scale = 2
scale min = 1
scale max = infinity
pixelratio = 3
collinhover commented 10 years ago

The pixel ratio is the issue, I believe. The scale is divided by the pixel ratio to get the final style width/height of the canvas. This accounts (or should account) for retina devices. ImpactJS only accounts for the window pixel ratio, and webkit also has webkitBackingStorePixelRatio. Can you get the value of the canvas context's webkitBackingStorePixelRatio?

collinhover commented 10 years ago

Also, if you have access to iOS, can you get the same 5 values for a retina device?

Pattentrick commented 10 years ago

On Chrome and the default browser webkitBackingStorePixelRatio is 1. On Firefox it is undefined.

I don't have access to iOS right now, but i will phone a friend once he is back at home if he could do a check on his iPad mini. But i think that iPad mini does not have a retina dsiplay.

Pattentrick commented 10 years ago

Update: The iPad mini of my friend does not have a retina display.

collinhover commented 10 years ago

Based on http://www.html5rocks.com/en/tutorials/canvas/hidpi/, it looks like Safari and Chrome disagree on the handling of the pixel ratio. I believe on Safari / iOS retina the webkitBackingStorePixelRatio is the same as the window pixel ratio. Can you try changing the lines starting here, https://github.com/collinhover/impactplusplus/blob/dev/lib/plusplus/core/plusplus.js#L245, to:

var backingToPixelRatio = ig.ua.pixelRatio / (ig.System.context.webkitBackingStorePixelRatio || 1);
this.realWidth = this.width * this.scale * backingToPixelRatio;
this.realHeight = this.height * this.scale * backingToPixelRatio;

// retina support

this.canvas.width = this.realWidth;
this.canvas.height = this.realHeight;
this.canvas.style.width = Math.round(this.realWidth / ig.ua.pixelRatio) + "px";
this.canvas.style.height = Math.round(this.realHeight / ig.ua.pixelRatio) + "px";

Does that work?

Pattentrick commented 10 years ago

The game won't start (even on desktop) when i edit the plusplus.js as you suggested.

Uncaught TypeError: Cannot read property 'webkitBackingStorePixelRatio' of undefined

ig.System.context seems to be undefined?

collinhover commented 10 years ago

Oops, I think it may need to be ig.system.context.

Pattentrick commented 10 years ago

Same problem with ig.system.context. Even if i just do a console.log( ig.system.context ); on the resize method at the plusplus.js i get an undefined.

Example:

javascript /**

Fun fact: If i log the ig.system, the first log is undefined and the other three are class references :O

xample

collinhover commented 10 years ago

Oops, my fault. this.context should work, since that is a method of the system.

Pattentrick commented 10 years ago

No more undefined with this.context. No more "crashes" on desktop :D

But on mobile the game does not start. For a brief moment you can see the loading bar and then ... nothing. I am not sure, but it seems like the canvas get's bigger and bigger and after some time the browser crashes (firefox/chrome).

Pattentrick commented 10 years ago

As i mentioned on my first post, the supercollider demo runs perfect on firefox/chrome (mobile). And my game does not ... so what is the biggest difference between these two games? Ok ... i have lots of custom code at my game, but even on the titlescreen (where nothing happens, and no custom code get's called) scaling won't work.

Could it be the config file? Doesn't make much sense to me ... but i am pretty clueless right know :D

Pattentrick commented 10 years ago

Update: Even switching the config file from the supercollider demo does nothing. i don't get it oO

collinhover commented 10 years ago

Okay, lets drop any of the changes and go back to the latest dev branch. I'll look at your demo as soon as I get some time tomorrow (we'll assume for now it is an issue specific to your demo).

Pattentrick commented 10 years ago

Ok, sounds great! Although "we" couldn't solve this issue today, it was pretty fun to mess around with the ++ code ;-)

As always thank you for your support! I hope i can repay you someday anyhow for this. By the way, i finished my game today. I will send you a link once i fixed all the open issues i am having.

collinhover commented 10 years ago

Looking through the demo you posted with the firefox issue, I honestly can't find anything in the primary game files that would cause this scaling issue. I also tried a few searches across all of the game code to find some likely causes, and nothing came up.

Lets try something new: change the resize code in plusplus/core/plusplus.js to force a specific scale. Does it work? What if you remove the divide by pixel ratio?

Pattentrick commented 10 years ago

Forcing a scale:

Forcing a specific scale will render a really small game (scale 1) in a big, but fully visible, canavs (it seems to be zoomed out ...).

Forcing a scale + remove divide by pixel ratio:

Forcing a specific scale and removing the divide by pixel ratio will render a small (scale 1) game in a big canvas (you have to scroll to get to the game screen).

Just removing the pixel ratio:

Just removing the divide by pixel ratio will result in a normally scaled (3 in my case) game but in a too big canvas (you have to scroll again).

Further notes:

Using the plusplus.js from the the latest master (r6) fixes this issues and displays the game as intended.

Sadly this seems to be a problem on all android devices i tested so far (Galaxy S4/ Galaxy S3/ Galaxy S3 Mini, Galaxy Nexus) on all browsers :-/

collinhover commented 10 years ago

So if I understand you, the master branch does not have the scaling issue? Also, to confirm, the issue is not present in the super collider when you run it with the latest dev, or the super collider that is already online?

It appears the issue is the pixel ratio, which was added to fix retina scaling. It looks like for android it may need to be reversed, using the webkitBackingStorePixelRatio.

Pattentrick commented 10 years ago

The master branch does not have the scaling issue on android, exactly! The supercollider demo that is live under http://collinhover.github.io/impactplusplus/demo/index.html also does not have the scaling issue.

The supercollider demo from the latest dev has the same scaling issue as my game. What makes sense, because they are using the same plusplus.js.

So yes, the added retina fix could be the culprit.

collinhover commented 10 years ago

Okay, another trial starting here, https://github.com/collinhover/impactplusplus/blob/dev/lib/plusplus/core/plusplus.js#L252, to:

var pixelRatio = Math.min(ig.ua.pixelRatio, (this.context.webkitBackingStorePixelRatio || 1));
this.canvas.style.width = Math.round(this.realWidth / pixelRatio) + "px";
this.canvas.style.height = Math.round(this.realHeight / pixelRatio) + "px";

My thought is that when the backing store is less than the pixel ratio, we can defer to the backing store with the canvas style.

Pattentrick commented 10 years ago

Editing the plusplus.js as you suggest, results in a veeeery big canvas with a very small game in it.

collinhover commented 10 years ago

What are the window width/height, realWidth/realHeight, and canvas style width/height values in this case?

Pattentrick commented 10 years ago

Here we go:

window width: 910 window height: 408

realWidth: 2730 realHeight: 1224

canvas style width: 2730 canvas style height: 1224

collinhover commented 10 years ago

Thanks, okay once again starting here, https://github.com/collinhover/impactplusplus/blob/dev/lib/plusplus/core/plusplus.js#L252, to:

if( ig.ua.pixelRatio > 1 && (!this.context.webkitBackingStorePixelRatio || this.context.webkitBackingStorePixelRatio > 1) ) {
this.canvas.style.width = Math.round(this.realWidth / ig.ua.pixelRatio) + "px";
this.canvas.style.height = Math.round(this.realHeight / ig.ua.pixelRatio) + "px";
}
Pattentrick commented 10 years ago

Hmmm ... everything gets bigger ...

Here are the values:

window width: 2560 window height: 1148

realWidth: 7680 realHeight: 7680

canvas style width: empty string canvas style height: empty string

collinhover commented 10 years ago

That shouldn't be happening... can you paste the current resize method in the plusplus.js file (with the most recent edit)?

Pattentrick commented 10 years ago

I'm not sure what you mean. I already pasted the code in the plusplus.js file. Or do you mean at my demo?

Pattentrick commented 10 years ago

In case you meant "paste it here":

javascript /**

collinhover commented 10 years ago

Yep, just wanted to see exactly what you had for the resize method, and we need to rework it a bit:

var modifier;

if( ig.ua.pixelRatio > 1 && (!this.context.webkitBackingStorePixelRatio || this.context.webkitBackingStorePixelRatio > 1) ) {
    modifier = ig.ua.pixelRatio;
} else {
    modifier = 1;
}

this.width = width * modifier;
this.height = height * modifier;

if ( typeof scale !== 'undefined' && scale !== null ) {

this.scale = scale;

}

this.realWidth = this.width * this.scale;
this.realHeight = this.height * this.scale;

// retina support

this.canvas.width = this.realWidth;
this.canvas.height = this.realHeight;
this.canvas.style.width = Math.round(this.realWidth / modifier) + "px";
this.canvas.style.height = Math.round(this.realHeight / modifier) + "px";
alert(' w: ' + width + ' h: ' + height + ' rw: ' + this.realWidth + ' rh: ' + this.realWidth + ' cw: ' + this.canvas.style.width + ' ch: ' + this.canvas.style.height );

this.size = Math.min(this.width, this.height);

// switch to crisp scaling when using a scale other than 1

if ( this.scale !== 1 && _c.AUTO_CRISP_SCALING ) {

    ig.System.scaleMode = ig.System.SCALE.CRISP;

}

ig.System.scaleMode( this.canvas, this.context );

this.onResized.dispatch(force);
Pattentrick commented 10 years ago

OMFB! YOU MADE IT!

Pattentrick commented 10 years ago

Sorry for the capslock! :D

It works on my android device perfectly. But i don't have a retina device here to test. But as far as i am concerned, everything is good ;-)

collinhover commented 10 years ago

Ping @aroth can you test the system resize method changes just above this post, if you're still working with retina?

aroth commented 10 years ago

Yes. I've been following along. I will test tomorrow and reply back. Excellent work again as always.

On Jan 16, 2014, at 8:42 PM, Collin Hover notifications@github.com wrote:

Ping @aroth can you test the system resize method changes just above this post, if you're still working with retina?

— Reply to this email directly or view it on GitHub.

aroth commented 10 years ago

Sorry guys, my life literally imploded two weeks ago. Sad stuff. I'll get my head in gear soon enough. Was this truly resolved, or were you waiting on my confirmation?

collinhover commented 10 years ago

No worries man, if it isn't resolved someone will post an issue about it. Hope things start going better for you soon!

Pattentrick commented 10 years ago

@collinhover I just noticed that your fix for this is not part of the dev branch at the moment. Do you plan to add this fix (it worked well in my case) to the dev? I could do a pull request if you like (don't know if that is easier for you, than edit the code and commit it for yourself)

collinhover commented 10 years ago

@Pattentrick thanks for the reminder, thought I'd already done it!