Skip to content

In depth explanation of ResolutionLevels

bdjones edited this page Feb 25, 2013 · 18 revisions

In-depth explanation of ResolutionLevels

This is going to be a pretty in-depth explanation of ResolutionLevels, but don't worry if you get overwhelmed. You only have to set them up once and then once you've done that, they'll save you from TONS of headache down the road.

The Basics

First, the basics: ResolutionLevels (aka resLevels) carry information about how to handle the size of the screen and which assets to use based on how big the screen is. You specify resolution levels through

futileParams.AddResolutionLevel(maxLength, displayScale, resourceScale, resourceSuffix);

When Futile is inited, it picks the most applicable resLevel and then sets everything else up from there. There currently isn't a way to change the resLevel while Futile is running, because that would involve reloading different assets and cause other issues. I can't think of reason you'd need to do this on mobile at all, and most 2D desktop apps run at a fixed res anyway, so I don't see it being a huge issue. However, if this is something you think you need, let me know and I can look into it.

The Specifics

The first parameter (maxLength) is the maximum screen size (width/height, whichever is longer) that Futile should use a specific resLevel for. If the resolution is larger than any resLevel's maxLength, then Futile will use the biggest resLevel that was specified. In every other scenario, it will never use a smaller resLevel (because it's better to scale down than scale up). Example, if there is a resLevel with a maxLength of 499 and a resLevel with a maxLength of 600, and the actual screen's longest side is 500 pixels long, it'll chose the 600 resLevel.

The next parameter (displayScale) is the ratio of Futile units (aka points) to pixels. In other words, if displayScale is 2.0, and you set something.x = 14, it'll actually move by 28 pixels. This is super handy on Retina displays and stuff like that, because you don't need to worry about what kind of display you're on, everything will just work.

The next parameter (resourceScale) you can think of as the ratio of pixels (in the atlas config json file) to points in the game. In other words, if resourceScale is 2.0, and a sprite's json file says it's 100 pixels wide, it'll come into Futile as being 50 points wide. If you're confused by what to choose, try it with the same number as the displayScale or 1.0f and one of those will probably work.

The last parameter (resourceSuffix) is pretty straight forward, it's a string that gets appended to the path in all calls to atlasManager.LoadAtlas() and atlasManager.LoadImage() (there are ways to override it though, if needed). It doesn't automatically get appended to LoadFont() but you can simply use a path of "Atlases/Somefont"+Futile.resourceSuffix if you want to do that.

That's all the parameters. Once Futile is inited, you can access the relevant parameters from Futile.displayScale, Futile.displayScaleInverse (which is just 1.0f/displayScale), Futile.resourceSuffix, etc. You can also get the screen size in points through Futile.screen.width, Futile.screen.halfWidth, Futile.screen.height, and Futile.screen.halfHeight.

##Examples

For a normal game supporting iOS and the Nexus 7, something like what BananaDemoProject has will work great:

futileParams.AddResolutionLevel(480.0f,		1.0f,	1.0f,	"_Scale1"); //iPhone
futileParams.AddResolutionLevel(960.0f,		2.0f,	2.0f,	"_Scale2"); //iPhone retina
futileParams.AddResolutionLevel(1024.0f,	2.0f,	2.0f,	"_Scale2"); //iPad
futileParams.AddResolutionLevel(1280.0f,	2.0f,	2.0f,	"_Scale2"); //Nexus 7
futileParams.AddResolutionLevel(2048.0f,	4.0f,	4.0f,	"_Scale4"); //iPad Retina

This means there will be 3 sets of resources (_Scale1, _Scale2, _Scale4). With this setup, the iPad will act as if it's 512x384 points, rather than 1024x768. In some games you may want the iPad to have a 1:1 point ratio, to do that, the iPad lines should be this instead:

futileParams.AddResolutionLevel(1024.0f,	1.0f,	1.0f,	"_Scale2"); //iPad
futileParams.AddResolutionLevel(2048.0f,	2.0f,	2.0f,	"_Scale4"); //retina iPad

Ok, now what about if you have a game where you want to use a single low resolution atlas for everything (ex. a game with pixel art). First, you should make sure your texture filtering is set to "point" instead of "bilinear". Then you can set up the resLevels like this:

futileParams.AddResolutionLevel(480.0f,		1.0f,	1.0f,	""); //iPhone
futileParams.AddResolutionLevel(960.0f,		2.0f,	1.0f,	""); //iPhone retina
futileParams.AddResolutionLevel(1024.0f,	2.0f,	1.0f,	""); //iPad
futileParams.AddResolutionLevel(1280.0f,	2.0f,	1.0f,	""); //Nexus 7
futileParams.AddResolutionLevel(2048.0f,	4.0f,	1.0f,	""); //iPad Retina

Notice how there is no suffix specified, because we only have one atlas so we don't need suffixes. Also, notice how the resourceScale is 1.0f? That means that each single pixel in the atlas will correspond to a single point in Futile.

##Handling Unmatched ResolutionLevels

Ok so we're almost done, but there's one thing that hasn't been explained yet: what happens if your screen doesn't directly match up with a resolution level? This is especially likely on Android where there are a million different screen resolutions.

There are two options for how Futile will handle this situation, depending on whether you set futileParams.shouldLerpToNearestResolutionLevel to true or false.

If shouldLerpToNearestResolutionLevel is false, then nothing crazy will happen, Futile will just use all the settings from the next largest ResolutionLevel (or one smaller than it, if no larger ones exist).

If shouldLerpToNearestResolutionLevel is true (the default), then Futile will modify the displayScale as follows:

displayScale *= lengthOfScreen/resLevel.maxLength;

Example: if the screen is 800 px long, and the resLevel has a maxLength of 1000 px and a displayScale of 2.0f, then the displayScale will become 1.6f - This means you get displayScale values that scale to the size of your screen in a very adaptable fashion.

Note that the default behaviour is "true", and I only added shouldLerpToNearestResolutionLevel as an option on August 14th, so if you got the initial alpha you won't have it. If you don't see the bool it means you have an earlier version, which means the "true" behaviour is what you'll get.

Conclusion

Alright, so that's it for this explanation of ResolutionLevels. It's worth noting that if you want you could consider only adding certain ResolutionLevels when you're running on certain platforms, giving an even higher level of control.

There is currently no feature to cause Futile to run in a specific aspect ratio or anything like that, but you should be able to adapt to the size of the screen however you want if you use ResolutionLevels and you respond to resize events from Futile.instance.SignalResize (especially for Standalone apps). See this reddit comment for more info on that.

If you know exactly how you'd like your screen sizing to act, and you're not sure how to go about in Futile, just ask me and I'll help you out! You can reach me at http://twitter.com/MattRix or http://reddit.com/user/MattRix

Discuss this page on Reddit: http://www.reddit.com/r/futile/comments/y7zat/how_resolutionlevels_work/