AS3/Adobe AIR Starting in Portrait & changing to Landscape becomes wrong - actionscript-3

I'm gonna try to explain this as good as I can with limited english!
Ok, I'm bulding an app that will on phones be in portrait mode and in landscape on tablets.
I do this by, first with calculating the display size than basically saying "if display size is more than 5 inches, consider this device to be a tablet".
This works great. I'm using Adobe Flash CS6 with FlashDevelop, so I have portrait mode as default once the application start. If the device is a tablet, it changes aspect ratio with stage.setAspectRatio(StageAspectRatio.LANDSCAPE);
This also works great.
Now, the problem is that stage.stageWidth will not change its value to the new aspectRatio. This is a easy fix with just using stage.stageHeight for the width. BUT the system bar on honeycomb/ics tablets/devices will not be changed.
Sorry for the bad explanation but let me show you with some numbers...
This is what happends when I start my application on my tablet.
Application start with Portrait. The height = 1232 width = 800. As you can see the display resolution should be 1280x720 but there is no way to get the height of the systembar througout any commands. I've test everything that returns resolution and none of them return the full resolution (1280x720).
Now the application turns into landscape (since it's a tablet) and gets this resolution height: 800, width 1232.
As you may can imagine this is wrong. Because the systembar is on the bottom. The resolution should be height: 752, width 1280.
Is there any solutions?
I've been thinking of a workaround that will basically calculate what the systembar *should be. But before I start on that, I would like to know if there is any way to solve this.*

-1. I don't know if there's an official way to do these,
but your first criteria sounds similar to this:
link: AS3/AIR: If phone use portrait, if tablet use landscape?
This also solves the problem that some devices' default orientation are "portrait" but some devices' are "landscape"
-2. As for the area of the screen
The following should give the pixel dimensions of the device:
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.fullScreenWidth;
stage.fullScreenHeight;
//import flash.system.Capabilities;
Capabilities.screenResolutionX;
Capabilities.screenResolutionY;
And then using this (which I assume you've been using) should return the usable area minus the Status Bar (a post I read mentioned it is correct for iPad but some Android tablets did not take into account the Navigation Bar):
stage.stageWidth;
stage.stageHeight;
Then this one should give the correct value of screen resolution minus Status Bar and Navigation Bar area:
//import flash.display.Screen
var screenBounds:Rectangle = Screen.mainScreen.visibleBounds;

Related

Proper positioning (Screen width & height)

A little lost here. I've got two movieclips. I want one on the far left (out of reach until the user hovers over their left side of the screen) and one on the far right. I've tried playing with Screen, Capabilities, and stage.
I don't know why, but apparently my resolution 1536 by 864?
trace("Screen x = " + Capabilities.screenResolutionX); //Screen x = 1536
trace("Screen y = " + Capabilities.screenResolutionY); //Screen y = 864
I don't want to set the position of the native window to what the difference of the stage's with and height is to screenResoltionX and Y just because that number seems so off to me. I'm on a monitor with it's current resolution at 1920 x 1080. The only thing I can think of is that I have my laptop set to display only on the monitor at this time with it's main screen inactive, yet the window appears on my monitor, so i'm assuming its picking up the values from my monitor .. and my laptop's screen has no where near that weird of a resolution. Anyone know where this is coming from? I've never seen this before. The same numbers return from stage.fullScreenWidth and stage.fullScreenHeight..
I'm using Adobe AIR 17.0 to build this. Building it with an opaque window. The current size of the stage is set to 1024 x 786.
Edit: I want these objects on the edges of the user's screen. I'm trying to get a grid that represents the entire bounds of the user's screen.
When using Capabilities.screenResolutionX & Capabilities.screenResolutionY, it is reporting for the primary display (so if you have more than one monitor, regardless of which monitor your app is on, it will report back the primary monitor's resolution), and only at the time your application starts (so if you change resolution after the app starts Capabilities.screenResolutionX will not reflect the new screen resolution).
Here is a quote from the documentation: (emphasis mine)
This property does not update with a user's screen resolution and instead only indicates the resolution at the time Flash Player or an Adobe AIR application started. Also, the value only specifies the primary screen.
For your purposes, it seems like it shouldn't matter what the screen resolution is. Just use the stage.stageWidth & stage.stageHeight values since they reflect the boundaries of your actual app, regardless of which monitor it's on or if it's full screen, windowed, or scaled etc.
if(stage.mouseX < stage.stageWidth * 0.5){
//mouse is on the left hand side of the application.
}
EDIT
Based off your comment, sounds like you need to do this:
When your app first runs, do this to make it responsive/liquid:
stage.align = StageAlign.TOP_LEFT
stage.scaleMode = StageScaleMode.NO_SCALE
Then the stage.stageWidth and stage.stageHeight properties will reflect the actual window size.
You can maximize it through code with:
stage.nativeWindow.maximize();
You can listen for window sizing changes with:
stage.addEventListener(Event.RESIZE, myResizeHandler);
function myResizeHandler(e:Event):void {
//stage.stageWidth & stage.stageHeight have changed
}

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.

Scaling a Game Maker app for mobile-device screens

I'm having a difficult time getting an HTML5 app I designed in Game Maker to scale for display on mobile-device screens. I've tried using this little bit of code, to set the width and height of a the main game room, in a setup object, before switching to that room:
room_set_width(rm_playspace,browser_width);
But that seems be doing absolutely nothing.
Have you successfully designed software for mobile devices with Game Maker? How did you get your software to scale for proper viewing on mobile devices with differently sized screens?
room_set_width( ind, w );
Description
With this function you can change (or set) the width of any room in your game except the current one.
so you need to go to another room, and then resize the first room and go back into it.
another option that you can try - just restart the room immediately after resizing, like
room_set_width(room, 640)
room_set_height(room, 480)
window_set_size(640, 480) // also you can use window_set_rectangle
room_restart()
(room should not be a persistent)
Don't forget to set view_port_xxx and view_size_xxx for proper sizes. You can use window_get_width() and display_get_width() etc. for that - refer to manual for more info.
You could also just resize the surface and before, the view.

Retrieve original stage width and height after scale

Does anyone know how I can retrieve the "ORIGINAL" stage height and width that was set during compile of an Air/Flash Application
I have set the Application to compile to 1920x1080;
I have stage.scaleMode = StageScaleMode.SHOW_ALL;
and stage.nativeWindow.maximize();
But when I trace stage.stageWidth I get 1280 which is the resolution of the screen.
I was hoping to get the 1920.
I cannot use stage.width or stage.getBounds(stage) because this returns 6000. Due to items being masked off screen.
With the stage.stageWidth being the screen resolution, I was hoping I could use that and mathematically work out the original using stage.scaleX. but even with SHOW_ALL scaling the entire application, stage.scaleX returns 1.
I would love to hardcode 1920x1080 into the application, but this code is being used in multiple applications of various dimensions. And now I have become stumped.
Any help would be welcome.
EDIT: I know what "Show all" does, you do not need to tell me about it.
I also know what stage.width and stage.stageWidth do, but stage.stageWidth is returning what I believe is incorrect in this example and need an alternative.
Resize does not help either as I need it after the fact.
when you are setting:
stage.scaleMode = StageScaleMode.SHOW_ALL;
the Event.RESIZE is not beeing dispatched from the stage, because no RESIZE of the stage is happening.
stage.width - is the parameter which gives you the size of all the display objects placed on it ( imagine everything what is places on the stage as a one MC ).
stage.stageWidth - this parameter will give you back the default width only ( because no REIZE is happening, since you have scaleMode=SHOWALL, normally it does return the visible flash stage size.
If you want to get the size of a screen ( device rezolution ):
Capabilities.screenResolutionX
SHOW_ALL parameter for scaleMode says application to stretch to the flash display size.
If you want to change something for different sizes of the screen / flash display stage,
you need to use NO_SCALE property.
p.s. for width parameter same rules applies.
UPDATE
After some testing found a solution for it:
stage.scaleMode = StageScaleMode.NO_SCALE; // reseting the scale to get actual width
ACTUAL_STAGE_WIDTH = stage.stageWidth; // this is where you getting the width you need
stage.scaleMode = StageScaleMode.SHOW_ALL; // setting back the scale.
#Jevgenij Dmitrijev solution was a bit of a hack. (No Offense)
The real answer for getting the published SWF Size is using
this.loaderInfo.width;
this.loaderInfo.height;
Found it on an older actionscript forum and it was something that i myself forgot.
you can look up loader info on ASdoc's and they'll give you an in-depth explanation.

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.