The result of screen resolution cannot be passed beyond main.lua after the build is built.

After my picture book app is almost done, I got an idea to make a little more: to make the illustration/animation of each page to scale with the screen width of the device. I planed this to show entire composition of each illustration with animation in each page. Fortunately, I organized the illustration and animation in one display group. Here is the structure of my app:

8X9U39f.png

Somehow I made the content of my app as 960x 640, and scale = “zoomEven” in the year of 2017. Each illustration with animation is 640x 640, align on the top. For the idea of scaling illustration according to the device resolution, I wrote a deviceRatio() function in main.lua

----------------------------------------------------------------------------------------- -- -- main.lua -- ----------------------------------------------------------------------------------------- -- include the Corona "composer" module local composer = require("composer") -- hide the status bar display.setStatusBar( display.HiddenStatusBar ) display.setDefault("background", 1, 0.6823, 0.78823) -- light pink BG -- Removes bottom bar on Android https://docs.coronalabs.com/api/library/native/setProperty.html if system.getInfo( "androidApiLevel" ) and system.getInfo( "androidApiLevel" ) \< 19 then native.setProperty( "androidSystemUiVisibility", "lowProfile" ) else native.setProperty( "androidSystemUiVisibility", "immersiveSticky" ) end -- get resolution scaleFactor for illustration function deviceRatio() local ratio = display.pixelHeight/display.pixelWidth local scaleFactor if ratio \<=1.5 then scaleFactor = 1 elseif ratio == 1.6 then scaleFactor = 0.9375 elseif ratio == 1.666 then scaleFactor = 0.9 elseif ratio \>1.7 and ratio \<= 1.8 then scaleFactor = 0.846 elseif ratio \>2 then scaleFactor = 0.6927 end print("scaleFactor in main", scaleFactor) return scaleFactor end local scaleFactor = deviceRatio() composer.setVariable("scaleFactor", scaleFactor) print("scaleFactor in main II", scaleFactor) -- load title/cover screen composer.gotoScene( "coverPage", "fade", 300)

I get the scaleFactor and pass it to page01.lua to scale the display group which contains illustration and animation of each page. Everything worked perfectly on Corona Simulator as I switched among different resolution and devices. However, after I made a build and ran on my Android phone, it showed a Runtime Error right away when I touch the coverPage.

Runtime Error

C:\ …\picBookProject\page01.lua:200: bad argument#1 to ‘scale’ (number expected, got nil)

-- page01.lua -- ----------------------------------------------------------------------------------- local composer = require( "composer" ) local widget = require( "widget" ) local scene = composer.newScene() local pages = require("data") -- load the pages "module" of page information ... local backGroup -- add mainImage(illustration #.png) in, otherwise mainImage are keeping in front of buttons local mainGroup local animGroup -- one illustration with animation local uiGroup ... -- ----------------------------------------------------------------------------------- -- Scene event functions -- ----------------------------------------------------------------------------------- -- create() function scene:create( event ) local sceneGroup = self.view -- Code here runs when the scene is first created but has not yet appeared on screen -- Set up display groups backGroup = display.newGroup() sceneGroup:insert( backGroup ) local illuScale = composer.getVariable("scaleFactor") print("illuScale", illuScale) -- to confirm that I got the scaleFactor value local animGroup = pages[101].animGroup animGroup.anchorChildren = true animGroup.anchorX = 0 animGroup.anchorY = 0 animGroup:scale(illuScale, illuScale) animGroup.x = display.screenOriginX animGroup.y = display.screenOriginY sceneGroup:insert(animGroup) mainGroup = display.newGroup() sceneGroup:insert( mainGroup ) uiGroup = display.newGroup() sceneGroup:insert( uiGroup ) ...

I have been thinking maybe I should put the deviceRatio function in config.lua. However, if doing so, I cannot pass the scaleFactor to the other lua with composer.setVariable()  and composer.getVariable.

Any idea why the scaleFactor could be passed in Corona Simulator, but not on build ? What should I do? 

Thank you in advance. :slight_smile:
 

** UPDATE ** I misread this.  You want to have this behavior ONLY in the simulator…
 
If you have SSKin your project, you can just do this:
(https://github.com/roaminggamer/SSK2)
 

local scaleFactor = onSimulator and 1 or deviceRatio() -- in main.lua

Then you can still use scaleFactor, but have it default to a known value when not running the simulator.

If you don’t want to use SSK, you can just detect you’re on the simulator like this:

local platformEnvironment = system.getInfo("environment") \_G.onSimulator = platformEnvironment == "simulator"

Your problem is your scaleFactor calculation as it only calculates a value at all for some display sizes. In your case, your Android devices has a resolution that does not result in a calculated value thus the variable is never set to a number in your main.lua and that’s why you get the nil error in page01.lua.

[lua]

local ratio = display.pixelHeight/display.pixelWidth

local scaleFactor

if ratio <=1.5 then scaleFactor = 1

    elseif ratio == 1.6 then scaleFactor = 0.9375

    elseif ratio == 1.666 then scaleFactor = 0.9

    elseif ratio >1.7 and ratio <= 1.8 then scaleFactor = 0.846

    elseif ratio >2 then scaleFactor = 0.6927

end

[/lua]

You can check the if/elseifs for what I mean.

You don’t calculate the scaleFactor at all for the following ratio values

> 1.5 and < 1.6

> 1.6 and < 1.666

> 1.666 and <= 1.7

> 1.8 and <= 2

Here’s a function to calculate the correct scale value that guarantees to have a given rect (width, height) visible within a defined other area (otherWidth, otherHeight)

[lua]

– put this somewhere in your main

local function calcScale( width, height, otherWidth, otherHeight )

    local newWidth = width * (otherHeight/height)

    local newHeight = height * (otherWidth/width)

    if newWidth > otherWidth then

        return otherWidth/width

    else

        return otherHeight/height

    end

end

– and calc your scale factor like so

local scaleFactor = calcScale( 640, 640, display.pixelWidth, display.pixelHeight )

[/lua]

Depending on the scale settings in config.lua and the result you want you may need to use the contentWidth and contentHeight or the actualContentWidth and actualContentHeight values from the display objects instead of pixelWidth and pixelHeight.

Michael Flad’s approach is precisely the way to go.

Constructing lengthy conditional statements gets difficulty to manage after a while and you’ll run into issues if there is an outlier that doesn’t meet with the predetermined criteria. Having a single universal solution is both easier to manage and less prone to bugs.

Hi all, thank you for all your reply. I am glad I level up my coding of function again. However, I am still digesting Michael Flad’s code.

I put the code in and built a build, it worked. However, the scaleFactor changes from 0.846 to 1.6875 when Simulator view as 1080x1920. So far only Viewing as 640x960 is correct (scaleFactor =1). I am trying to figure out what’s wrong.

By the way, I think the resolution of my Sony Xperia XZ Premium is 2160x3840 (1.77777) according to the screenshot image which is taking by default device screen capture button. I wonder if this means pixelWidth = 2160 and pixelHeight = 3840 ? Does using screenshot to verify the device resolution is correct? :huh:

@roaminggamer
No no no. I was a little ambitious. :lol:  Not only on Corona Simulator. I wish to fit most devices. Kinda like making RWD for device. I will check out your SSK. I have known of your SSK for a while when google question around. But most of time I don’t understand the code, maybe because I haven’t got that level yet.

@Michael Flad
Thank you for your code. I am still digesting it.

When I tired to observe if any way to achieve my idea, I arranged this diagram.
BPbdNQv.png
Then I use the following code to observe my situation.
 

print("display.topStatusBarContentHeight", display.topStatusBarContentHeight) print("display.contentScaleX", display.contentScaleX) print("display.contentScaleY", display.contentScaleY) print("display.pixelWidth", display.pixelWidth ) print("display.pixelHeight", display.pixelHeight ) print("aspact ratio", display.pixelHeight / display.pixelWidth) print("for Dynamic Image Selection", display.pixelWidth / display.actualContentWidth ) -- suggested by Dynamic Image Selection print(" -------------- ") print("display.contentWidth", display.contentWidth) print("display.contentHeight", display.contentHeight) print("display.screenOriginY", display.screenOriginY) print("display.screenOriginX", display.screenOriginX) print("display.viewableContentWidth", display.viewableContentWidth, " if letterbox, no pillar area") print("display.viewableContentHeight", display.viewableContentHeight) print("display.actualContentWidth", display.actualContentWidth ) -- if letterbox scale, returns the content width, including the letterbox area. -- if zoomEven scale, = display.viewableContentWidth property. print("display.actualContentHeight", display.actualContentHeight ) -- if letterbox scale, returns the content height, including the letterbox area. -- if zoomEven scale, = the display.viewableContentHeight property. print("aspact ratio", display.actualContentHeight / display.actualContentWidth)

And then, I have to use pixelWidth and pixelHeight, otherwise I will get pillar bars when viewing as 4:3 (1.3333…) device.

Finally, I did some calculation… (I wish I used 16:9 instead of 4:3 since it seemed rare to meet 4:3 device )
U2Fu4qw.jpg

Actually, when I made the composition of illustration, I did consider that left and right sides were cropped when it’s 16:9 (1.7777). Now if I don’t want them to be cropped, I can just use scaleFactor = 0.846 to make 640x640 to shrink the display group and fit it all in 1080x1920 (1.7777) device, and ignoring the other resolution. However, I just think it’s almost there… to make RWD on our favorite Corona~~~

Maybe in the future, starting our project with letterbox and 16:9, instead of 4:3, is better? :ph34r:
 

 

Designing for 16:9 letterbox is a good place to start… you can then fill the blanks for tall/wide devices.

It is advisable to constrain a single dimension (normally height for portrait) in config.lua.  Pick a static height and calculate the width.

For example,

&nbsp; &nbsp; &nbsp; &nbsp; width = 960, &nbsp; &nbsp; &nbsp; &nbsp; height = math.floor(960 \* display.pixelHeight/display.pixelWidth),

Then you do not have to worry too much about scaling.

Hi all,

After I asked a friend coder about the logic of Michael Flad’s solution, I understood it! Then I was trying to focus on fixing the scale issue. After I figured out why the scale was wrong, I found that, originally, in the very beginning, I just wanted to make the animation displayGroup.width = display.actualContentWidth. However,  since displayGroup is a special type of display object, I cannot assign its width this way. Therefore I was trying to change its size with object:scale(), and started looking for the “scaleFactor”. Eventually, it has gone too far.

Now I just need one line:

local scaleFactor = display.actualContentWidth/640

This 640 should be the content width I set in config.lua, I think. or maybe I should use

local scaleFactor = display.actualContentWidth/display.contentWidth

Now it’s all set!!! The burned build also works, although I only have two Sony mobile devices to test :stuck_out_tongue:

Still thank you for all your time and reply. Thank you very very much! <(_ _)>