AS3 - iOS force landscape mode only? - actionscript-3

I've built a game for iOS that is designed for landscape mode and it works just fine except that if you turn the device to portrait mode it stops there to with the interface only filling about the middle half of the screen. How can I force the app to only allow the two landscape modes and not stop at the portrait position.
I've tried all the publishing settings. Aspect Ratio is set for Landscape and Auto Orientation is checked on, if I uncheck AUto Orientation that the app does not rotate to the other landscape mode and I hear that's an automatic rejection from Apple.
This app is ready to go except for this little flaw. Thanks for any help you can offer.
Rich

I found the answer to this over on the Adobe forums a few days ago.
Set Aspect Ratio to Auto.
Set Auto Orientation to allowed.
Then use this code on your main clip:
var startOrientation:String = stage.orientation;
if (startOrientation == StageOrientation.DEFAULT || startOrientation == StageOrientation.UPSIDE_DOWN)
{
stage.setOrientation(StageOrientation.ROTATED_RIGHT);
}
else
{
stage.setOrientation(startOrientation);
}
stage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGING, orientationChangeListener);
function orientationChangeListener(e:StageOrientationEvent)
{
if (e.afterOrientation == StageOrientation.DEFAULT || e.afterOrientation == StageOrientation.UPSIDE_DOWN)
{
e.preventDefault();
}
}
Worked fine for me..

Another, albeit similar, way to do this is to set the aspectRatio to landscape in the application descriptor and autoOrients to false. Then enable autoOrients once the application has loaded and listen for the orientationChanging event. In Flash Builder 4.6, this may be done as follows:
Descriptor:
<aspectRatio>landscape</aspectRatio>
<autoOrients>false</autoOrients>
Application code:
private function applicationCompleteHandler():void {
stage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGING, stageOrientationChangingHandler);
stage.autoOrients = true;
}
private function stageOrientationChangingHandler(event:StageOrientationEvent):void {
if (event.afterOrientation == StageOrientation.DEFAULT || event.afterOrientation == StageOrientation.UPSIDE_DOWN) {
event.preventDefault();
}
}
It looks like you also have to make sure that the application has explicit dimensions; otherwise, views may still be resized even through the stage does not reorient.
Please see:
http://bugs.adobe.com/jira/browse/SDK-32082

The answer above did not work for me, because on iOS the preventDefault no longer works.
For anyone who just still isn't having good luck... Here's what I did.
I wanted:
Ipad & All Android Tablet devices to be able to Portrait or Landscape and auto-rotate in any direction
Iphones, Ipods, & All Small Screen Devices to be forced Landscape (or maybe in your case you want forced portrait).
I Did:
IN my -app.xml:
<aspectRatio>any</aspectRatio>
<autoOrients>true</autoOrients>
In Actionscript:
var screenDPI:Number = Capabilities.screenDPI;
var resolutionX:Number = Capabilities.screenResolutionX;
var resolutionY:Number = Capabilities.screenResolutionY;
var numDiagonalDistance:Number = Math.round(Math.sqrt((resolutionX*resolutionX)+(resolutionY*resolutionY)));
var numDiagonalInches:Number = numDiagonalDistance/screenDPI;
if(numDiagonalInches<6){
MainData.SMALL_DEVICE=true;
}else{
MainData.SMALL_DEVICE=false;
}
if(MainData.SMALL_DEVICE){
this.stage.setAspectRatio(StageAspectRatio.LANDSCAPE);
}
Though I guess you could easily put StageAspectRatio.PORTRAIT or even use the reverse logic to logic ipads only or something. Good Luck!
EDITED: I'm actually editing this because even this method still has problems. You'll get landscape but its not always the landscape oriented to how you're holding the device...
EDITED AGAIN (2-27-2014): Turns out if I included -swf-version 23 (now with AIR 4.0) this problem is finally solved.

Related

Libgdx, Setting the full screen resolution during runtime causes application to render at the wrong size

I am only using the desktop Application, no mobile.
I am experimenting with letting the user set the screen resolution during run time. I give him the Display Modes available and he applies one. This part actually works. The problem occurs when i save this mode and try to set this display mode the next time they launch the game.
I am using preferences to store the mode the user selected. I am unable to access preferences before the Create method in my Game class, or in the DesktopLauncher Object, where you normally set up the config file and pass it into the application. So my DesktopLauncher looks like this.
val config = Lwjgl3ApplicationConfiguration()
config.setFullscreenMode(Lwjgl3ApplicationConfiguration.getDisplayMode())
Lwjgl3Application(MainGame(), config)
I use the current screen resolution on the creation of the application. Then in my Create method in my MainGame class i get the mode they set from preferences and i set it like so...
override fun create() {
var modes = Gdx.graphics.displayModes.toList()
val mode = Gdx.graphics.displayMode
val preference: Preferences = Gdx.app.getPreferences("screenPreference")
val screenWidth = preference.getInteger("width", mode.width)
val screenHeight = preference.getInteger("height", mode.height)
val refreshRate = preference.getInteger("refreshRate", mode.refreshRate)
modes = modes.filter { it.width == screenWidth }
modes = modes.filter { it.height == screenHeight }
modes = modes.filter { it.refreshRate == refreshRate }
if (modes.isNotEmpty()) {
Gdx.graphics.setFullscreenMode(modes[0])
}
....
}
To summarize i get the list of modes, i pull from preferences what was set last, and i filter the list according to what was in preferences. This should leave one item left in the list and i apply it. If for some reason the list is empty, then i don't set it, or there is no preference set i just apply the current mode again.
This is where the weird stuff happens. I have checked all the numbers when creating my screens and cameras, and they are all correct. I do receive the correct resolution, but the application doesn't render correctly. Below are a couple examples of what happens.
In the first image you see the bounds of the application to the screen. My application only renders in the bottom corner, and the rest is black. What happened to achieve this effect is i started the application with a smaller resolution than my native resolution, so 1280x1024, then in my create method i set the application full screen mode to 1920x1080 before building the rest of my application. I have checked my cameras and my viewports, and they all have the resolution 1920x1080, but the image is not filling the entire screen.
And a second.
This one is what happens when i reverse the settings. So i start at native resolution 1920x1080, and in my create method i set it to 1280x1024, again before creating the rest of my application. This gives me black bars on both sides of the image like id expect, but the application is HUGE, and only a portion of it fits in the window, the rest goes out of bounds, as depicted by the dotted lines.
It will remain like this the entire time, unless i change the resolution while the application is running, it will then correct itself for the rest of the applications life.
I am confounded by this effect i am getting, and am looking for an answer as to why, or how to fix it.
I found the issue that was causing the image to render incorrectly. I was setting the display mode in the create() function in my main game class. This function is not run on the rendering thread, and you do not want to use Gdx.graphics on anything other than the rendering thread, as described in the libgdx wiki https://github.com/libgdx/libgdx/wiki/Threading
There is a function where you can pass in a lambda to be run on the rendering thread.
Gdx.app.postRunnable {
Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode(modes[0]))
}
After passing that into postRunnable the game renders correctly on launch.

StageWebView Flash's White when Displayed

StageWebView Flash's White when Displayed
So I've been working on a project using Adobe Animate to create a universal Air application that can be ported to multiple platforms i.e. Mac, Windows, and iOS.
It uses StageWebView to display videos embedded on HTML pages that have their own custom html5 video player and everything works well except for one simple but annoying thing.
Whenever I display a Stage Web View you'll see a flash of white before the page displays.
Now I originally thought this was an issue with checking for a URL load completion or a poorly formatted HTML document but that doesn't seem to be the case.
What I did notice after several attempts of trying to remove the issue is that it did go away if I used the embedded Air WebKit opposed to using the native WebKit from the desktop device.
(Code Below) Causes white flash on load:
var webView:StageWebView = new StageWebView(true);
(Code Below) This gets rid of the issue but my HTML tags like video and progress are not supported by the embedded WebKit and no longer function properly.
var webView:StageWebView = new StageWebView();
Information from about the setting from Adobe:
useNative:Boolean (default = false) — When useNative is false, a version of WebKit embedded within AIR is used as the source of the
StageWebView created. When useNative is true, then AIR will use the
the system's default web engine. Mobile platforms only support using
the system web engine, so useNative is ignored on mobile platforms.
The frustrating thing is that I've set a listener to check for load completion and that doesn't get rid of the issue. So as a workaround I've hidden the displayed StageWebView off the screen and then moved it's location to where I want it to be after a delay which is not great.
Other attempts to display it small as a pixel resize it in place cause the issue still.
/* Check for Stage Web View Errors */
webView.addEventListener(ErrorEvent.ERROR, onError);
function onError(e:ErrorEvent):void {
trace("Stage Web View error: " + e);
}
/* Function to not show Stage Web View until loaded. */
function onCompleteHandler(e:Event):void {
webView.assignFocus();
// Delay the Stage Web View to fix white flash issue.
setTimeout(callWebView,500);
webView.removeEventListener(Event.COMPLETE,onCompleteHandler);
}
/* Multi-Function Stage Web View Loader, Just add file path string to call */
function webviewFilePath(path:String):void {
webView.stage = this.stage;
// Prep filepath
filePath = new File(new File(path).nativePath).url;
// Load file path
webView.loadURL(filePath);
// Add listener for Complete URL Load then Show
webView.addEventListener(Event.COMPLETE,onCompleteHandler);
}
/* Function to call Stage Web View independantly so it can be delayed with a timer */
function callWebView() {
webView.viewPort = new Rectangle(posX(viewX), posY(viewY), viewWidth, viewHeight);
}
Any hints or tips on how I can alleviate or fix the issue would be great.
Of course if Adobe just actually updated the embedded Air WebKit that would probably fix the whole issue in the first place but I doubt that's happening anytime soon.
Partial Fix
So the issue still exists when I initially load up the Stage Web View but I've managed to minimize its appearance during app use.
One major part of the issue was how I reset the StageWebView in preparation for a new page I wanted to load or when I wanted to close the view.
I went a little overboard on resetting StageWebView because audio in StageWebView has been known to continue playing even when it's hidden.
/* Function to Reset Stage Web View */
function resetWebView():void {
webView.loadString("<!DOCTYPE HTML><html><body></body></html>");
//webView.viewPort = new Rectangle(0, 0, 0, 0);
webView.stage = null;
//webView.viewPort = null;
}
I realized I could just simply hide the StageWebView and load up a blank page while it was hidden from view to stop any audio playing. That was easy enough to accomplish with a simple string loaded into it.
Although from time to time I'll still see that white flash it's occurrence is minimal.
private var webView : StageWebView;
webView = new StageWebView( true );
webView.stage = this.stage;
webView.viewPort = new Rectangle( 0, 0, 1024, 768 );

How create fully responsive html5 game using Phaser library?

I'm using Phaser 2.5.0 (tried 2.4.8 also) and I'm trying to create fully responsive game using phaser library.
Everything is ok when I refresh page, here is image:
but when I change rotation to portrait dialog message is not ok, image:
When I refresh page using portrait mode I get ok dialog:
So problem is when I resize browser window.
Here is code for init phaser game:
var game = new Phaser.Game(window.innerWidth, window.innerHeight, Phaser.AUTO);
Tried also:
var game = new Phaser.Game("100%", "100%", Phaser.AUTO);
Here is create function located in main.js:
create: function(){
console.log('create');
this.game.antialias = true;
this.game.stage.smoothed = true;
this.input.maxPointers = 1;
this.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
this.scale.minHeight = 0;
this.game.time.advancedTiming = true;
},
So to tell again problem is when I resize browser window but when I do refresh then it's not working ok. Game must support resize.
Here is one simple example which is giving almost same result, on refresh is ok but when doing resize is not ok: https://jsfiddle.net/CroDac/tv010u0t/
Thank you
There was/is an old, but apparently not fixed, bug in iOS that caused (causes?) this. There are several workarounds on the net, on of them is here:
https://github.com/scottjehl/iOS-Orientationchange-Fix
From the description:
This fix works by listening to the device's accelerometer to predict
when an orientation change is about to occur. When it deems an
orientation change imminent, the script disables user zooming,
allowing the orientation change to occur properly, with zooming
disabled. The script restores zoom again once the device is either
oriented close to upright, or after its orientation has changed. This
way, user zooming is never disabled while the page is in use.
Maybe this can help you....

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

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;

UIViewController device rotation delegate methods are not getting called in iOS5

I am developing an iPhone application. In this application, UIViewController (vc1) presents another UIViewController (vc2). vc1 supports both Portrait and Landscape orientations; vc2 supports only Portrait orientation.
When vc2 is presented, it asks vc1: shouldAutorotateToInterfaceOrientation: and this returns YES
In iOS5 (Beta 7) willRotateToInterfaceOrientation:, didRotateFromInterfaceOrientation: are not getting called for this sequence. But, this works fine in iOS4. Is this a bug in iOS5?
I had reported a bug to Apple and I got the following reply:
"Engineering has determined that this issue behaves as intended based on the following information:
The presentation behavior is correct - if it behaved differently in previous versions, that was a bug. The arguably unexpected change in behavior regards the dismiss of VC1 which no longer gets rotation callbacks but it will layout in portrait.
There are other ways to determine what your orientation is when a view controller lays itself out. For various reasons, relying on the rotation callbacks proved to be problematic.
In general, viewController rotation callbacks occur in two cases:
The device orientation changes for view controllers in the window hierarchy
Mixed interface orientation presentations. (Bottom controller only supports portrait, device is in landscape, and a view controller that supports landscape is presented.) However this is arguably a misfeature.
Try using viewWillLayoutSubviews: in iOS 5."
I had faced a similar issue when testing my app on iOS5. The layout of subviews in the main view controller used to get messed up if the orientation changed when a modal view controller was active.
What I did was to store the current orientation flag in the main controller. This flag is updated in two places in the main controller
willAnimateRotationToInterfaceOrientation:
viewWillLayoutSubviews (this is on iOS5 only)
I write all the logic to adjust the subviews by comparing the current orientation with the stored value. If they are different - update the stored orientation, update your subviews.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Any orientation is OK
return YES;
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
portrait = UIInterfaceOrientationIsPortrait(toInterfaceOrientation);
// Code to update subview layout goes here
}
-(void)viewWillLayoutSubviews
{
BOOL isPortraitNow = UIInterfaceOrientationIsPortrait(self.interfaceOrientation);
if(isPortraitNow != portrait)
{
DLog(#"Interfaceorientation mismatch!, correcting");
portrait = isPortraitNow;
// Code to update subview layout goes here
}
}