Scaling algorithm madness

oripessach

  • *
  • Posts: 259
I posted this a couple of days ago to the Help Desk forum, and got no response. Reposting here in case someone is having the same issue.

And seriously, having a forum named Help Desk where no help is ever given is a bit silly. But never mind that - on to the bugs:

Hi,

I'm working on a game that needs to have a full screen display (no letterboxing) on mobile phones, and I'm doing that by having a wide display that's designed to have all the action near the center, and by positioning on-screen controls dynamically by accessing engine.root.x and doing some math. This works on every iOS device I tested with (in the simulator) except the 3.5" iPhone 4/4s, where I get black bars above and below the active area of the display.

I've done some digging, and I was surprised to find out that the Scale to Fit algorithms are reversed based on the screen's aspect ratio, which I haven't seen documented anywhere. I set my scaling algorithm to StF (Letterbox) even though it does the exact opposite of what the documentation says it would, because I found out that in most cases it did the right thing. Imagine my surprise when I found that Letterbox gets switched to Fill when the aspect ratio is above 1.5!

In my case, changing the line:

Code: [Select]
widescreen = aspectRatio > 1.5;
to:

Code: [Select]
widescreen = aspectRatio >= 1.5;
Fixed my problem, but I find this behavior puzzling and arbitrary. The fact that it isn't documented makes it worse.  I suspect that what was really meant there was:

Code: [Select]
widescreen = aspectRatio > 1.0;
Which even works for me on an iPad.

So, what's going on here? The way the code is written simply doesn't work for my game, and seems broken.

Further, what is the reason for reversing the scaling algorithms' behaviors like that?



rob1221

  • *
  • Posts: 9430
I looked at Universal.hx and found this:
Quote
         //Scale to fit algorithms reverse on widescreen setups.
         if(widescreen)
         {
            if(MyAssets.scaleToFit1)
            {
               MyAssets.scaleToFit1 = false;
               MyAssets.scaleToFit2 = true;
            }
            
            else if(MyAssets.scaleToFit2)
            {
               MyAssets.scaleToFit1 = true;
               MyAssets.scaleToFit2 = false;
            }
            
            trace("Widescreen (Aspect Ratio > 1.5)");
         }

It is intentional and therefore not a bug, but I have no idea why the algorithms reverse.

EDIT: Regardless of whether the scaling modes are changed, you should not use any letterboxing on iOS devices.

« Last Edit: August 04, 2015, 09:28:40 am by rob1221 »

oripessach

  • *
  • Posts: 259
The bug is that the code makes an arbitrary distinction between the aspect ratios on an iPhone 4 and an iPhone 5, reversing the algorithm in one case but not the other, essentially making the choice of algorithm meaningless.

My whole point is that I was trying to avoid letterboxing, but the code as written right now makes that impossible.

Also, the current implementation seems to arbitrarily change the user's choice of scaling algorithm based on undocumented and confusing criteria. Even if someone did that on purpose, it's still a bug. You can't tell people to try different scaling algorithms to see whether they work for their game, and then change their selection.

rob1221

  • *
  • Posts: 9430
Yeah I understand that switching to letterbox from a non-letterbox mode is a problem for iOS.  For now just use the code modification that you already mentioned earlier, assuming it doesn't break anything else.  I can make changes to Stencyl's engine, but I'm not messing with someone else's code when I don't even know the reason for it in the first place.

oripessach

  • *
  • Posts: 259
I'm fine with that, as long as you promise me to find someone who knows why this was done and ask them. :)

rob1221

  • *
  • Posts: 9430
I found the date the code was added which was about 2 years ago and by Jon.  I searched for a forum post talking about the part but I didn't find one.

oripessach

  • *
  • Posts: 259
It might be a good time to revisit the decision to do this, no?

rob1221

  • *
  • Posts: 9430
Yeah.  I'll try to get Jon's attention on this issue.

oripessach

  • *
  • Posts: 259
Thanks. I really do appreciate you looking into this issue.

rob1221

  • *
  • Posts: 9430
The scaling mode swapping is intentional, but it was only made to work with the standard 480x320, which is where the 1.5 number comes from.  Try changing that line to this instead and see if it solves the problem for you:
Code: [Select]
widescreen = aspectRatio > (Math.max(MyAssets.stageWidth, MyAssets.stageHeight) / Math.min(MyAssets.stageWidth, MyAssets.stageHeight));


oripessach

  • *
  • Posts: 259
Sorry - I was busy getting married. I'll try this tonight.

oripessach

  • *
  • Posts: 259
This seems to work fine.

I just tried it, and with this change I can select the desired scaling algorithm, and the game ends up using that in all screen resolutions on iOS (I tested all of them just now.) So it solves my problem, at least.

As for the bigger picture, let me see if I understand the intent of the code correctly: It tries to change the scaling algorithm from Scale to Fit (Fill) to Scale to Fit (Letterbox) and vice versa if the device's screen's aspect ratio is larger than the game's aspect ratio? Why, and how is this useful? Can you walk me through an example showing why this is needed?

Thanks!