Closed Pattentrick closed 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.
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.
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?
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
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
?
Also, if you have access to iOS, can you get the same 5 values for a retina device?
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.
Update: The iPad mini of my friend does not have a retina display.
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?
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?
Oops, I think it may need to be ig.system.context
.
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
/**
@param {Boolean} [force=false] whether to force global resize (only do this when absolutely necessary). */ resize: function ( width, height, scale, force ) {
this.width = width * ig.ua.pixelRatio;
this.height = height * ig.ua.pixelRatio;
if ( typeof scale !== 'undefined' && scale !== null ) {
this.scale = scale;
}
console.log( ig.system.context );
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 / ig.ua.pixelRatio ) + "px";
this.canvas.style.height = Math.round( this.realHeight / ig.ua.pixelRatio ) + "px";
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);
}
});
Fun fact: If i log the ig.system
, the first log is undefined and the other three are class references :O
Oops, my fault. this.context
should work, since that is a method of the system.
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).
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
Update: Even switching the config file from the supercollider demo does nothing. i don't get it oO
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).
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.
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?
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 :-/
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.
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.
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.
Editing the plusplus.js as you suggest, results in a veeeery big canvas with a very small game in it.
What are the window width/height, realWidth/realHeight, and canvas style width/height values in this case?
Here we go:
window width: 910 window height: 408
realWidth: 2730 realHeight: 1224
canvas style width: 2730 canvas style height: 1224
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";
}
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
That shouldn't be happening... can you paste the current resize method in the plusplus.js file (with the most recent edit)?
I'm not sure what you mean. I already pasted the code in the plusplus.js file. Or do you mean at my demo?
In case you meant "paste it here":
javascript
/**
@param {Boolean} [force=false] whether to force global resize (only do this when absolutely necessary). */ resize: function ( width, height, scale, force ) {
this.width = width * ig.ua.pixelRatio;
this.height = height * ig.ua.pixelRatio;
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;
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";
}
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);
}
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);
OMFB! YOU MADE IT!
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 ;-)
Ping @aroth can you test the system resize method changes just above this post, if you're still working with retina?
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.
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?
No worries man, if it isn't resolved someone will post an issue about it. Hope things start going better for you soon!
@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)
@Pattentrick thanks for the reminder, thought I'd already done it!
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 a3
. 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 = {