iPhone 4 problem!

How come for me, when i run in the simulator using a regular iphone the app looks perfect, but on iphone 4 everything is squished into the top left corner of the device. How can I stretch the app to look on on the iphone 4 also using the old coordinate system (since new version of corona only builds with 4.0 compatibility on iphone). This is the error I get when I try to use the sample build.settings used here that seemed to work for others.

This error happens both with an EMPTY build.settings file or the one i placed below

PANIC: unprotected error in call to Lua API (attempt to index a nil value)
logout

my build.settings

application = { content = { width = 320, height = 480, scale = "zoomEven", }, } [import]uid: 6317 topic_id: 1361 reply_id: 7049[/import]

Try putting the code in config.lua (not build.settings). You’re confusing the Corona simulator :slight_smile:

-Tom [import]uid: 7559 topic_id: 1361 reply_id: 7051[/import]

Hm, as a complete Corona beginner, the scaling stuff discussion here is quite confusing :frowning:
What I would like is to provide only ONE set of graphics - in high resolution - (targetting iPhone 4 as default) which will all be scaled down by Corona automatically on a iPhone 3. I really would not want to include two complete sets of graphics in my binary since this would have a big impact on the file size. In my opinion, providing a high res set only and let it scale down automatically provides better visual quality than providing a low res set and let it scale up, doesn’t it?

So to proof if I understood this correctly:

I can achieve this by saving a single set of images in high resolution to my project folder and using a config.lua as shown below. This will then scale down all my graphics to a smaller resolution if the game is running on a iPhone3, right?

application =  
{  
 content =  
 {  
 width = 640,  
 height = 960,  
 scale = "zoomEven",  
 },  
}  

So, to break it down:

  • I will design all my images in high res (targetting the iPhone 4 resolution)
  • Specifiy the base resolution in my config.lua (640 x 960)
  • Then I use the 640 x 960 coordinate system within my game code
  • Corona does all the rest (scaling down on iPhone 3 etc.)
  • And if I would like to EXCLUDE certain images from automatic scaling, I use the “@” naming convention. Those images are then NOT scaled, but loaded from a different file instead, without scaling.

Is this correct so far? [import]uid: 9644 topic_id: 1361 reply_id: 7168[/import]

The scaling modes are used to scale up, not scale down. If you specify 620 x 960 in config.lua, it will not work on a 320 x 480 iphone.

If you want to target iphone4 and iphone3, you need to provide two sets of graphics if you want the high resolution graphics on the iphone4. Not all your graphics need to be high resolution – only the ones that need the higher resolution images. The graphics made for the 320x480 format will scale up on the iPhone4.

If you want to target both platforms, you need to work in a 320x480 coordinate system.

-Tom [import]uid: 7559 topic_id: 1361 reply_id: 7181[/import]

Between the documentation and this thread, I think the whole “how to” process got a little messy, so I created a 3-step tutorial and posted it to CoronaSDK.com.

–> http://ideveloper.kodingen.com/2010/retina-display-setup-in-3-easy-steps/

Hopefully that will help newcomers to this thread :slight_smile: [import]uid: 7849 topic_id: 1361 reply_id: 7297[/import]

Jonathan,

Thanks for posting the detailed information and I’m sure it will be more helpful than trying to read this thread.

One correction I would like to make is to a statement you made in Step 2: “Obviously the width and height should be switched if your app uses landscape orientation.”

The wide and height values specified in config.lua is the size of the screen your app was designed for. These values are always specified in portrait mode – even if your app runs in landscape mode.

We are working hard to improve our own documentation and to provide better examples for all our APIs.

Thanks again for the great write-up.

-Tom [import]uid: 7559 topic_id: 1361 reply_id: 7298[/import]

@Tom: That’s news to me! Lol … I’ll go fix the post. [import]uid: 7849 topic_id: 1361 reply_id: 7299[/import]

Thanks for the tutorial, jonbeebe, this was exactly what I was looking for! :slight_smile:

However, I hope that upcoming versions of Corona will support this by default (without changing any libs).

  • One question regarding the changed libs: is this kind of a temporary “hack” or an official solution? Will my code also work in future Corona releases then or will I have to change it again when upgrading?

[import]uid: 9644 topic_id: 1361 reply_id: 7309[/import]

Unfortunately it’s a temporary “hack” (changes to movieclip, ui, etc). When you upgrade your version of Corona, you should still have the same ui.lua and movieclip.lua file in your project folder.

If Ansca were to give us new ui.lua and movieclip.lua files, then I’m sure they would include the changes since retina display is here to stay, so I wouldn’t worry about that too much–it would be in the release notes. [import]uid: 7849 topic_id: 1361 reply_id: 7313[/import]

I added the library support in future Corona DMGs as feature request #1448 (internal).

Thanks,
-Tom [import]uid: 7559 topic_id: 1361 reply_id: 7405[/import]

@evank

Regarding post 38, do you have any news on Dynamic SpriteSheet Resolution?

See here how TexturePacker is ready to accommodate such a feature, without breaking the coordinates.

Read here and the comments here about confusion on how to implement this functionality.

Personally, I was surprised to find out that when talking about “resolution independence”, you only take into account simple images. On the other hand, you promote spritesheets as the preferred way to work with visual assets in Corona (as you should do) and you use this format as a major selling point for “Game Edition”.

But, how should someone use SpriteSheets for a game if resolution independence is not provided? Is there any way to detect the device, the app is running on, to manually dictate the loading of the appropriate spritesheet png?
Really worried about what else I am missing… [import]uid: 7356 topic_id: 1361 reply_id: 10484[/import]

I learned a lot reading this thread. I wish I could have found some of this information in the official docs.

Specifically, I didn’t know that dynamic content scaling only works in one direction, up. If I want to develop for iphone 3 AND 4 it seems I MUST use the iPhone 3 resolution as the base coordinate system, rather than iPhone 4 (which is what I would prefer.)

And, as Magenda points out above, Spritesheets really need to work with Dynamic Resolution. These are two of the key benefits to developing games using Corona, but it they don’t work together the benefits are muted.

I’m still unclear the best way to proceed. Simply, I’m trying to make a game that works on both iPhone 3 and iPhone 4, uses higher res. graphics on iPhone 4, and makes use of spritesheets on both platforms using a single code base. Is this possible now using Corona?

[import]uid: 9422 topic_id: 1361 reply_id: 10514[/import]

@XenonBL - actually, dynamic content scaling DOES work in both the up and down directions (I’ll explain below why it doesn’t seem that way).

To see an example of dynamic content scaling using a large content size and then DOWNscaling to smaller screens, check out the “SimplePool” sample project. Its config.lua file establishes the iPad as the base content size for the app:

application =   
{  
 content =   
 {   
 width = 768,  
 height = 1024,   
 scale = "letterbox"  
 }  
}  

…but then the game downscales nicely to iPhone3, iPhone4, Droid, Nexus One, etc.

However, here’s the potential gotcha: there is a Corona “safety feature” that autoscales larger images by default – this is discussed in the documentation for the display.newImage() API:

http://developer.anscamobile.com/content/display-objects#Image_Autoscaling

Specifically, the “safety feature” scales all images down to the next power-of-2 in each dimension, relative to the native screen size of the current hardware. So, for example, on iPhone3, all large images will be downscaled to no larger than 512 x 512.

Normally, this is harmless, and actually helpful, since it prevents users from accidentally blowing up all their graphics memory by loading a single large camera image. However, if you’re trying to globally scale your entire project DOWN from iPad or iPhone4 to iPhone3, then you’ll find that you’re tripping the safety feature on iPhone3 by accident, since all large assets will be bigger than 512 x 512.

The fix is easy: just add the optional “true” parameter when loading large images, since this overrides the safety feature. In SimplePool, for example, you can see it in use here:

local tabletop = display.newImage( "table\_bkg.png", true )  
 -- "true" overrides Corona's downsizing of large images on smaller devices  

In other words, you should be able to do what you want: size everything for iPhone4, and then globally scale the app down to iPhone3.

One caveat, though: remember that iPhone3 (pre-3GS) only has half as much texture memory as iPhone4 – roughly 10MB vs 20MB – so it is literally not possible to fully use the 20MB graphics memory of the iPhone4 AND still target the iPhone3. You’ll need to keep that in mind, and watch your texture memory consumption to make sure the app still works on your lowest-common-denominator device targets.

To see how much texture memory is currently being used by your app, you can check the parameter named “textureMemoryUsed” in the system.getInfo() function, as documented here:

http://developer.anscamobile.com/content/system-os

[import]uid: 3007 topic_id: 1361 reply_id: 10520[/import]

@Magenda - you can get a LOT of information about the current device and platform using the system.getInfo() API:

https://developer.anscamobile.com/content/system-os

I agree that transparently uniting dynamic image resolution and sprite would be great, but there are a couple of background issues. First of all, there are very few possible dimensions for sprite sheets, and the maximum is either 1024 x 1024 or 2048 x 2048, depending on hardware and GPU. (The former case is more common, the latter case is iPhone4, iPad and not much else.)

It does seem like there would be a nice “2x” solution by automatically exporting a sprite sheet at 1024 and 2048 size from the sprite sheet authoring tools, but the other subtle factor is that a sprite-sheet construction tool will “pad” the separate images by an extra pixel or two, for certain technical reasons. This means that it cannot be guaranteed that the layout of the sheet will be the same for the 1024 and 2048 cases, at least some of the time.

In short, there is a way to do it, and it’s a good idea, but it’s a more complex implementation than images in general, and there will always be hard limits imposed by the limits of mobile hardware itself. [import]uid: 3007 topic_id: 1361 reply_id: 10523[/import]

@evank Thanks for the explanation. What about the spritesheets. Is there a workaround to implement them?
@jonbeebe Thanks for the tutorial. Awesome as usual. [import]uid: 8192 topic_id: 1361 reply_id: 10524[/import]

@evank / @AnscaTeam

Honestly, I don’t get it…

Firstly, system.getInfo() doesn’t help since it doesn’t provide the device resolution and the OS version is not mutual exclusive with specific resolutions (ios4 runs on both ip3 and ip4).

What scenario we need:

Step 1:
We save a spritesheet of 2048*2048 as “spritesheet.png” and then resize it with TexturePacker or whatever also to 1024*1024 as “spritesheet@ip3.png”. The base dimension could be 1024*1024 and the second 512*512, or anything valid (TexturePacker automatically finds valid dimensions).
With TexturePacker we get these two spritesheets, each one with a different lua file. Everything is done automatically. No “pads”, no bugs, no caveats… not messing around with coordinates or other things, not powers of 2 or 3. TexturePacker gives a valid dimension with the sprites registered absolutely right in the lua file for the new layout. Just don’t bother with this side of technicalities.
We leave from this step with two valid spritesheet pngs and two valid lua coordinate-files…

Step 2:
Inside both of these two spritesheets, we have, among others, a sprite called “hero”. From our code, we load “spritesheet.png” to extract the “hero” sprite. When Corona is about to read the “spritesheet.png” you want to get the resolution of the device (or what else helps you internally) and depending on whether the app is running on ip4 or ip3 to decide if “spritesheet.png” or “spritesheet@ip3.png” is going to be loaded. The accompanying “spritesheet.lua” or “spritesheet@ip3.lua” file will give the right coordinates.

Why this is not possible? Corona is involved only in step 2, and you already have done relevant work for simple images. I don’t see any technical barriers here. If technical barriers existed, how Cocos2d has managed to do this? [import]uid: 7356 topic_id: 1361 reply_id: 10532[/import]

@evank, thanks for the information. I’m still trying to wrap my head around all this and perhaps I’m making it more complicated than it actually is. Are you saying that if I develop natively for iPhone 4, including using spritesheets, that my game will “just work” on iPhone 3 (as long as I don’t go over the 10 mb texture memory limit of iPhone 3 and override the safety feature of Corona)? Or is there still an issue around spritesheets not translating correctly?

[import]uid: 9422 topic_id: 1361 reply_id: 10536[/import]

@XenonBL - The answer is “yes, it should just work”. It’s all OpenGL hardware scaling in the end, so you can freely scale the entire app up or down with no performance loss. This is why hardware acceleration is really nice!

The complexity only comes in if you want to selectively swap in different assets on iPhone3 and iPhone4, which is what Magenda is talking about (see my next response). [import]uid: 3007 topic_id: 1361 reply_id: 10548[/import]

@Magenda - we’re ultimately doing the same things as in that cocos2d discussion, but we’re really trying to avoid using Apple’s “points vs. pixels” vocabulary, for two reasons: it seems to confuse people, and it only works well in the special case where one device is exactly 2x the dimensions of the other device. Because Corona needs to handle many different iOS and Android screens, with different shapes and sizes, the “points” integer multiplier doesn’t really help. Therefore, we came up with the notion of a base content size in config.lua (somewhat similar to “stage size” in Flash) and various ways to globally scale that content up or down.

To answer your question: yes, what you describe should work. You can detect the device, and then selectively load the assets you want. I was thinking more about future ways of handling everything transparently without making you build the assets twice.

How to detect the device? For starters, I just noticed that our system.getInfo() documentation seems to be wrong: I think we reversed the definitions of “name” and “model”, so I just fixed that in our online docs.

The next problem is that Apple seems to like NOT allowing specific model detection. I just built a test project on my iPhone 4, and the value returned for system.getInfo( “model” ) is simply “iPhone”. Evidently this is a standard problem, and the standard workaround is to test the points/pixels ratio in the OS and infer the Retina display from that (2=Retina, 1=not Retina).

Therefore, the fix that will ultimately help you isn’t in the code you have, but it’s in our codebase and will be released shortly. We are going to let you test the scaling factor between the base content size and the hardware screen size, which will not only return a “2” in the above Retina Display case, but will also return useful intermediate values on Android, iPad, and other screens that are not exact multiples. So you can use that as your iPhone 4 detector. The API looks like this:

scaleX = display.contentScaleX  
scaleY = display.contentScaleY  

(Note that these will generally return the same value, except in “zoomStretch” scaling modes.) [import]uid: 3007 topic_id: 1361 reply_id: 10549[/import]

@evank

Thanks for your answer, I am looking forward to the next release.

Some additional questions:

  1. Supposing we have a way to detect the device (ip3/ip4/ipad), how is this “manual-spritesheet-loading” going to work cooperatively with the settings in config.lua? What would be the resolution there? Depending on the resolution, the whole objects-layout changes. Isn’t this a dead-end ?
    It seems to me that setting the content area from an “external” file, that you can’t modify from within the app-code, may be good for dynamic scaling but not viable for programmatically loading assets depending on the device. Am I missing anything here?

  2. If we manage to manually load spritesheets depending on the device, is everything else ready for building a “Universal” app, accepted as such in AppStore and working perfectly in ip3+ip4+ipad from the same build? Is there any other known issues to be solved for building “Universal” builds?

[import]uid: 7356 topic_id: 1361 reply_id: 10812[/import]