Multi Resolution


This article concerns StarlingCitrusEngine and how to manage multi-resolution using Citrus Engine.

The features explained in this article should be considered even if you're not targeting mobile; not only to make possible ports easier in the future for your project, but also so you integrate the workflow and see that even for a non-mobile game you might save some lines of codes and troubles by making use of them. In the end, you will also possibly configure all of your projects the same ways without having to keep separate files or compiling conditionally for mobile, desktop or web.

There are some explanations to be done, that's what this article is for, But you can have a quick look at the final example code to see where we're going and see how simple it is to setup a project for any resolution and target.

When in this article I write screen, its to facilitate explaining things as most of readers will come here for mobile development and on mobile your game is highly likely to be running in fullscreen mode in which case the window, screen, and native flash stage are the same size.

In fact to be less confusing I should be talking about the flash native stage, to unify all concepts explained here no matter where the app runs, in fullscreen or windowed mode, on desktop or mobile : we made sure that all is handled the same.

We won't be going over what is already made clear in the starling wiki about managing multi-resolution development here :

so make sure you are familiar with this starling specific article, as this article will make references to it.

All we will be doing here, is use Citrus Engine features so you don't have to setup your viewport manually or handle the resize event yourself (unless you want to - we're not forcing these features on you :p ), while still following the official ideas described in that article.

Base dimensions

If you didn't do that yet, you should decide on base dimensions for your game. The base dimensions means the dimensions of the stage needed when you run your game at a resolution of 1 - and it should be the resolution/dimensions on which you base all your development of assets and code on.

Another definition if that's not clear enough, its the dimensions from which you would upscale or downscale your original game to fit in the other possible screens of other devices.

To help you with managing viewport position, the starling stage sizes and the actual up/downscaling, CitrusEngine needs to know about these base dimensions otherwise it has no base for calculating the scaling and ratios for you.

In your document class or the class extending StarlingCitrusEngine, add the following lines in the constructor :

_baseWidth = 480;
_baseHeight = 320;


Looking at the article mentioned above, we decided to implement “viewport mode” so that Strategy 2 and Strategy 3 can be implemented in an automatic way so that you don't have to do anything special.

here are the modes we made available.

  • ViewportMode.NO_SCALE

no_scale, the mode that will set the viewport in the center of the screen, with the base size. Not really something you'd want but its the first part of Startegy 2.

  • ViewportMode.LETTERBOX

letterbox , or strategy 2 - the alternative version- in fact, will use RectangleUtil to fit the viewport inside the screen, set the starling stage to the baseWidth/baseHeight values and also center the viewport, even on resize and fullscreen events, so everything is automated for you.

  • ViewportMode.FULLSCREEN

FULLSCREEN (or strategy 3) : viewport fills the screen, the starling stage is also zoomed to fit, like strategy2 in fact, only we add a little extra to fill up the screen using a simple ratio calculation … basically the stage's original aspect ratio is kept and simply extended vertically or horizontally.

This mode is not specific to an app running in fullscreen or on mobile!

Even though the name of this mode is FULLSCREEN, it actually means the starling viewport will fill up the flash native stage , which if the app is running in fullscreen, is of the same size as the screen. if your app runs in windowed mode in the air player, or in flash player on a web page, that mode will always make starling fill the window/stage/player in exactly the same way and keeping the original aspect ratio, and is to be used on any platform or player you want that to happen no matter what the stage display state is.

  • ViewportMode.LEGACY

that's the default mode used by CitrusEngine. This one sizes the viewport to the flash stage, and sets the starling stage to the same dimensions. This mode does not consider the base dimensions at all. you'll have to handle dynamic positioning, content scaling etc…

note on this mode : the flash stage coordinates are the same as the starling stage coordinates as they are both aligned and at a ratio of 1:1, unlike previous modes.

  • ViewportMode.MANUAL

CitrusEngine will do nothing.

Now you simply have to add a line to use one of these modes :

_baseWidth = 480;
_baseHeight = 320;
_viewportMode = ViewportMode.FULLSCREEN;

Scale factor and your assets

Now you can even tell CitrusEngine what resolution assets you have so he can figure out the closest size there is to the reported starling's contentScaleFactor.

_baseWidth = 480;
_baseHeight = 320;
_viewportMode = ViewportMode.FULLSCREEN;
_assetSizes = [1, 1.5, 2, 4, 5];

Citrus Engine now thinks I have assets for 1, 1.5,2,4 and 5.

when done setting up starling and its viewport, _ce.scaleFactor will return one of these values that is closest to Starling.current.contentScaleFactor so that I can easily decide on which set of asset to use in the starling asset manager for example or when I create new textures in my game.

you don't have to use this. this is really to help you have a quick setup and not worry about hardcoding stuff in or having to decide which assets you want to load for what resolution - so scaleFactor is basically a helper property for you (and also for when CE uses the dynamic texture atlas generator or creates textures from bitmaps for you.)

scaleFactor is 1 by default.

note that you can force scaleFactor to be a certain value by just setting _assetSizes to have only one entry or scaleFactor will stay 1.

example on how StarlingCitrusEngine sets the scaleFactor

if starling's contentScaleFactor is 2.333333, and you defined _assetSizes as [1, 1.5, 2, 4, 5]

StarlingCitrusEngine by simple distance calculation will set scaleFactor to be 2 because its the closest number in your list of sizes to 2.33333333

you can override StarlingCitrusEngine.findScaleFactor if you want to hardcode scaleFactor or calculate it a different way.

using the scaleFactor when creating textures manually

if you let StarlingCitrusEngine decide on the right scaleFactor but you're not using an asset manager, you would load your asset (png for example) from the folder you created that corresponds to the scaleFactor , and then whenever you create a texture, you would use scaleFactor as the scale argument for the Texture like so :

var asset:Bitmap = /* a Bitmap loaded from file or url for the right scale (ex: "assets"+scaleFactor+"x/image.png") */; 
var texture:Texture = Texture.fromBitmap(asset,true,false,_ce.scaleFactor);
var image:Image = new Image(texture);

setUpStarling() and Context3D profiles

You should specify a context3DProfile to be used with the setUpStarling function's via its 4th argument.

setUpStarling(true,1,null, Context3DProfile.BASELINE_CONSTRAINED);

the first argument is whether starling should show its stats display, the second is the antialiasing value, the third is the viewport which if left null will be handled automatically by StarlingCitrusEngine if using any viewport mode other than the MANUAL and LEGACY mode. reparacion de electrodomésticos madrid

if you leave the profile argument to “auto” however, StarlingCitrusEngine will try for available profiles in the _context3DProfiles array :

_context3DProfiles = [Context3DProfile.BASELINE_EXTENDED,Context3DProfile.BASELINE];
setUpStarling(true,1,null, "auto");

BASELINE_EXTENDED will be tested , and if its not available, then we'll test for BASELINE. if none work, an error is thrown.

warning : “auto” might fail due to the incapacity of the device/air to provide a new context3D in reasonable time. so a default delay of 100ms is defined (which does not mean this is a valid delay for all devices but so far tests have proven conclusive)

The idea is to be able to develop for any resolution faster by not having to worry about this, and also to be able to prepare your game/app conditionally … based on the best profile the current device can run AND the scaleFactor so to choose a different set of texture for example when setting everything up.

If you want to get rid of the delay and if Air and the devices allows it, you can set _context3DProfileTestDelay to 0.

_context3DProfileTestDelay = 0;
_context3DProfiles = [Context3DProfile.BASELINE_EXTENDED,Context3DProfile.BASELINE];
setUpStarling(true,1,null, "auto");

We already have the _context3DProfiles array defined as


so you really don't have to set it up if you want to test for all of them,

_context3DProfileTestDelay = 0; // our device allows for getting a new context3D without delay
setUpStarling(true,1,null, "auto");

they are ordered in a way that the last one that works will be used and should be the best one available.

please give us your feedback on this feature, we'd love to know if that feature has got enough real world applications to actually be the default behavior with setUpStarling.


In CitrusEngine, you can set the fullScreen property to true (or see if its true or false to know whether you are already in fullScreen mode or not)

This will start changing the flash stage display state to fullscreen interactive as long as the device or browser authorizes it, so this also works for simple Air desktop games and you can simply toggle fullscreen mode by toggling this property

_ce.fullScreen = !_ce.fullScreen;

if a viewport mode is being used, the viewport will be automatically resized and positioned as it would by default on a resize event.

Final example code

Assets are orgranized in folders named by their asset resolution :

  • assets1x/…
  • assets1.5x/…
  • assets2x/…

and the looks like this :

	public class Main extends StarlingCitrusEngine
		public static var assetManager:AssetManager;
		public function Main()
			_baseWidth = 480;
			_baseHeight = 320;
			_viewportMode = ViewportMode.FULLSCREEN;
			_assetSizes = [1, 1.5, 2, 4, 5];
		override public function initialize():void
		override public function handleStarlingReady():void
			assetManager = new AssetManager(scaleFactor);
			assetManager.verbose = true;
			assetManager.enqueue("assets" + scaleFactor + "x");
					if (ratio == 1)
						state = new FirstState();

notice that we let StarlingCitrusEngine find the scaleFactor for us to give to the starling assetManager - and to load up assets in our corresponding folder containing the assets we prepared specially for that scale factor.

Example Project


  • Why is starling null after I call setUpStarling?

as explained in the setUpStarling() and Context3D profiles section of this article, if you don't provide a Context3DProfile on setUpStarling's 'profile' argument in place of the default “auto” value, StarlingCitrusEngine will start running tests of the best profile available - so starling will be ready to work with only in handleStarlingReady and its best to manipulate starling (viewport or stage) then. in fact, your project's structure should be the same as the Final example code no matter what so you are prepared for that possibility.

  citrus/multi_resolution.txt · Last modified: 2019/02/14 14:44 by
Powered by DokuWiki