Jump to content

Retina displays question


Recommended Posts

I'm having a little trouble to understand this:

 

I have a canvas, let's say 480x320, and I use a div container to resize it.

CSS.canvas { width: 100%; height: 100%; }JSresize(); //Here using window.innerWidth and window.innerHeight I find the dimensions of the device and I apply those measurements to the div container so the game gets resized via CSS.Viewport<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> 

If I use this code on a retina device, will it display the game correctly stretched or double sized? Different pov, same question: will window.innerHeight return the device pixels or the CSS pixels?

 

I can make the same question again using different words :lol: . I want to correct the images because I don't like how retina displays resizes my game. So I make my canvas double size 960x640 and use of course bigger sprites. Using the solution above, what should I do to fit my game, stick to the window.innerHeight value or use half of it because then it will be doubled by the display?

 

I hope someone understood my question, if not, I can still ask it in several more different ways, I feel inspired today :D

Link to comment
Share on other sites

It depends on how you detect the device width. I don't know which of those values window.innerHeight returns, but if I had to guess, it would be CSS pixels.

 

Luckily, you can tell if you need to resize the inner canvas size with window.devicePixelRatio. Just multiply canvas.width and canvas.height by window.devicePixelRatio, and it will display correctly on retina and non-retina devices.

Since now canvas.style.width is different from canvas.width, you'll be drawing more hardware pixels per display pixel, which is exactly what you want.

 

However, this means that your canvas will be 4 times larger on retina devices. This is a problem because your game is going to be drawn in the top left quarter of the screen if you continue to use the same pixel co-ordinates for drawing things.

So the last thing you need to do is scale the canvas context by window.devicePixelRatio, so that all the co-ordinates you use in the game will be scaled up for the larger canvas area.

 

To recap, assuming canvas.style.width and canvas.style.height remain unchanged because they are already set in CSS, do this:

canvas.width *= window.devicePixelRatio;canvas.height *= window.devicePixelRatio;canvas.getContext("2d").scale(window.devicePixelRatio, window.devicePixelRatio);

 

You'll probably want to clean up that code a bit. Remember you are changing both the canvas element and the canvas context.

Link to comment
Share on other sites

It depends on how you detect the device width. I don't know which of those values window.innerHeight returns, but if I had to guess, it would be CSS pixels.

 

Luckily, you can tell if you need to resize the inner canvas size with window.devicePixelRatio. Just multiply canvas.width and canvas.height by window.devicePixelRatio, and it will display correctly on retina and non-retina devices.

Since now canvas.style.width is different from canvas.width, you'll be drawing more hardware pixels per display pixel, which is exactly what you want.

 

However, this means that your canvas will be 4 times larger on retina devices. This is a problem because your game is going to be drawn in the top left quarter of the screen if you continue to use the same pixel co-ordinates for drawing things.

So the last thing you need to do is scale the canvas context by window.devicePixelRatio, so that all the co-ordinates you use in the game will be scaled up for the larger canvas area.

 

To recap, assuming canvas.style.width and canvas.style.height remain unchanged because they are already set in CSS, do this:

canvas.width *= window.devicePixelRatio;canvas.height *= window.devicePixelRatio;canvas.getContext("2d").scale(window.devicePixelRatio, window.devicePixelRatio);

 

You'll probably want to clean up that code a bit. Remember you are changing both the canvas element and the canvas context.

This helped to clear some fog from my mind! Thanks!

 

i'll try this approach or if availabre I'll try to use bigger sprites and proper coordinates so I don't have to scale up the context.

Link to comment
Share on other sites

You can still use bigger sprites! context.drawImage lets you specify the destination size. So you can draw a double sized image onto a regular sized area.

 

All my game assets are in normal resolution, double resolution and quadruple resolution so that I can display sharp images from iphone 3gs devices all the way up to ipad retina.

I just load the correct image size by detecting the platform. But none of my rendering code needs to change.

Link to comment
Share on other sites

You can still use bigger sprites! context.drawImage lets you specify the destination size. So you can draw a double sized image onto a regular sized area.

 

All my game assets are in normal resolution, double resolution and quadruple resolution so that I can display sharp images from iphone 3gs devices all the way up to ipad retina.

I just load the correct image size by detecting the platform. But none of my rendering code needs to change.

That's smart :ph34r: , I didn't even think of that possibility!

 

So you suggest doing this:

 

canvas.width *= window.devicePixelRatio;canvas.height *= window.devicePixelRatio;canvas.getContext("2d").scale(window.devicePixelRatio, window.devicePixelRatio); 

While drawing with double sized sprites and downscaling them by window.devicePixelRatio in the drawImage() call. I'll definitely give it a try

Link to comment
Share on other sites

I don't know how smart it is actually.

If I learned one thing, it is: don't waste resources on mobile devices!

 

Loading bigger images and rendering them downscaled means:

 

  • More content to download over a possibly slow connection
  • More data to store in memory
  • Slower rendering process, since all assets need to be downsampled and rendered on EVERY FRAME.

So this approach would be a no-go for me.

 

Additionally, increasing your canvas dimensions and rendering retina graphics can break down your rendering speed, too, since having a canvas with a dimension of 320x480 px vs. a canvas with 640x960px on the iphone means four times more pixels to draw on each frame.

 

Idk how complex the your games are, but I can figure that you will very quickly reach a point where it just lags.

Link to comment
Share on other sites

Yeah, that's true, my app is using ejecta so rendering is hardware accelerated. It also loads assets from the local file system.

 

If it were a networked game running in a regular mobile browser, it would probably take several minutes just to load.

 

And I had problems running into the memory limit from loading assets at quadruple resolution for the ipad retina display.

Link to comment
Share on other sites

  • 7 months later...

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...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...