Adaptive, display content, positioning question

This is not correct.  You can scale sprites to get any ‘size’ that you want.

You cannot reset the config after it’s loaded. You should not (and cannot for desktop apps) do operations in config.lua*. We even discourage using zoomStretch because it has the potential to seriously distort the screen. I know another Corona developer is trying to do this, but I’ve never seen other apps offer such a setting.

* Many people do compute the aspect ratio in config.lua and dynamically adjust the width and height to make the content area fit the screen. There are pros and cons to this method, but more importantly it doesn’t work for desktop builds and is taking advantage of an a feature that just happens to work and could change in the future.

Without knowing what you’re trying to do, it’s hard to advise what the best course of action for you. I’m going to be updating one of my games in the App Store today and it uses a computed config.lua, but it’s a game that works well for. The new game I’m working on, a computed config.lua would be a really bad idea because it would affect game play.

For many developers, what config.lua does and how Corona adapts that to various screens may seem like hard to understand magic, but it’s really not.

What config.lua does is define an invisible rectangle on the screen. By default that rectangle gets centered, but you can move it around depending on what you want to accomplish.  Most people make that rectangle a 1:1.5 (2:3) aspect ratio, meaning that it’s 1.5x longer than it is wide (I’ll do all of this for portrait apps since you always specify portrait dimensions in config.lua).  If you set your width to 320 in config.lua, your 1.5x height would be 480.  Depending on your screen you may have extra space on either side of the box while the opposite side should be flush to those edges.  If you’re on a phone, or TV (or full screen desktop) you’re likely going to have more space on the top and bottom of the box. If you’re on an iPad or other more square tablets, that extra space will be on the sides.

What frustrates many is that 0, 0 isn’t the top, left of the screen and display.contentWidth, display.contentHeight is no longer the right, bottom.  

There are a couple of solutions to this and it depends on the type of game/app you’re making. If distance between objects **will not** affect game play (such as my trivia game), you could shift the virtual screen box to be aligned to the top, left, which would make 0, 0, the top left and then don’t use display.contentWidth, display.contentHeight, but instead use display.actualContentWidth, display.actualContentHeight and you now have the same effect as computing the aspect ratio.

If your game is one where distance between objects matters, think angry birds and the distance between the slingshot and the pigs, or in my new game where the distance between my player’s ship and the enemies appearing on the screen would make the game easier on a phone if the space is stretched out and harder on an iPad when they start closer together, this type of config is bad. 

In this case, when you need to reference the bottom, right,  you can still use display.actualContentHeight, display.actualContentWidth, but you need to add display.contentOriginX, display.contentOriginY to anything you’re positioning around the edges of the screen. You can start your sling shot at X pixels and put the pigs near display.contentWidth.  Then depending on  your device that extra space just becomes extra background and doesn’t factor into game play. But you can position your UI elements using the display.contentOriginX, Y values.

The trick is to make sure you background is big enough to work on all screens, which means part of it will most likely be off screen depending on the device. Don’t build UI chrome into the background since you need to move that stuff around.

Rob

If I was to do a desktop or iTV/AmazonTV build, it is looking like I would most likely split my code base into two builds specifically for this. Especially if I am not to do 

My game is a pixel game.  Meaning I render my assets small, and scale them x2. With a pixel game, having pixels align properly is one of the most important aspects of having a pixel game.  A pixel game is a popular method of making 2D games.

 that just happens to work and could change in the future.

I understand that a lot of people in the Corona community, especially the Corona engineers, have really expressed that they do not create many pixel graphic games with finite borders.  When I mention a Pixel on my screen, I realize it is not literally a ‘pixel’ on the screen. It is a collection of pixels made to represent the scaled ‘pixel’. So unless the aspect ratio meets 1:1 on my game will never match exactly with zoomstretch. It will be elongated in y slightly for most devices. I typically can compensate for this with making my graphics slightly elongated in X and the affect is not that bad.

My game has taken years to make for a variety of reasons (outside of working on it) and there is no ‘just dont make it like that’ option at this point. I literally have thousands of users waiting on my game.   

Without knowing what you’re trying to do, it’s hard to advise what the best course of action for you

You can go here to see screenshots and gifs of my game in action, this should give you a clearer understanding of what I am doing. My game does not have floating graphics ui for obvious reasons. Having control of the borders of my game IS the primary importance of a pixel game of my style.

Currently both methods seem to work fine for my game, while the zoomStretch, seems to work the best but letterbox does seem to be workable as well. As long as I avoid many round circles filling the entire screen with my pixel game zoomstretch seems to work the best for now. 

One good thing about my game is that I have moved all UI coordinates into tables. So I can easily(relatively) set configurations of X,Y coordinates for letterbox if I was to make a desktop version. In doing this I have found that it can also ‘work’ for phones with that 2:1 aspect ratio, although I end up with very large blank areas of letterbox that are more extreme in the portrait mode for a game like this.

While I have developed my game to be adaptable to letterbox, I really hope it is not in the plan to get rid of zoomstretch for Corona because ‘most’ developers do not use it. It would severely affect my business in the long run.

I’ve not heard any talk about removing “zoomStretch”. 

wacky stuff fwiw, i’ll likely “take heat” for even mentioning this, but it is possible.  (i’m also not suggesting it’s recommended, because it isn’t easy or intuitive, and corona support would likely just shrug you off if they knew you were doing this)

you can recreate for yourself any of the scale modes by omitting content dimensions from config.lua – you’ll then be using device dimensions… at least initially.  now size and position the stage however you wish to accomplish an equivalent scaling to having set content dimensions in config.lua.

for example, first calc x/y scales:

local xscale = desiredContentWidth / device.pixelWidth local yscale = desiredContentHeight / device.pixelHeight

then figure out how you’ll use them based scale method:

if (desiredScaleMethod == "zoomStretch") then -- nop, use x/y scales as is, anamorphic elseif (desiredScaleMethod == "letterbox") then -- fit longer axis, letterbox shorter axis xscale = math.max(xscale, yscale) yscale = xscale elseif (desiredScaleMethod == "zoomEven") then -- fit shorter axis, bleed longer axis xscale = math.min(xscale, yscale) yscale = xscale end

then adjust the stage to match

local stage = display.getCurrentStage() stage.width, stage.height = desiredContentWidth, desiredContentHeight -- corona's notion of content scale is backwards to what is needed here stage.xScale, stage.yScale = 1.0/xscale, 1.0/yscale

…et cetera, because there’s more work to do, like figuring out how you want to center the stage on the device (and what your resulting origins will be) or calcing for convenience the resulting equivalents to viewable/actual contentWidth/Height.  but all of that is just a bit of basic math, and you can even stuff those derived values back into display.* if you wish to make it backwards compatible. (just don’t mess with pixelWidth/Height).

you’ll also need to monitor resize/orient events and do whatever dynamic recalc in response to those events, since you’d no longer be relying on corona to do it for you.

but finally, once all is working, you can dynamically set any scale mode or content dimensions that you please at runtime.

i can imagine what your setup looks like:  specify minimum aspect ratio content (4:3, as per your 768x1024), internally capable of bleeding out horizontally to maximum aspect ratio device (which was formerly ~16:9).  now with 2:1 aspect ratio S8 you are faced with too much horizontal bleed once scaled to fit vertically.  (all of above using portrait orientation terms).  sound about right?

so the crux of the problem was assuming that no-one would ever invent a > 16:9 aspect device.  (similarly, some other dev’s config.lua might someday fail with assumptions that no-one will ever invent a < 4:3 aspect device)

if i’ve got that right, then you have two primary options (assuming that your preference is to leave everything else alone to the extent possible, and just “patch” for S8 support):

make your config.lua conditional, calc device aspect ratio and set different width/height based on it.  leave everything else alone unless/until aspect ratio exceeds 1.667, then do something “different” that only affects S8

(or settle for non-square pixels and use zoomStretch on S8 with 16:9 content dimensions, ie “cap” your content aspect ratio to 16:9 and anamorphically stretch it, it’ll then “act like” a 16:9 device but display 2:1 with non-square pixels)

leave config.lua alone, but make your app’s layout code conditional, in same way - again via device aspect ratio, squashing things in as necessary horizontally when aspect ratio exceeds 1.667

Adaptive is great for business apps where you want more real estate on tablets than you have on phones and plan to have different UI layouts. But for games, you generally want to keep the same basic screen albeit a different shape. 

You may need to just make your backgrounds big enough to fit the extra space the S8 gives you.

Rob

Hi @dodi_games,

Apparently the “excessively tall” screen size of the S8 is proving to be a nightmare for app developers across all platforms. It’s simply “too tall” to accomodate UI designs that almost everybody designs for. Personally, I’m hoping that Apple and others don’t follow this trend.

Anyway, with “adaptive” mode, it’s often better to position/size things based on screen “percentage” instead of strict X and Y values (except for things that align to screen edges, for positioning, which of course can be predictable values). This is because adaptive will adjust the content area size automatically, so if you position something at like “.x=50” then 50 on one device will vary quite a bit from 50 on another device.

There are other things to note, all of which are outlined in this guide:

https://docs.coronalabs.com/guide/system/adaptiveScale/index.html

Brent

Thanks to everyone for your replies. I hope the trend of devices with strange content area ends.

@Brent I will read and practice with new projects before changing an entire App to Adaptive, is a challenge for me. I will be updating here if I find some novelty that can help other people.

I am going to ask my basic doubts about positioning objects using “adaptive” in this topic to avoid the creation of multiple topics with the same central idea.

Reading “Adaptive Scaling (Resolution Independence)” I understand that in order to position an object down the screen I need to use “display.contentHeight” (_H), and if I want to position it up I guess it is _H / _H, but this only locates the vertical center of the object which causes only half of my image to be seen on screen. Is there any way to calculate that vertical center to subtract it from _H / _H (top)? Before I am forced to create an image of twice the size leaving half of it blank so when the image is located above with its vertical center is full on the screen.

Thanks in advance

_H / _H results in 1. I don’t think that’s what you want.  _H / 2 or _H * 0.5 (somewhat more efficient) would compute the center point between 0 and _H. Personally I would out of habit use display.actualContentHeight though for “adaptive” they are likely the same.

Rob

to position an image with a specific bottom y coord, subtract half the image height, or set the anchor to bottom:

image.y = desiredBottomY - image.height/2 -- or: image.anchorY = 1.0 image.y = desiredBottomY

@all

All your answers were very useful and I managed to accommodate all the App menu display objects where I wanted. The only thing I can not adjust is the sprites. Try “object.scale ()” but it does not give me the result that I want (pretty bad blurry images when switching through devices in the simulator). I use sprites to make “ads banners”. The sprites are in “images sheets” and the sprites api does not allow me to change the size. The result is that for 320 x 480 use sprites of 240 x 45 (I use it as a guide to create my images, I know Adaptive does not use predefined content area) and it is good in the small devices but when I switch to ipad they stay at 240 x 45 and hardly see on the screen. Is there any way to work the sprites using adaptive?

Are you using dynamic image (sprite) selection? You should almost always do so, and “adaptive” is no exception.

Brent

@Brent

Yes, I have my default image, @2x and @3x sheet, I have also activated them in the config lua. The problem is to put it on the screen and adjust its size, I must use _W/(some value) and _H/(some value), but the sprite api does not allow to change its width and height, same when using an image sheet for the widget button. object:scale() is not a good solution because it would have to double its size so that it looks good on large devices but is off the screen on small devices. I think the problem is that the sprites can not be adjusted width and height because their value is given in the size that the image sheet was created.

Hi again,

So to be clear, you’d like to actually scale the sprite to a “consistent” size regardless of the content area size adaptive mode is picking?

In many cases (but I realize not all ), the main benefit of adaptive mode is to actually make things like UI buttons smaller on tablets than they are on phones, since there’s a larger screen area. Thus, when I use that mode, I don’t usually scale anything like graphics or sprites less/more than the size I designed them to be. Sure, there are exceptions (and you might have one) but that’s sort of a general approach which I take.

Take care,

Brent

@Brent
Thanks, I’ll study the concept carefully.

Holy Moley. This is a great post and something I had no idea about.

So it looks for right now, I am just going to continue doing what I have been doing, zoomStretch x2,blinear, “magTextureFilter”, "nearest, and sprites x2 to fit my Pixelated game on most screens without too much stretching. (I avoid circles so it’s not noticeable or ever complained about with my customers) 

However, this one presents a special case.  For now, my solution will be to set the GooglePlay Store to not download to Samsung Galaxy S8. 

But I wonder if there is another solution I could do later, such as detect if the device is 2:1 and then set my zoomStretch x2,blinear, “magTextureFilter” up differently for Samsung Galaxy S8 specific?   Advice?

@all

For the moment I applied a 512 pixels rule. I have noticed, in tests with s8 and s8+ devices, that after 512p for a content area of ​​768*1024 (zoomEven) I still have around 10-20 pixels between my content and the edge of the screen. I lose a lot of background, but at the moment it is not very important for the concept of application that I am creating.

@dodi_games,

On the actual devices I assume? Do you have both of these for testing or are users reporting this to you?

Brent