I have worked so hard on an app that displays perfectly on my Galaxy Note 3. However, it does not display right on iPhone and also one other Droid I tested on. My issue is with addChild() and then resizing it to fit the screen. For some reason when I add the Background (addBG(); The screen size works but if I load addChild to the BG, this works great on my Note 3 but not on the iPhone or another android device.
My issue is with the screenX, screenY var I created. They seem to be different for devices. Or it is a "rendering order issue" I am not sure. Would be so greatful for the help to fix this issue so it looks great on each phone. I have read some tuts on this subject but they are confusing. I think my code is close, I hope, and maybe it just needs a tweak. !
Here is a shot of the about screen on an IPhone. See the white does not fit the whole screen.
and Here is a shot from my Droid Note 3.
Declared Vars in a package:
This is not my full code, of course but only that which I believe is relevant.
public var screenX:int;
public var screenY:int;
public function Main()
{
if (stage)
{
setStage();
addBG();
}
}
public function setStage()
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
if (flash.system.Capabilities.screenResolutionX > stage.stageWidth)
{
screenX = stage.stageWidth;
screenY = stage.stageHeight;
}
else
{
screenX = flash.system.Capabilities.screenResolutionX;
screenY = flash.system.Capabilities.screenResolutionY;
}
}
This works: addBG();
public function addBG()
{
theBG = new BG();
addChild(theBG);
theBG.width = screenX;
theBG.height = screenY;
}
This does not: addAbout();
public function addAbout()
{
About = new viewAbout();
About.width = screenX;
About.height = screenY;
theBG.addChild(About);
TweenMax.fromTo(About,1, {alpha:0}, {alpha:1, ease:Expo.easeOut} );
}
UPDATE: And yet another more complex load is also called from a button and having the same issue. I hope you see the logic of what I am trying to do. First set the BG to the device then load and resize content to fit proportionally into the BG I loaded. The reason being, the BG will be distorted to different proportions and that's ok, but the content can not. So here is the example that loads content into the BG and then content into that container.
public function addRosaryApp()
{
Rosary = new viewRosaryApp();
Rosary.width = screenX;
Rosary.height = screenY;
theBG.addChild(Rosary);
TweenMax.fromTo(Rosary,1, {alpha:0}, {alpha:1, ease:Expo.easeOut} );
contentRosary = new contentRosaryApp();
theBG.addChild(contentRosary);
contentRosary.width = screenX;
contentRosary.scaleY = contentRosary.scaleX;
contentRosary.x = screenX/2 - contentRosary.width/2;
contentRosary.y = menuBanner.height;
}
Have you tried adding the child to stage first, and then setting the size? That's the only difference I can see between addBG and addAbout
About = new viewAbout();
theBG.addChild(About); // do this first
About.width = screenX; // then set width
About.height = screenY; // and height
I think your problem may have to do with either of several things.
My findings so far from my own devices (an Ipad Air, an iphone 4S, an LG G2 and an Acer Iconia A500) is that the only device size that's being reported correctly at all times is the stage.fullScreenWidth and the stage.fullScreenHeight
1st, Android reports Capabilities.screenResolutionX as the LONG side of your Android device.
IOS devices however report the SHORT side of your device to Capabilities.screenResolutionX.
2nd, stage.stageWidth and stage.stageHeight seem to report the wrong size on both Android and IOS.
And in fact if you check these before and after setting stage.scaleMode and stage.align then the values will differ completly (although Android will show it almost correctly).
My suggestion is that you set a base size (width and height) for your app and then compare it with the actual stage.fullScreenWidth and stage.fullScreenHeight reported by the device. That way you can get some nice scaleratios to use to scale your displayobjects. That's what I'm currently on my apps and it scales just fine :-)
Related
So, I'm building fairly simple application for portrait mode only, and it will have vertical scrolling for content.
Content is basicly a MovieClip containing image as background and other minor elements (couple small MovieClips as buttons etc).
The problem is that I don't seem to find a smooth way to scroll my content. I would love it to be smooth and accurate, and I've tried numerous different ways for it.
For testing purposes the background I'm using (inside my content MovieClip) is 533x1250 jpg from library.
This is how I add my content mc and backround into it:
scaleXFactor = stage.stageWidth / 640; //my stage is 640x960
...
addChild(content); //which is new MovieClip()
var bg:bg1 = new bg1();
bg.x = p1bg.y = 0;
bg.width = 640 * scaleXFactor;
bg.scaleY = bg.scaleX;
content.width = bg.width;
content.height = bg.height;
content.addChild(bg);
For scrolling I assumed I'd be safe by just simply using MOUSE_DOWN & MOUSE_UP event listeners and basic ENTER_FRAME function like this:
mouseLastPos = stage.mouseY;
if(MouseUpVar == 1){
mousePosDiff = (mouseOriPosY-mouseLastPos);
}
content.y -= mousePosDiff*1.2;
mouseOriPosY = stage.mouseY;
if(MouseUpVar == 0){ //Smoothening which is allowed by MOUSE_UP
if(mousePosDiff > 0){
mousePosDiff -= 0.001;
}else if(mousePosDiff < 0){
mousePosDiff += 0.001;
}
}
if(content.y < (content.height - stage.stageHeight)*-1){
content.y = (content.height - stage.stageHeight)*-1;
}else if(content.y > 0){
content.y = 0;
}
In debug player it's as smooth as you can ever imagine, but in real device (Samsung Note4) it's very laggy and clumsy.
I've also tried freshplanet's script, which is not as laggy, but still a little clumsy, and messes up my scaleY for some reason.
And IScrollerComponent seems to have some issues on AIR, and I didn't get any visual elements on my screen with it.
Rendering settings or cacheAsBitmap didn't seem to have any effect on this.
How should this be done right? Is it normal that this 'small' image (533x1250) causes bad lag?
I really need to use AS3 and AIR for this, so I'm hoping to find a good and "simple" solution (yeah, that doesn't happen too often).
Thanks,
kaarto
Try using cacheAsBitmap=true on your content and scrollRect instead of moving your content.
I have a "2D" scene (Z pointing up) with a plane geometry as the game arena set like this:
var arenaMesh = new THREE.Mesh(
new THREE.PlaneGeometry(SceneWidth, SceneHeight),
new THREE.MeshLambertMaterial({
map: arenaTexture,
emissive: 0xffffff
}));
arenaMesh.position.x = SceneWidth / 2;
arenaMesh.position.y = SceneHeight / 2;
arenaMesh.position.z = 0;
arenaMesh.receiveShadow = true;
The game object is set like this (a really flat box):
var size = 20;
var bodyMesh = new THREE.Mesh(
new THREE.BoxGeometry(size, size, 0.01),
new THREE.MeshLambertMaterial({
map: bodyTexture,
alphaTest: 0.65,
emissive: 0xeeeeee
}));
bodyMesh.position.x = x0;
bodyMesh.position.y = y0;
bodyMesh.position.z = 5.0;
bodyMesh.castShadow = true;
I'm using BoxGeometry here due to some shadow problems I had before.
Now, the problem is that this works perfectly fine on my desktop (FF and Chrome): my fake 2D game object is rendered and it casts a shadow on the game arena. However, on Nexus 7 I can see only the shadow of the object! After some debugging, I noticed that If I set the z-position of the game object to a much bigger value, like z=15.0 it gets rendered. Unfortunately this is not acceptable, because then the object seems like it's flying. Lowering the game arena plane to e.g. z=-15.0 has the same effect. What the heck could cause this? I seems like the precision is somehow completely lost there. Why is the shadow still there correctly?
Based on the comments added to my question, the solution for the problem was to set zNear to a higher value. Apparently the ratio of zNear and zFar affects the precision of Z-buffer and thus fixes problems on Nexus 7.
I'm developing in qt 5.3 on android device. I can't get the screen resolution.
With the old qt 5 version this code worked:
QScreen *screen = QApplication::screens().at(0);
largh=screen->availableGeometry().width();
alt =screen->availableGeometry().height();
However now it doesn't work (returns a screen size 00x00). Is there another way to do it? thanks
Size holds the pixel resolution
screen->size().width()
screen->size().height();
Whereas, availableSize holds the size excluding window manager reserved areas...
screen->availableSize().width()
screen->availableSize().height();
More info on the QScreen class.
for more information, screen availableSize is not ready at the very beginning, so you have to wait for it, here is the code:
Widget::Widget(QWidget *parent){
...
QScreen *screen = QApplication::screens().at(0);
connect(screen, SIGNAL(virtualGeometryChanged(QRect)), this,SLOT(getScreen(QRect)));
}
void Widget::getScreen(QRect rect)
{
int screenY = screen->availableSize().height();
int screenX = screen->availableSize().width();
this->setGeometry(0,0,screenX,screenY);
}
I found that there are several ways to obtain the device resolution, each outputs the same results and thankfully works across all Os-es supported by Qt...
1) My favorite is to write a static function using QDesktopWidget in a reference class and use it all across the code:
QRect const CGenericWidget::getScreenSize()
{
//Note: one might implement caching of the value to optimize processing speed. This however will result in erros if screen resolution is resized during execution
QDesktopWidget scr;
return scr.availableGeometry(scr.primaryScreen());
}
Then you can just call across your code the function like this:
qDebug() << CGenericWidget::getScreenSize();
It will return you a QRect const object that you can use to obtain the screen size without the top and bottom bars.
2) Another way to obtain the screen resolution that works just fine if your app is full screen is:
QWidget *activeWindow = QApplication::activeWindow();
m_sw = activeWindow->width();
m_sh = activeWindow->height();
3) And of course you have the option that Zeus recommended:
QScreen *screen = QApplication::screens().at(0);
largh=screen->availableSize().width();
alt =screen->availableSize().height();
Google suggests that the following is not that uncommon a question: having loaded something into a Flash stage using a Loader, I want to resize it. However, if you do this before the content is loaded, resizing the image causes it to disappear.
The proposed solution is usually to use an Event listener for Event.COMPLETE. Here's my code:
public function FlixelTest()
{
super();
// support autoOrients
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
myLoader = new Loader();
myLoader.x = (stage.fullScreenWidth-640)/2;
myLoader.y = (stage.fullScreenHeight-480)/2;
addChild(myLoader);
var url:URLRequest = new URLRequest("stuff.swf");
myLoader.load(url);
myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadProdComplete);
}
function loadProdComplete(e:Event):void{
myLoader.height = 480;
myLoader.width = 640;
}
According to every posting I can find so far online, this solution should work. When the event fires, the Loader is done, and can be resized. However, it doesn't. Commenting out the lines that modify .height and .width cause the SWF to appear, uncommenting them and running again and the SWF never loads.
Could anything else be interfering here? This is using FlashBuilder to construct an Actionscript3 -> Android project.
EDIT - The solution here doesn't appear to work either: Problem resizing loader after loading swf
UPDATE - I have a working, and horrific, solution that is as followed:
function loadProdComplete(e:Event):void{
if(myLoader.width != 0){
myLoader.width = 640;
myLoader.content.width = 640;
}
else{
timer = new Timer(500);
timer.addEventListener(TimerEvent.TIMER, timertick); // there should be a comma here but yahoo replaces it with ...
timer.start();
}
}
function timertick(e:TimerEvent){
timer.stop();
stage.dispatchEvent(new Event(Event.COMPLETE));
}
It basically uses the content's width to see if it's finished loading. If it hasn't, it waits a half second and refires the COMPLETE event. This actually helps display it (although the width hasn't been adjusted, I assume that's a separate issue) - I can't believe this is the only way to get it working...
While not strictly a solution, the way I've circumvented this is by not resizing it at all - I am instead cropping an area over the window so all that's seen is the section I wanted to display.
function loadProdComplete(e:Event):void{
var gameMask : Shape = new Shape;
gameMask.graphics.beginFill(0xffcc00);
gameMask.graphics.drawRect(myLoader.x,myLoader.y,640,480);
gameMask.graphics.endFill();
myLoader.content.mask = gameMask;
}
Since the mask would've been necessary for me anyway to hide off-stage clutter, this solved two problems at once.
I won't accept this as the answer in case anyone has any alternative insights, but if anyone comes across this question, this is a posisble solution.
Actually, I am bothering the problem of screen size of phonegap apps.
I have found a solution from this site (http://ryangillespie.com/phonegap.php).
By using javascript and the feature of css3, it works.
The code is following:
var designWidth = 480; // zoom to fit this ratio
var designHeight = 762; // not 800 b/c top bar is 38 pixels tall
var scaleChange = 1; // % change in scale from above #s
function zoomScreen() {
var docWidth = window.outerWidth;
var docHeight = window.outerHeight;
if (docWidth != designWidth) {
var scaleX = docWidth / designWidth;
var scaleY = docHeight / designHeight;
if (scaleX < scaleY) {
$('body').css('zoom', scaleX);
scaleChange = scaleX;
} else {
$('body').css('zoom', scaleY);
scaleChange = scaleY;
}
}
}
But, the problem is: it only behave correctly in the initial run. When I shut down the app and restart it, the screen size behave wrong.
There is also one more weird behavior. After I try to reload the page by
window.location.reload()
The screen size behaves correctly.
How to fix it?
This is my first post. If I miss some of the information, I would clarify.
That method might only be called when the app creates the view initially, depending on how you have the app working, there may be an 'onCreate' or 'onSurfaceCreated' method that is getting called to correctly set the changes. Then when you bring the app up again, the surface has already been created, and so that app doesn't try and re-create it and somehow it's not in the right state. If you determine that you need to reload the settings every time, have the app call that reload method in the 'onSurfaceModified', or 'onResume', or whatever, or try to figure out how the view is getting modified between runs.