8 years ago
Well this is my first question, and after a long time searching through the forum, I can't seem to find an answer...
I have a game that is supposed to fill the full width of the screen, and half of the height. This all works well in a fixed resolution system. What I would like to do now is, scale the game down proportionally as needed, while still keeping the view screen at the full width of the screen.
Is this at all possible? The thing is this is a game component of a web site that dynamically resizes to fit the browser at all times... The whole site works really good in every mobile I've tested, but I can't seem to find a way to also scale the game in proportion with the rest of the site, while keeping the game's view intact...
Also, if this is not possible, is there a way to dynamically change the spritesheets to which the game refers to in the level design, so that I can have multiple sized assets and then chose which one I want?
Thanks in advance,
Ok ... rephrasing my question ... can I manipulate the scale of the canvas/game, without changing the field of view? (canvas width seems to be attached to it's resolution, therefore my guess would be that I would have to scale the assets when the game is loaded and trigger a rescale of all values used in position and object collision ... still here's hoping)
Well... it seems you are figthing with what i've been fighting with for the last weeks...
ig.main is not well built : you don't know what will be the size of the canvas, what the scale really means, ... i'll post on this later when i have time.
Now i have a graphic engine that uses full resolution of the browser whatever the resolution, but this was a long work and i changed (injected) a lot of classes to achieve that. A great issue was that scale is supposed to be an integer (see ig.Image.resize) and in fact if you want to have full freedom of choice on resolution, you have to handle non-integer scale. So you have to redefine ig.Image.draw() and ig.Image.drawTile(), and to write an image scaling function that handles non-integer scale (for this i draw into a new canvas using canvas.scale(,)).
As i said, a lot of work...
8 years ago
// First find the max-width of the device.
// Let's pretend for this example that we found it to be 720.
var max_width = 720;
// Let's pretend your game at scale 1 is this size.
var width = 640;
var height = 480;
// Calculate the scale so that canvas will be the right size.
var scale = max_width / width; // equals 1.125
ig.main('#canvas', MyGame, 24, width , height , scale );
yes, ig.ua.viewport.width and height can help you find the right canvas size.
But that's not what i'm talking about. I'm talking about having a resolution independant game engine. So you would have your world, within this world all computations are done in world coordinates, and they are rendered to screen whatever resolution.
Here the width/height that you give to the ig.main are changed afterwise !!! and you end up having ig.system.width and realWidth. (same for height). So as the name suggest, if one width is 'real', the other is... fake. 'width' is in fact like a world view width, but at the same time it is used to compute the screen view width...
All this part of the framework should be re-though i think.
I did it in my project and i am pleased i have no longer headaches about my user screen resolution.
i rewrote ig.main into ig.main2, which looks like :
ig.main2( canvasId, MyGame,
screenCssWidth, screenCssHeight ,
worldViewWidth, worldViewHeight );
I use something like this sorry its a bit rushed but it should help, I dont understand why you need to inject / rewrite main to get this working. If you are detecting mouse / touch then dont Forget to include the ig.internalScale . (idealWidth & idealHeight are what you want you would like the canvas size to be in this example, but of course you can force based on width etc).
var canvas = ig.$('#canvas');
var gameWidth = window.innerWidth;
var gameHeight = window.innerHeight;
var scaleToFitX = gameWidth / idealwidth;
var scaleToFitY = gameHeight / idealheight;
var currentScreenRatio = gameWidth / gameHeight;
var optimalRatio = Math.min(scaleToFitX, scaleToFitY);
canvas.style.width = idealwidth * optimalRatio + "px";
canvas.style.height = idealheight * optimalRatio + "px";
ig.internalScale = idealwidth / ( idealwidth * optimalRatio );
ig.main('#canvas', PSCGame, 60, idealwidth, idealheight, 1, ig.ImpactSplashLoader);
Well it seems you didn't read me well, neither did you read well FBB's post.
We're talking about having a resolution independant game, where you can, on one hand set the world coordinate, and, on the other hand, choose screen coordinates with no constraint for both choices.
Let me give an example : for one making a game like 'cut the rope', he would work, say, in cm, and since we are within a room of, say, 4 meters by 3, the world coordinates would range from (x) 0 to 4000 // and (y) 0 to 3000. Then we do all our computation within this world. the speeds are in cm/s, acceleration cm/s^2, and all the size you can easily understand : it's all in cm, so much easier to set good values.
And then -the engine- renders it at whatever resolution you asked. As long as the aspect ratio remains the same between world view and screen view.
Your example doesn't work at all : imagine in my code i spawn an entity at 320, in the middle of my 640X480 screen. ok. now i change to 800X600. the entity will still be at 320 (scale is always 1 in your example), so it will no longer be in the middle of the screen. --> resolution dependancy = fail.
8 years ago
Hi guys, first off, thank you for all your answers...
Well I kind of figured as much... if we truly need to make a resolution independent game it would require a massive rewriting of main... The thing is I had already managed to get the effect I needed with a fix in all similar to what Stuart suggests. The main problem is performance... with that approach, we are stuck with either having good looking images in all devices (by using large assets) which in turn makes for ~20fps games in an iPhone, or having pixelated/blurred images on an iPad with ~57fps...
I think my solution will probably be to rewrite a big part of loader and maps classes in Impact so that I can load LD and HD assets, and resize everything on the fly so that I get the best from both worlds...
If I'm able to build this in a component fashion, would that interest anyone?
Thx, yes there's much to do...
I solved the issue of file size vs quality for the image by
using vector graphics i render on the fly at right resolution.
You talk about 20fps on iphone for HD, could you give details ?
which iPhone ?
how many entities ?
size of the graphics for those entities ?
and same questions for LD, the 57 fps on iPad, please.
i'd be interested to know wether the update() takes a
significant part of it or if all is eaten by draw() on iPhone.
A LD/HD library is interesting but 1) it should load only ONE
resolution 2) seems hard to me without a rewrite of main.
May be worth having a chat with fugufish as he is looking to resolve the same sort of issue.
8 years ago
Well I'm currently testing on all iPhones except 5 (3GS/4/4S) and iPad2 and 3.
The test scene is extremely basic, 1 player fully functional, one finish zone, 1 side scrolling layer and 2 effect zones on a transparent background.
Using a system in all similar to Stuart's resizing (plus some effect specific operations), I manage to have with 35x35 tiles and zoom 1, ~55fps on every iPhone (apparently they share the same resolution which leads me to think that safari is non-retina?), and on iPad using 70x70 tiles I get about the same performance...
So what I'm thinking of doing is rewrite the loader class so that it dynamically changes the folder where it searches for assets... for instance:
media/LD/ALL IMAGES WITH EXACT SAME NAMES
That way I build a singleton DeviceMgr that handles all window related operations for the game, and sets choses which asset folder to look in.
After that it should be pretty much straightforward to use a scale factor (in this case 0.5) to rescale all values in run-time ... what do you guys think about this process? Am I forgetting/over complicating something?
Thx for the answer. Did you try to remove the effects to see their fps cost ? i found so far with canvas that when you do not use only basic functions, but use globalAlpha/compositeOperation/..., the cost might raise very fast.
For the assets : inject a new init() for ig.image(). What you could do is that you only give the file NAME ('missile.png') when declaring a new image/Animation Sheet. And in the init() overload of ig.Image() you choose the right path depending on the resolution. Something like :
this.path= ( some condition ? 'media/LD/' : 'media/HD/' ) + filename ;
Rq : If you want to resize after loading you cannot use the resize provided in ig.Image : it is only working for integer >1 scale. I did a 'float' rescale within a new canvas, i can put the code here if you wish. Be warned though that the Impact code is quite messy : the word 'width' for instance means either 'image width', 'tile width', 'screen scaled width', 'screen width', 'world width' depending on ... we don't really know what :-)
For retina display, yes they do have the same resolution as the others... in css pixels. So the viewport width/height will be the same. BUT... there is a hidden css pixel --> screen pixel ratio that explains why the screen is sharper. you can know the css --> pixel ratio with ig.ua.pixelRatio.
maybe you wanna look at this link to understand better retina stuff :
Be warned also that using ig.system.scale === 0.5 factor will NOT display the images with a... 0.5 scale. I am not courageous enough to explain it now, but look the code, i just simply cannot understand how it works !!! (and i found while searching that it works because two bugs are cancelling one another...) so good luck :-)
Page 1 of 1