sheetContentWidth and sheetContentHeight

Hi,

  One aspect of Corona that I’m confused by is the sheetContentWidth/sheetContentHeight options in newImageSheet.

  What confuses me is why these are needed at all?  Shouldn’t the image file meta data itself indicate its width and height?  And how exactly does this help with the dynamic scaling?  I’ve read that section of the docs over and over and saw no references to the sheetContentWidth/Height - only to the selection of images based on the suffixes.

  If you specify a sprite frame size, the number of frames, and the file contains its dimensions (as they all do) why would you then indicate the sheet size unless it is somehow smaller than the image size?  And again, what does any of it have to do with scaling of 1x? the dynamic scaling seems to ask you to define the “@2x” monikers in your filenames, so presumably that would tell the sdk what the original scale was and I wouldn’t have to specify it myself during sheet creation?

  The docs say:

These values tell Corona the size of the original 1x image sheet. For example, if you’re developing for both iPad and iPad Retina, and you’re using an image sheet of 1000×1000 for the regular iPad, you should specify 1000 for both of these values and then design your Retina image sheet at 2000×2000.

Please help me understand this.  If my retina version of the sheet is 500x50, and has 10 sprites of 50x50, and I have 2 png image sheets - 1 that is 500x50 (2X for Retina iPad - lets call it “ship@2x.png”) and 1 that is 250x25 (1X for regular ipad - “ship.png”) that when I go to load the sheet on EITHER ipad or ipad retina I would use the exact same line:

 spritesheet = graphics.newImageSheet( “ship.png”, {width=25, height=25, numFrames=10, sheetContentWidth=250, sheetContentHeight=25})

…and that the SDK will automatically adjust the image sheet name to ship@2x.png for the iPad retina (if I define it properly in my config.lua) and use ship.png automatically for ipad? correct?

What confuses me further (assuming the above is essentially correct- and I don’t know that it is) is that I had planned to use adaptive scaling - so that presumably the stage content[width|height] is going to match the device’s display resolution.  So would the sprites for iPad Retina be 25x25 or 50x50?  I mean, I get that if I were using a fixed content scale for the application that the screen gets stretched and the coordinate system presumably is mapped for the display resolution.  But if you use adaptive scaling, then what should I expect when I go to provide offsets into the sprite’s local object space? a 50x50 area or a 25x25 area?  Is that entirely determined by the resolution of the 1x sprite? 

Thanks- I know I asked a few questions here.  I’ve been searching the forums and google for quite a while, and I’m sure this is a newbie question that I just haven’t grasped yet.  I appreciate your patience in entertaining it once again if I’ve failed to find the definitive thread on it.  I watched the video on dynamic scaling and it didn’t clear it up for me.  I guess its the whole “adaptive” scale setting in the config.lua that is confusing me because I then have no basis for what my 1x sprites represent in relation to the screen- if that makes sense. 

thanks,

Byron

Please help me understand this.  If my retina version of the sheet is 500x50, and has 10 sprites of 50x50, and I have 2 png image sheets - 1 that is 500x50 (2X for Retina iPad - lets call it “ship@2x.png”) and 1 that is 250x25 (1X for regular ipad - “ship.png”) that when I go to load the sheet on EITHER ipad or ipad retina I would use the exact same line:

 spritesheet = graphics.newImageSheet( “ship.png”, {width=25, height=25, numFrames=10, sheetContentWidth=250, sheetContentHeight=25})

…and that the SDK will automatically adjust the image sheet name to ship@2x.png for the iPad retina (if I define it properly in my config.lua) and use ship.png automatically for ipad? correct?

Yes this is correct. Think of display.newImage() and display.newImageRect(). The key difference between the two is that display.newImage() loads the file name specified at the width and height of the actual image. You don’t set it. You may scale it later yourself. It does not know how to use @2x, @4x type images.  For display.newImageRect() you provide a filename and the 1x width and height to make the image (since we are working in content units). This variant will use the scaling information in config.lua to determine if the real device’s screen is close to the width and height in config.lua and then pull in the best matching graphic and load it at that size.

If your config.lua says you’re using a 320 point wide content area and you’ve defined your imageSuffix block to say load @2x images when the scale is 2.0, on a 640px wide screen you will get the @2x image. On a 639px screen (of course there aren’t any, but for logic sake) you will get the 1x image. For screens 640px to 1279px, your @2x image is used, and if you defined an @4x image, from 1280px and greater you would get the @4x image.

Sprite sheets are based on the logic behind display.newImageRect().  If your 1x image sheet is 250x25, then you would tell the graphics.newImageSheet that sheetContentWidth and sheetContentHeight are 250 and 25 like you have it. If we detect you’re on an @2x device, we will add the @2x suffix and try and load that image and let dynamic scaling work for you.

What confuses me further (assuming the above is essentially correct- and I don’t know that it is) is that I had planned to use adaptive scaling - so that presumably the stage content[width|height] is going to match the device’s display resolution.  So would the sprites for iPad Retina be 25x25 or 50x50?  I mean, I get that if I were using a fixed content scale for the application that the screen gets stretched and the coordinate system presumably is mapped for the display resolution.  But if you use adaptive scaling, then what should I expect when I go to provide offsets into the sprite’s local object space? a 50x50 area or a 25x25 area?  Is that entirely determined by the resolution of the 1x sprite?  thanks,

Byron

Adaptive scaling is a quirky concept to grasp. But let’s start with the TL;DR of it. You most likely should not use it for games.

Think of any game really… But lets use Clash of Clans. If you play it on a phone or a tablet, it’s basically the same. Controls are in the same position. (well some stuff may stretch to edges on a wider phone, closer together on a taller iPad)  It’s just stuff is bigger on the tablet.

Now consider a business app that’s using a bunch of switches, tableViews, etc. On an iPad, you don’t expect those tableView rows to double or triple in height, it would be nice if the tableView’s rows stayed the same, but you got more rows visible. Or the on/off switch is the same size if you hold your iPad and iPhone up together (well close). This is where Adaptive scaling comes in.

On an iPhone 4/5 you get a 320x width content area, on the iPhone 6 where there is more real estate  you get a 375x wide content area and on the iPhone 6 plus you get 414px wide. On the iPad’s you get 768x content points wide to play with. This gives you the flexibility to have your app look different on the different devices, rewarding the larger screen with more content.

So for Flappy Birds, this is not desirable. For ESPN Fantasy Football it is (or business/utility apps). I did a weather app for my wife. She has an iPhone 5, and can only get about 5 days of the extended forecast on her screen before she starts scrolling. On my iPhone 6, I get like two more tableView rows to see 7 days worth of weather. I used Adaptive for it.

Hope that helps explain it.

Rob

That does help immensely  Thanks.

I’m still a little foggy on some aspects of positioning at different scales. I guess I’m thinking old-school integer pixel positioning and worrying that my coordinate resolution would default to the 1X resolution, but that shouldn’t be the case with decimal coordinates and a scaling layer between the two. I think some experimentation on my own is called for.  

Thanks again,

Byron

It’s really best if you try to avoid thinking in pixels. You have an X by Y grid of points to work with. Design your game to fit your grid. Lua doesn’t have integers. Everything is a float. Fractional .x and .y values are common place.

Rob

Yes, use percentages.

:slight_smile:

Please help me understand this.  If my retina version of the sheet is 500x50, and has 10 sprites of 50x50, and I have 2 png image sheets - 1 that is 500x50 (2X for Retina iPad - lets call it “ship@2x.png”) and 1 that is 250x25 (1X for regular ipad - “ship.png”) that when I go to load the sheet on EITHER ipad or ipad retina I would use the exact same line:

 spritesheet = graphics.newImageSheet( “ship.png”, {width=25, height=25, numFrames=10, sheetContentWidth=250, sheetContentHeight=25})

…and that the SDK will automatically adjust the image sheet name to ship@2x.png for the iPad retina (if I define it properly in my config.lua) and use ship.png automatically for ipad? correct?

Yes this is correct. Think of display.newImage() and display.newImageRect(). The key difference between the two is that display.newImage() loads the file name specified at the width and height of the actual image. You don’t set it. You may scale it later yourself. It does not know how to use @2x, @4x type images.  For display.newImageRect() you provide a filename and the 1x width and height to make the image (since we are working in content units). This variant will use the scaling information in config.lua to determine if the real device’s screen is close to the width and height in config.lua and then pull in the best matching graphic and load it at that size.

If your config.lua says you’re using a 320 point wide content area and you’ve defined your imageSuffix block to say load @2x images when the scale is 2.0, on a 640px wide screen you will get the @2x image. On a 639px screen (of course there aren’t any, but for logic sake) you will get the 1x image. For screens 640px to 1279px, your @2x image is used, and if you defined an @4x image, from 1280px and greater you would get the @4x image.

Sprite sheets are based on the logic behind display.newImageRect().  If your 1x image sheet is 250x25, then you would tell the graphics.newImageSheet that sheetContentWidth and sheetContentHeight are 250 and 25 like you have it. If we detect you’re on an @2x device, we will add the @2x suffix and try and load that image and let dynamic scaling work for you.

What confuses me further (assuming the above is essentially correct- and I don’t know that it is) is that I had planned to use adaptive scaling - so that presumably the stage content[width|height] is going to match the device’s display resolution.  So would the sprites for iPad Retina be 25x25 or 50x50?  I mean, I get that if I were using a fixed content scale for the application that the screen gets stretched and the coordinate system presumably is mapped for the display resolution.  But if you use adaptive scaling, then what should I expect when I go to provide offsets into the sprite’s local object space? a 50x50 area or a 25x25 area?  Is that entirely determined by the resolution of the 1x sprite?  thanks,

Byron

Adaptive scaling is a quirky concept to grasp. But let’s start with the TL;DR of it. You most likely should not use it for games.

Think of any game really… But lets use Clash of Clans. If you play it on a phone or a tablet, it’s basically the same. Controls are in the same position. (well some stuff may stretch to edges on a wider phone, closer together on a taller iPad)  It’s just stuff is bigger on the tablet.

Now consider a business app that’s using a bunch of switches, tableViews, etc. On an iPad, you don’t expect those tableView rows to double or triple in height, it would be nice if the tableView’s rows stayed the same, but you got more rows visible. Or the on/off switch is the same size if you hold your iPad and iPhone up together (well close). This is where Adaptive scaling comes in.

On an iPhone 4/5 you get a 320x width content area, on the iPhone 6 where there is more real estate  you get a 375x wide content area and on the iPhone 6 plus you get 414px wide. On the iPad’s you get 768x content points wide to play with. This gives you the flexibility to have your app look different on the different devices, rewarding the larger screen with more content.

So for Flappy Birds, this is not desirable. For ESPN Fantasy Football it is (or business/utility apps). I did a weather app for my wife. She has an iPhone 5, and can only get about 5 days of the extended forecast on her screen before she starts scrolling. On my iPhone 6, I get like two more tableView rows to see 7 days worth of weather. I used Adaptive for it.

Hope that helps explain it.

Rob

That does help immensely  Thanks.

I’m still a little foggy on some aspects of positioning at different scales. I guess I’m thinking old-school integer pixel positioning and worrying that my coordinate resolution would default to the 1X resolution, but that shouldn’t be the case with decimal coordinates and a scaling layer between the two. I think some experimentation on my own is called for.  

Thanks again,

Byron

It’s really best if you try to avoid thinking in pixels. You have an X by Y grid of points to work with. Design your game to fit your grid. Lua doesn’t have integers. Everything is a float. Fractional .x and .y values are common place.

Rob

Yes, use percentages.

:slight_smile: