It’s been a while since I’ve needed to do this. I’ve refactored some AS3 code I used to manage this with. With this, you can press the f key to toggle between fullscreen and windowed mode. The Starling context is scaled up or down, maintaining aspect ratio.
All this happens within the OpenFL context, not the Starling context, although the ResizeEvent.RESIZE listener is added to the Starling context. I hope that makes sense.
If you don’t mind stretching your content (generally not desirable), comment out the algorithm below under // Auto-fit any resolution maintaining aspect, and un-comment the one under // Auto-fit any resolution with stretch.
package;
import openfl.Assets;
import openfl.display.Shape;
import openfl.display.Sprite as OpenFLSprite;
import openfl.display.StageDisplayState;
import openfl.display.StageScaleMode;
import openfl.events.KeyboardEvent;
import openfl.geom.Rectangle;
import openfl.ui.Keyboard;
import starling.core.Starling;
import starling.display.Image;
import starling.display.Sprite;
import starling.events.Event;
import starling.events.ResizeEvent;
import starling.textures.Texture;
class Main extends OpenFLSprite {
private var starling:Starling;
private var shapeScaler:Shape;
public function new() {
super();
// Initialize Starling
starling = new Starling(StarlingRoot, stage);
starling.start();
// Starling resizer
var originalViewPort:Rectangle = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);
this.stage.scaleMode = StageScaleMode.NO_SCALE;
shapeScaler = new Shape();
shapeScaler.graphics.beginFill(0);
shapeScaler.graphics.drawRect(originalViewPort.x, originalViewPort.y, originalViewPort.width, originalViewPort.height);
shapeScaler.graphics.endFill();
Starling.current.stage.addEventListener(ResizeEvent.RESIZE, stageResized);
// Enter Standard Fullscreen State
stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
// Listen for keyboard event
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown);
}
/**
Listens for f key and toggles fullscreen state.
**/
private function keyDown(e:KeyboardEvent):Void {
switch (e.keyCode) {
case Keyboard.F:
if (stage.displayState == StageDisplayState.FULL_SCREEN_INTERACTIVE) {
stage.displayState = StageDisplayState.NORMAL;
} else {
stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
}
default:
}
}
/**
Listens for Starling resize events and scales the entire Starling context accordingly.
**/
private function stageResized(e:ResizeEvent):Void {
shapeScaler.width = e.width;
shapeScaler.height = e.height;
// choose the larger scale property and match the other to it;
(shapeScaler.scaleX < shapeScaler.scaleY) ? shapeScaler.scaleY = shapeScaler.scaleX : shapeScaler.scaleX = shapeScaler.scaleY;
// choose the smaller scale property and match the other to it;
(shapeScaler.scaleX > shapeScaler.scaleY) ? shapeScaler.scaleY = shapeScaler.scaleX : shapeScaler.scaleX = shapeScaler.scaleY;
// Auto-fit any resolution maintaining aspect.
Starling.current.viewPort = new Rectangle((e.width - shapeScaler.width) / 2, (e.height - shapeScaler.height) / 2, shapeScaler.width,
shapeScaler.height);
// Auto-fit any resolution with stretch.
// Starling.current.viewPort = new Rectangle(0, 0, e.width, e.height);
trace('Stage resized to:', e.width, e.height, ' and viewPort resized to', shapeScaler.width, shapeScaler.height);
}
}
/**
The beginning of the Starling context.
**/
class StarlingRoot extends Sprite {
public function new() {
super();
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
private function onAddedToStage(e:Event):Void {
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
// Load the texture from the assets path
var myImage = new Image(Texture.fromBitmapData(Assets.getBitmapData("img/atlas.png")));
// Scale the image based on stage width.
myImage.scale = stage.stageWidth / myImage.width;
addChild(myImage);
}
}
For what it’s worth, I would normally have the entry-point for my Starling context (StarlingRoot) in a separate .hx file, not the same file as Main. I’ve only put it in a single file here for simplicity sake.
