Set ApplicationDPI in AS3 Mobile application - actionscript-3

I developing an application in Flash Builder with AS3 only (no flex stuff). In flex it is possible to set the application's dpi by the following code:
<s:ViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" applicationDPI="320">
But I using only AS3. I have read that it is not possible to change the application's DPI in run-time (with AS3), but how can I set this in project settings, compiler settings or is there another way to do it?
Also, what is the default application's DPI setting?
Ask it here because can't find it on the net (only flex based solutions).

The DPI on mobile is set by the hardware, it is entirely dependent on the phone and screen. When you set the applicationDPI in a Flex mobile you're telling Flex to automatically scale your assets.
Automatic scaling. Developers can choose to specify a target DPI for their application by setting the applicationDPI property on the application. When this is explicitly set, developers should set up their skins and layout as if they were running on a device of the given DPI. At runtime, if the device has a different DPI from the specified target DPI, Flex will automatically scale the entire application to preserve the approximate physical size of the application and its controls. For example, if an application is targeted at 160 DPI, it will automatically scale by 1.5x on a 240 DPI device. If you choose not to use this feature, you'll need to make sure your custom skins and view layouts adapt properly to different pixel densities at runtime.
Source
In an AS3 mobile project you're going to need to handle this yourself.
You can get the current DPI using Capabilities.screenDPI but I think what you may be after is a ratio to scale your assets by. One way to do this would be to start with the original game width.
private static const WIDTH:Number = 1024;
You can then get a ratio using
var ratio:Number = stage.fullScreenWidth / WIDTH;
And apply this to your assets
myBitmap.scaleX = myBitmap.scaleY = ratio;
Now this isn't going to take the rotation of the device into account, so fullScreenWidth/Height may be flipped. To check for that you're going to need to do something like this
if (stage.fullScreenWidth > stage.fullScreenHeight){
//portrait
} else {
//landscape
}
Hopefully this helps

Related

User defined resolution in AS3

For the last couple of days I've been wondering if it would be possible to let the user define the resolution to be used, when building for an AIR application.
Say if I have my SWF set up at a 1280x720 resolution by default, would it be possible to have, in the main menu, a set of resolutions, for instance 1366x768 or 1024x768, that the user can choose and then scale the window that contains the game to that size?
With AIR, you can manipulate a window's size from your code.
For the window of the current code's scope, you can do:
stage.nativeWindow.width = 1280;
stage.nativeWindow.height = 720;
OR, if you want to move the window to a particular spot and size:
stage.nativeWindow.bounds = new Rectangle(0,0,1280,720);
Or, you can use NativeApplication.nativeApplication.activeWindow or one of the items (windows) from NativeApplication.nativeApplication.openedWindows

Using sprite atlases in a multi resolution setup in Cocos2D-x

I've just been able to setup a Cocos2d-x for a multiresolution environment. Ie supporting all/most of the available iPhone screen sizes.
My next step is to scrap the individual files (bunch of pngs) and use sprite atlases (aka sprite sheets) instead.
How does this work in Cocos2D-x? Does anyone have a working sample setup?
Once again, Google and existing documentation (well, I don't think that exists) fail me.
For cocos2d-x v3.5...
The cocos2d-x test classes are always a great place to look to see how things can be done with cocos2d-x.
Check out the AppDelegate.cpp in:
Cocos2d-x/cocos2d-x-3.5/tests/cpp-tests/Classes/AppDelegate.cpp.
In that class the window size is tested to see which set of assets should be loaded. That is part of the issue, deciding which assets to load.
For iOS retina, you can check the size of the screen and then set the content scale factor to either 1.0 for standard resolution or 2.0 for retina resolution.
Unfortunately, cocos2d-x doesn't seem to ever detect certain screen sizes and call Director::getInstanct()->setContentScaleFactor(2.0) for you, so I think we have to do this our self.
I have not tested the impact of setting contentScaleFactor on non-apple devices yet...
Check out the code below. Try running it in your AppDelegate::applicationDidFinishLaunching() method to get an idea of how cocos2d-x sees screen pixels and points; the result is not exactly what I expected. The output below is for an iPhone 5 device.
director->setContentScaleFactor(2);
Size winSizePoints = director->getWinSize();
Size winSizePixels = director->getWinSizeInPixels();
Size visibleSize = director->getVisibleSize();
CCLOG("Content scale factor set to 2.0.");
CCLOG("winSizePoints:%.2f,%.2f", winSizePoints.width, winSizePoints.height);
CCLOG("winSizePixels:%.2f,%.2f", winSizePixels.width, winSizePixels.height);
CCLOG("visibleSize:%.2f,%.2f", visibleSize.width, visibleSize.height);
director->setContentScaleFactor(1);
winSizePoints = director->getWinSize();
winSizePixels = director->getWinSizeInPixels();
visibleSize = director->getVisibleSize();
CCLOG("Content scale factor set to 1.0.");
CCLOG("winSizePoints:%.2f,%.2f", winSizePoints.width, winSizePoints.height);
CCLOG("winSizePixels:%.2f,%.2f", winSizePixels.width, winSizePixels.height);
CCLOG("visibleSize:%.2f,%.2f", visibleSize.width, visibleSize.height);
Output of above code:
Content scale factor set to 2.0.
winSizePoints:1136.00,640.00
winSizePixels:2272.00,1280.00
visibleSize:1136.00,640.00
Content scale factor set to 1.0.
winSizePoints:1136.00,640.00
winSizePixels:1136.00,640.00
visibleSize:1136.00,640.00
So it seems we have to check the the screen size and then choose assets.
One option is to then use code like this to decide which assets to load based on if the screen is retina or not. You could use a similar approach to also loading different size background images to deal with different aspect ratios (more aspect ratios below).
float scaleFactor = CCDirector::getInstance()->getContentScaleFactor();
if (scaleFactor > 1.99)
{
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("spriteSheet-hd.plist", "spriteSheet-hd.png");
}
else
{
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("spriteSheet.png", "spriteSheet.plist");
}
For sprite sheets, I highly recommend Texture Packer. Awesome tool that can create SD and HD sheets and .plist files for you with the press of one button.
If you publish to multiple platforms, you will also want to use the macros to detect the device type and use that information in deciding which assets to load.
e.g.
if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
elif CC_TARGET_PLATFORM == CC_PLATFORM_WP8
elif CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
elif CC_TARGET_PLATFORM == CC_PLATFORM_IOS
elif CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
endif
Another thing to consider is that on low power CPU and RAM devices, loading large assets might make your frames per second (FPS) go to crap. Or worse, the device might not be able to load the asset or could crash the game. So be sure to test/profile on least common denominator devices that you plan to support.
Aspect Ration is another important issue (landscape width:height).
iPad aspect ratio is 4:3
iPhone 4 is 3:2
iPhone 5 & 6 are 16:9
Android throws in a bunch more width:height ratios.
WP8.1 is 15:9... not sure if others.
The point is that you probably don't want to stretch your backgrounds to get them to fill the screen, or have black bars on the edges where assets are not tall or wide enough.
To deal with this I create background assets that are wider than they need to be going off the right side of the screen. That content looks good but is not vital to convey the meaning of the background. That extra content can be clipped on devices that have narrower aspect ratios, i.e. ipad, and is visible on wider aspect ratio devices, i.e. iPhone 6.
The background images are then scaled up/down to match the screenSize height and retain their aspect ratio.

Frame resolution in windows - Cocos2dx

I am trying to set up my new project to support multiple resolutions.
As explained here all you need is to get a folder for each resolution and select one depending on the frame size (adjusting your content scale depending on your design resolution).
As i understand it, i could work on low res (480x320) and then add higher resolution assets for the other cases and everything should work (using as base my design resolution for everything).
I am working on windows, and by default it is using a frame size of 960x640, which makes my app to use a folder with a higher res than my design resolution (480x320).
How can i change my frame size (outside of my app delegate so i don't affect behaviours outside of windows) and scale it in windows?
I think it is a good idea to work with a frame size equal to your design size but if it is better to keep this default frame size or use another design resolution i would like to hear some reasons for that.
After posting this in cocos2dx site i got the answer.
All you need to do is set a GLView for your director in main, so when your appdelegate gets it, it is using the proper resolution and zoom factor already.
Your main.cpp should end up looking like:
#include "main.h"
#include "AppDelegate.h"
#include "cocos2d.h"
USING_NS_CC;
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// create the application instance
AppDelegate app;
auto director = Director::getInstance();
director->setDisplayStats(true);
auto glview = GLViewImpl::createWithRect("MyApp", Rect(0, 0, 480, 320), 2.0f);
director->setOpenGLView(glview);
return Application::getInstance()->run();
That will make your game run in windows with a resolution of 480x320 and scaled to the double (2.0).
Credit for this goes to mr. IQD :P

AS3 air multiple resolutions, assets and layout iphone and ipad app

I am building an app in AS3/Air and I would like to target both iPhone and iPad resolutions. I understand the different aspect ratios between iPhone and iPad however the app I am building currently has different layout and slightly different content to fit the different screen sizes. I currently have 2 versions of the app already built, one for iPhone the other for iPad. All assets have been created with the target platform in mind but now, I would like to combine the 2 apps into a single one.
I am thinking I will rename each each screen file to iphone_login, ipad_menu, ipad_settings etc and include them all in the same build. Then during startup, check what device the user is on and set iphone_ or ipad_ and also set the resolution at this time too.
I prefer not to have black edges going from iphone resolution to ipad so my questions are:
Is my approach a suitable one considering the outcome I would like?
How do I determine what device a user is on to show the correct files, assets and resolution?
I understand the app size will increase at least double by adding 2 sets of assets and 2 sets of code files but considering the differences in design layout and content I don't see another solution, apart from keeping 2 apps.
Thanks :)
What's the problem? iPad and iPhone have different resolution and dpi combination, check them and identify current platform.
Get view you need by class like this:
public static const PAGE1:String = "page1";
public static const PAGE2:String = "page2";
private static var PHONE_VIEW_NAME_2_CLASS:Dictionary = new Dictionary();
private static var TABLET_VIEW_NAME_2_CLASS:Dictionary = new Dictionary();
public class ViewProvider
{
{
PHONE_VIEW_NAME_2_CLASS[ViewProvider.PAGE1] = Page1PhoneView;
PHONE_VIEW_NAME_2_CLASS[ViewProvider.PAGE2] = Page2PhoneView;
TABLET_VIEW_NAME_2_CLASS[ViewProvider.PAGE1] = Page1TabletView;
TABLET_VIEW_NAME_2_CLASS[ViewProvider.PAGE2] = Page2TabletView;
}
public function ViewProvider()
{
}
public static function isTablet():Boolean {
...analyze Capabilities.screenResolutionY, Capabilities.screenResolutionX and Capabilities.screenDPI
}
public static function getViewClass(name:String):Class
{
return isTablet() ? TABLET_VIEW_NAME_2_CLASS[name] : PHONE_VIEW_NAME_2_CLASS[name];
}
}
And in your program
navigator.pushView(ViewProvider.getViewClass(ViewProvider.PAGE1))
All coordinated, paddings and another position numbers, font sizes etc correct with multiplier depending on runtime dpi by simular way...
I'm in the middle of a similar problem.
My solution is to have the images at the best resolution in a file pool, and then downscale them depending on the device when the app starts. You can do this also with non animated vector assets and put them into a bitmapData object.
Another option is to always have the asset pool with files at the maximum resolution needed loaded in the memory, and downscale them at runtime when they are needed. This works well if you will be using some asset in different places at different sizes, for example an icon.
As for the code, you should find a way to separate the code that manages data, the codes that manages the logic, and the code that "paints" the UI. This way you will be able to reuse most of the code in both versions, but only change the code that "paints" the UI. Check the MVC pattern for more info.

ActionScript Screen Measurements

i'm attempting to use the Capabilities class to draw an accurately sized sprite on screen at exactly (2.5" x 5") regardless of the screen's resolution, but while i believe the code is correct, the size of the sprite is not accurate - when actually measuring it with a ruler.
function inchesToPixels(inches:Number):uint
{
return Math.round(Capabilities.screenDPI * inches);
}
var mySprite:Sprite = new Sprite();
mySprite.graphics.beginFill(0x000000, 0.5);
mySprite.graphics.drawRect(0, 0, inchesToPixels(2.5), inchesToPixels(5));
mySprite.graphics.endFill();
addChild(mySprite);
I'm not entirely sure about this, but my feeling is that the screenDPI value being returned by the Capabilities class would be the same value for two monitors running the same resolution, even if the monitors had different physical dimensions.
To illustrate, if you have two monitors, one which is 14" and the other which is 28", both displaying the same resolution of 800 x 600 pixels, that screenDPI property will return the same thing because they're both using the same resolution.
However, the number of dots in a literal, real-world inch on each screen will be different because of the physical dimensions of the monitor. So when you're running your code and measuring the on-screen Sprite you create with a ruler, it's not going to match up to real-world inches. I'm not sure how you could get around this problem (if I'm right about what's causing it), it seems like it'd be difficult.
Debu
I suggest at the start of your app telling the user "I detected your monitor is XX inches" (where XX is calculated from screenDPI), and allow the user to type in a correct monitor size.