Dealing with Multiple screen sizes


(BlueZumbrellas) #1

So something I’ve found recently is that FlashPunk is pretty good for prototyping for mobile games. Getting something up and running is quicker than tools like Unity and AS3 has support for pretty much all the common features smartphones have these days. Plus it’s always nice to have something you can show off to people when out and about. Of course, due to FP’s CPU blitting, you’ll never achieve 30+ FPS at native res but given most devs work at 320 x 240 and scale upwards this shouldn’t be a problem on any supported iOS/flagship android device (Nexus 7/10, HTC One, Galaxy IV etc).

Here’s a basic Main.as to help you get started with a mobile/desktop hybrid project that will handle any (almost) resolution you throw at it (remember to set the flag of what platform you’re targeting to TRUE):

package 
{
	import flash.system.Capabilities;
	import net.flashpunk.Engine;
	import net.flashpunk.FP;

[SWF(width = "640", height = "480")] //Resolution of the game (Desktop version)

public class Main extends Engine 
{
	public static const MOBILE:Boolean = false;
	public static const AIRPACKAGE:Boolean = false;
	public static const IOS:Boolean = false;
	public static const ANDROID:Boolean = false;
	
	//Used for packaging desktop AIR, iOS and Android apps. Set in the constructor, ensures game always scales to correct size regardless
	//of device.
	private var screenResolutionX:int;
	private var screenResolutionY:int;
	private var screenScale:int;
	
	public function Main():void 
	{
		if (MOBILE || AIRPACKAGE)
		{
			//Grab screen resolution of device
			screenResolutionX = Capabilities.screenResolutionX;
			screenResolutionY = Capabilities.screenResolutionY;
			
			if (IOS)
			{
				if (Capabilities.screenResolutionX == 640) {screenScale = 2;} //iPhone 4 expample
			}
			else if (ANDROID)
			{
				if (Capabilities.screenDPI >= 410) {screenScale = 8;} //HTC One Example
			}
			else if (AIRPACKAGE)
			{
				//TODO: Grab common resolutions for PC screens.
				screenScale = 4;
			}
		}
		else
		{
			//Default size for desktop is 320 x 480, scaled by 2
			screenResolutionX = 320;
			screenResolutionY = 240;
			screenScale = 2;
		}
		
		//Initalize game. Tip - when working on Mobile, be sure to divide screen resolution by screen scale,
		//This saves processing power (important as Flashpunk uses the CPU to render atm) and helps enhance the
		//game's pixel art look.
		super(screenResolutionX, screenResolutionY, 30, false);
		FP.screen.scale = screenScale;
		//FP.console.enable();
	}

So a few things here. First, this type of scaling is suited to a certain type of game, like the single screen puzzle game I’m currently making and which this code sample is from. Very few objects use fixed x and y positions making it easier for things to re-position according to resolution and aspect ratio. Games like platformers which benefit from having a fixed viewpoint will most likely need to find another way. Secondly, you’ll need to test on-device/use a simulator for the mobile build as annoyingly the ADL reads the screen resolution of the desktop and not the test device. There’s a great tutorial that comes bundled with the mobile project template on how to get that running.

Lastly, about how to tell what scaleSize to use. On iOS this is pretty easy: 1x For iPhone 3GS (assuming that’s the base), 2x For iPhone 4/S & 5, 4x for iPad 1/2/Mini and 8x For iPad 3/4. On android, not so much: Google themselves say that instead of resolutions you should be using DPI values instead. It’ll take a bit of experimenting to get things right (for example, what looks good at 2x on my nexus 7 looks absolutely tiny on the HTC One).

Hope this helps :slight_smile: Also feel free to correct me if I’m wrong on anything. Happy making!


(fedyfausto) #2

i have 60 pfs on my Iphone5 because the new CPU arm9 go so fast with CPU rendering


(Alex Larioza) #3

@fedyfausto There’s still many people with older (and slower) devices, so if you want to reach a wide audience you can’t base your performance off the newest iPhone.


(fedyfausto) #4

iknow :frowning: it’s so boring because FP it’s really good


(Draknek) #5

You should set the scaling factor based on the size of the screen, don’t try to do any device-detection.

This is my code:

public static var touchscreen:Boolean;

public function Main ()
{
	if (Capabilities.manufacturer.toLowerCase().indexOf("ios") != -1) {
		touchscreen = true;
	}
	else if (Capabilities.manufacturer.toLowerCase().indexOf("android") >= 0) {
		touchscreen = true;
	}
	
	var w:int;
	var h:int;
	
	var targetW:int = 120;
	var targetH:int = 100;
	
	if (touchscreen) {
		w = Preloader.stage.fullScreenWidth;
		h = Preloader.stage.fullScreenHeight;
		
		// Can't remember the details of why this is here now...
		if (isAndroid && w < h) {
			var tmp:int = w;
			w = h;
			h = tmp;
		}
	} else {
		w = Preloader.stage.stageWidth;
		h = Preloader.stage.stageHeight;
	}
	
	var sizeX:Number = w / targetW;
	var sizeY:Number = h / targetH;
	
	var scale:int;

	if (sizeX > sizeY) {
		scale = int(sizeY);
	} else {
		scale = int(sizeX);
	}

	w = Math.ceil(w / scale);
	h = Math.ceil(h / scale);
	
	super(w, h, 60, true);
	
	FP.screen.scale = scale;
}

Change targetW and targetH to the minimum allowed width or height.

This code requires a reference to the stage object, which you don’t normally have access to in the FlashPunk constructor. I assign it in the preloader to a static var Preloader.stage so I can access it here.

This approach works for me on all devices, it doesn’t matter if they have a weird screen size. (You still have to look at FP.width and FP.height to place things onscreen correctly though.)


(BlueZumbrellas) #6

Thanks Drakek, that’s much better! I got it working without the whole Preloader thing though (as ScreenResolutionX & Y do the same thing since you’ll want your game full screen anyways).

	public function Main():void 
	{	
		//Holds width and height values
		var w:int;
		var h:int;
		
		//The minimum allowed resolution
		var targetWidth:int = 320;
		var targetHeight:int = 240;
		
		if (MOBILE)
		{
			Multitouch.inputMode = MultitouchInputMode.GESTURE; //Set touch mode to gesture
			
			//Grab device's resolution
			w = Capabilities.screenResolutionX;
			h = Capabilities.screenResolutionY;
		
			//Used for determining the scale factor
			var sizeX:Number = w / targetWidth;
			var sizeY:Number = h / targetHeight;
		
			var scale:int;
		
			//Determine what scale value to use based on orientation
			if (sizeX > sizeY)
			{
				scale = int(sizeY);
			}
			else
			{	
				scale = int(sizeX);
			}
		}
		else if (DESKTOP) //Remember to set the SWF properties below imports
		{
			scale = 2;
			w = targetWidth * scale;
			y = targetHeight * scale;
		}
		
		//Initialise game
		super(w / scale, h / scale, 30, false);
		FP.screen.scale = scale;
	}

I know the scaling for the desktop version is a bit goofy, but it means I can keep a single code-base and turn things on/off based on what I’m targeting with flags.


(BlueZumbrellas) #7

So I’m going to hi-jack my own thread, but I recently came across this:

http://forums.tigsource.com/index.php?PHPSESSID=da2ed1617378481ecb96f83904be8baf&topic=26923.msg753544#msg753544

Along with reading Andy Moore’s AS3 optimisation guide: http://www.andymoore.ca/2012/01/how-to-improve-your-mobile-as3air-performance/

I don’t know if Chevvy reads this forum, but it would be cool to be able to see code for that hack! I’m progressing well in a game I’m working on and I really don’t want to deal with having to learn unity/starling to be able to access the GPU.

Is there an easy way to cache my spritemaps/tilemaps to the GPU with FP as-is?


(Sharon Shalom Iluz) #8

Have you guys tried out the code cause im trying is and the i get an error at the super line of code


(FNX) #9

I just do something like this in my GameEngine class:

FP.screen.scaleX    = screenWidth / FP.width;
FP.screen.scaleY    = screenHeight / FP.height;
FP.screen.smoothing = false;

where screenWidth/screenHeight are the native resolution of the device, FP.width and FP.height are the actual game size. Smoothing true or false depending on the kind of game and personal taste. I use as resolution for games of 320x533 (which is Samsung Galaxy S Plus resolution, looks the same as 480x800) portrait and scale up or down accordingly and it works pretty well with my games :smile:

What would be nice is that FP worked well with high resolution scaled down but unfortunately it runs damn slow, so you will get a bad look on tablets…


(Jacob Albano) #10

If you have a compile error, include it in its entirety.


(Sharon Shalom Iluz) #11

sorry it was my fault i had 2 super methods


(Sharon Shalom Iluz) #12

I have a question would you use 2 set of images and animation for high rez screen and lower one or one asset for all of them cause you don’t want it to pixelate ? if so what resolution of the images would be best?


(Sharon Shalom Iluz) #13

I’m sorry i don’t get it its giving me an error for the preloader .stage whats in the preloader file look like ? im testing all 3 code on different sizes and it doesn’t seem to be changing anything


(Sharon Shalom Iluz) #14

the if MOBILE and DESKTOP i don’t get how its referring where its getting its value to compare?