Sunday, July 20, 2014

HaxeFlixel scale modes: complete guide pt. 2: auto-zoom

Part 1: Zoom set to 1

When I started testing the various scale modes available in HaxeFlixel several days ago, I quickly found out that pretty much none of them work as I'd expect. Fortunately, it didn't take long for me to figure out, that it's caused by the automatic zoom calculation that's included in the template, and not by scale modes themself. I mean this:
Both screenshots show the same device and the same code.
So what happened here?

This is the culprit:

if (zoom == -1)
{
var ratioX:Float = stageWidth / gameWidth;
var ratioY:Float = stageHeight / gameHeight;
zoom = Math.min(ratioX, ratioY);
gameWidth = Math.ceil(stageWidth / zoom);
gameHeight = Math.ceil(stageHeight / zoom);
}

So when you set the zoom to -1, the template will recalculate not only the zoom factor, but also your gameWidth and gameHeight. Which leads to a disaster, as those values are used to determine the size of your assets in relation to the game area. So, for example, if you design for 320x480 and prepare a background that nicely fills that 320 px width, you will find out that after launching your game in a different than intended aspect ratio (for example, in landscape rather than portrait orientation), your gameWidth might suddenly become, for example, 100 px, and now the engine "thinks" that it's supposed to fit the 320 pixels wide background not on one, but on over 3 screens.

It might be a good thing for some games, but I'd guess it's bad for most. But perhaps my biggest complaint is that it leads to horribly unpredictable and inconsistent behavior - a game launched in portrait mode and then switched to landscape will look differently than a game launched in landscape and then switched to portrait. More examples below.

Test setup

This is my design resolution.
How does it look on other screens?
Like before, my "test screen" is designed with 320x480 pixels in mind and will be tested in the following starting resolutions (like if the game was launched with this resolution):
  • 640x960 pixels - iPhone 4,
  • 640x1136 pixels - iPhone 5,
  • 960x640 pixels - iPhone 4 in landscape orientation,
  • 768x1024 pixels - non-retina iPad & other tablets
In addition, I'll showcase the following in order to justify saying that zoom = -1 is a trap:
  • Portrait > Lanscape - started in 640x960 px, then rotated to 960x640 px,
  • Landscape > Portrait - started in 960x640 px, then rotated to 640x960 px.
I started from a default HaxeFlixel project template. In my Main.hx, I changed my gameWidth and gameHeight
to 320 and 480, respectively. This is my design resolution. To test different actual resolutions, I modified my Project.xml's <window> tag and/or resized windows on the fly.

My only game state consists of a red background covered by a static 320x480 image (blue). In my design resolution, the background is not visible at all, but in certain scaling modes, it will show up, marking the difference between inaccessible, off-game area (= black bars) and areas that are within the game bounds, just not covered by my image (= red background).

Note 1: As of the time of writing this post and version 3.3.4 of HaxeFlixel, you need the development branch to even think about Scale Modes in the fledgling HTML5 target. A few days ago they simply wouldn't work at all, in the next version, they should be integrated with the master branch and the world will be a better place. What a glorious time to be alive!

Note 2: As mentioned, I found several inconsistencies between Scale Mode behavior on different target platforms. I'll explain them in detail in the following parts of this guide.

Note 3: Don't look at resolutions (they are resized for easier viewing), even though I mention them every now and then. It's the aspect ratios that matter.

Zoom = -1

In this test, I left the default setting of zoom = -1 (in Main.hx).

Click on a thumbnail to change the Scale Mode:

Click in the table below to change resolutions. Make sure to compare "Landscape" with "Portrait -> Landscape" and "Portrait" with "Landscape -> Portrait"!
640x960
(Port)
960x640
(Land)
640x1136 768x1024 Port ->
Land
Land ->
Port

Next


My plan for the next part(s) is to review each Scale Mode individually, focusing on glitches (especially in the HTML5 department), caveats and use cases. Knowing my luck, by the time this guide is finished, it will be outdated, but it's a good thing! It means that HaxeFlixel is improving (and it is, constantly).

I'll post a link as soon as I finish part 3. In the meantime, make sure you read part 1, which shows all the scale modes in action (and working properly!).

Tuesday, July 15, 2014

HaxeFlixel scale modes: complete guide pt. 1: overview

A few days ago I had a bit of a struggle with HaxeFlixel's scale modes and their apparent desire to make my life miserable. Fortunately, there are some wonderful coders out there in the HaxeFlixel community who literally fix things within hours. Right now, I got what I wanted and the scaling works for the most part - although there is still some wackiness and inconsistency in the less used areas, as I will hopefully be able to showcase here.

While I'm not that much into blogging (which should be obvious from my, like, one year or so hiatus), I think an overview of HaxeFlixel's many scale modes is due, especially considering that their official demo is incomplete and runs in Flash - the only platform where scaling is borderline useless. Of course you can compile the demo yourself on mobile or HTML5, but I believe it's simply much faster to look at some images.

Test setup

This is my design resolution.
How does it look on other screens?
The idea behind scaling is that games designed for a specific resolution (in my case: 320x480 pixels, which happens to be the resolution of a non-retina iPhone) should also adapt to other resolutions, for example:
  • 640x960 pixels - iPhone 4,
  • 640x1136 pixels - iPhone 5,
  • 960x640 pixels - iPhone 4 in landscape orientation,
  • 768x1024 pixels - non-retina iPad & other tablets
  • etc.

I started from a default HaxeFlixel project template. In my Main.hx, I changed my gameWidth and gameHeight
to 320 and 480, respectively. This is my design resolution. To test different actual resolutions, I modified my Project.xml's <window> tag PLUS resized windows on the fly - to make sure that it works consistently in both situations (and I guessed right, it doesn't always!).

My only game state consists of a red background covered by a static 320x480 image. In my design resolution, the background is not visible at all, but in certain scaling modes, it will show up, marking the difference between inaccessible, off-game area (= black bars) and areas that are within the game bounds, just not covered by my image (= red background).

Note 1: As of the time of writing this post and version 3.3.4 of HaxeFlixel, you need the development branch to even think about Scale Modes in the fledgling HTML5 target. A few days ago they simply wouldn't work at all, in the next version, they should be integrated with the master branch and the world will be a better place. What a glorious time to be alive!

Note 2: As mentioned, I found several inconsistencies between Scale Mode behavior on different target platforms. I'll explain them in detail in the following parts of this guide.

Note 3: Don't look at resolutions (they are resized for easier viewing), even though I mention them every now and then. It's the aspect ratios that matter.

Zoom = 1

In this test, I explicitly set my initial zoom to 1 (in Main.hx). As you'll soon notice, the "default" automatically calculated zoom = -1 that's set in the template is a trap.

Click on a thumbnail to change the Scale Mode:

Click to change the target device resolution:
640x960 960x640 640x1136 768x1024

Next

In the next part of this overview, I'll have a look at the whimsical nature of Scale Modes when subjected to automatic zoom calculation by an unsuspecting developer, who thinks that something that's been put into the default project template must be pretty well-tested. I have no doubt that some people will think of it as "features", but in my book, something as inconsistent is simply a bug.

Afterwards, my plan is to review each Scale Mode individually, focusing on glitches (sadly there are a few as of now, especially in the HTML5 department), caveats and use cases. Knowing my luck, by the time this guide is finished, it will be outdated, but it's a good thing! It means that HaxeFlixel is improving (and it is, constantly).

I'll post a link as soon as I finish part 3. Read part 2 here. Do it.