Jon Goikolea Posted May 11, 2013 Share Posted May 11, 2013 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 . 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 Quote Link to comment Share on other sites More sharing options...
whirlibulf Posted May 11, 2013 Share Posted May 11, 2013 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. Quote Link to comment Share on other sites More sharing options...
Jon Goikolea Posted May 14, 2013 Author Share Posted May 14, 2013 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. Quote Link to comment Share on other sites More sharing options...
whirlibulf Posted May 14, 2013 Share Posted May 14, 2013 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. Jon Goikolea 1 Quote Link to comment Share on other sites More sharing options...
Jon Goikolea Posted May 14, 2013 Author Share Posted May 14, 2013 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 , 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 Quote Link to comment Share on other sites More sharing options...
Chris Posted May 14, 2013 Share Posted May 14, 2013 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 connectionMore data to store in memorySlower 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. Quote Link to comment Share on other sites More sharing options...
whirlibulf Posted May 14, 2013 Share Posted May 14, 2013 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. Quote Link to comment Share on other sites More sharing options...
Zebestov Posted December 21, 2013 Share Posted December 21, 2013 I'm doing it this way:canvas.width = myWidth * window.devicePixelRatio;canvas.height = myHeight * window.devicePixelRatio;canvas.style.width = myWidth + "px";canvas.style.height = myHeight + "px"; Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.