[RESOLVED]What is the trick to make an app fit all screen size?

@player_03

Do you work with width/height or scaleX/Y when resizing it in the event callback? The reason I am asking is to figure out the best way. Do I have to worrry about other transformations when scaling for the new stae size?

Btw stage.scaleMode produces emtpy screen on Android, but works on Linux.

Assuming your app has a hard-coded native resolution:
Listen for the screen resize event

Measure the aspect ratio of the current device window (stageWidth/stageHeight).

create a new container that has the dimensions of your native resolution, but stretch the height or width to match the same aspect ratio as the device window. Note that we are just matching the aspect ratio for now, not blowing up to the full screen size.

fill the container with an empty black bitmap

center your entire game inside of this container (this also assumes that your game is contained within its own sub-container).

THEN, just scale that container upward/downward to match exact width and height of the device’s window. because your game is nested inside of the container, it will maintain your native aspect ratio while expanding to fit the device window.

2 Likes

I am targeting Android and at this point I feel like probably the best way is to create the sprites and images with the proper aspect ratio and the placements from the get go. This resizing afterwards sounds more like a desktop way. Am I wrong on this when it comes to mobile? Get the aspect ratio and use it as a leverage to place things properly in the beginning (working with percentages rather than absolute coords) unless one does a bitmap scale as @afroninjadotcom described, at least that is what I understood from his post.

@afroninjadotcom
Please correct me if I misunderstood your points.

Create a new bitmap in the main sprite, copy the scaled current bitmap rendered in the current sprite to the new empty bitmap. And remove the old bitmap.

I implement the above logic on all major targets- flash, desktop, android, and ios.

Don’t get me wrong there are certainly advantages to targeting different resolutions in a dynamic fashion but it’s always been a complete headache for me. I think it applies to functional apps, but for games it’s usually easier to just scale your entire output accordingly (just my opinion though)

I don’t copy any bitmaps- I place my entire game inside of a sprite, then place that sprite into an adjustment container. I then scale the adjustment container to fit the desired resolution.

AfroNinja: what’s the difference between your implementation and StageScaleMode.SHOW_ALL? The only difference I can find is that your implementation would let you center it. And even then it would be easier to make a workaround to center it:

//Insert your values here:
private static inline var NOMINAL_WIDTH:Int = 800;
private static inline var NOMINAL_HEIGHT:Int = 600;

public function new() {
    super();
    
    //...
    
    stage.scaleMode = StageScaleMode.SHOW_ALL;
    #if flash
        stage.align = untyped "";
    #else
        stage.addEventListener(Event.RESIZE, onResize);
    #end
}

private function onResize(e:Event):Void {
    var stageScaleX:Float = stage.stageWidth / NOMINAL_WIDTH;
    var stageScaleY:Float = stage.stageHeight / NOMINAL_HEIGHT;
    
    var stageScale:Float = Math.min(stageScaleX, stageScaleY);
    
    Lib.current.x = 0;
    Lib.current.y = 0;
    if(stageScaleX > stageScaleY) {
        Lib.current.x = (stage.stageWidth - NOMINAL_WIDTH * stageScale) / 2;
    } else {
        Lib.current.y = (stage.stageHeight - NOMINAL_HEIGHT * stageScale) / 2;
    }
}

I’ve confirmed that this behaves as expected on Flash, Neko, and Windows.

It’s possible that the OpenFL “next” will provide a StageAlign.CENTER property, making this even easier.

1 Like

I guess nothing, I didn’t realize it would be that easy to center with the SHOW_ALL value :smile:
also didn’t realize you could move the stage itself with Lib.current.x/y.

It’s not the actual stage. Lib.current is a movie clip created and managed by OpenFL, and your Main class is automatically added as a child of it (except in Flash).

So unless you add children directly to the stage, Lib.current can serve as a parent of everything in the display list.

@player_03
I tried using StageScaleMode for Android but it gives me a blank screen, but it works on Linux Desktop. Maybe not supported on Android?

@afroninjadotcom
Do you have a basic code to show how you do it? I have just started using OpenFL (and no prior as experience), so I do not know all the nitty gritty details of OFL at the moment.

thanks

Ok, then I guess you can try it AfroNinja’s way:

//Insert your values here:
private static inline var NOMINAL_WIDTH:Int = 800;
private static inline var NOMINAL_HEIGHT:Int = 600;

public function new() {
    super();
    
    //...
    
    #if flash
        stage.scaleMode = StageScaleMode.SHOW_ALL;
        stage.align = untyped "";
    #else
        stage.addEventListener(Event.RESIZE, onResize);
        onResize(null);
    #end
}

private function onResize(e:Event):Void {
    var stageScaleX:Float = stage.stageWidth / NOMINAL_WIDTH;
    var stageScaleY:Float = stage.stageHeight / NOMINAL_HEIGHT;
    
    var stageScale:Float = Math.min(stageScaleX, stageScaleY);
    
    Lib.current.x = 0;
    Lib.current.y = 0;
    Lib.current.scaleX = stageScale;
    Lib.current.scaleY = stageScale;
    
    if(stageScaleX > stageScaleY) {
        Lib.current.x = (stage.stageWidth - NOMINAL_WIDTH * stageScale) / 2;
    } else {
        Lib.current.y = (stage.stageHeight - NOMINAL_HEIGHT * stageScale) / 2;
    }
}

I should note that I’m testing in OpenFL 2.2.8, not OpenFL 3.

4 Likes

@player_03

I have no idea but this is segfaulting on Linux ;(

I think it is something about this portion

 if(stageScaleX > stageScaleY) {
            Lib.current.x = (stage.stageWidth - FRAME_NOMINAL_WIDTH*stageScale)/2;
        } else {
            Lib.current.y = (stage.stageHeight - FRAME_NOMINAL_HEIGHT*stageScale)/2;
        }

progress: I have some actual text on the images, so removing them stopped the segfault which is weird. But now changing the size turns the window into an empty screen.

progress_2:
ok now it seems like all the values are returning inf
Main.hx:115: 1,1
Main.hx:157: resizing,inf,inf,inf (stageScale, stageScaleX,stageScaleY)
bizarre I will infestigate more

I doubt it’s that part, because that was there before and you said it worked on Linux.

Try commenting this part instead:

Lib.current.scaleX = stageScale;
Lib.current.scaleY = stageScale;

If that doesn’t change anything, try adding these two haxedefs to help debug the segfault:

<haxedef name="HXCPP_STACK_LINE" />
<haxedef name="HXCPP_CHECK_POINTER" />
1 Like

If the scale values are infinity, that suggests that NOMINAL_WIDTH and NOMINAL_HEIGHT are 0.

@player_03

Sorry about the fuss, I had 2 issues. I had to initiate the nominals and then cleaning and making a fresh build of linux target solved the segfault. No idea I seem to get segs here here there and clean build solves that issue.

Your solution is perfect for me for now, Thanks again for your dedicated solution.

Sorry to come up with so many troubles :frowning:

So the resizing seem to work with Android with couple issues. But the biggest issue to me is that the mouse touch event (mousedown moving) moves in an bizarre fashion. For example I click on an image then start moving it but the image moves fast to its left or right as in it is accelarating when it moves from the click center. Linux build has the same issue`.

This was not the case when I was using a non resized Window. It is peculiar.

Try using a window width and height of 0 in order to handle the resize and screen scale yourself on mobile

You’re probably handling the mouse event incorrectly. I assume you’re checking either e.mouseX and e.mouseY or stage.mouseX and stage.mouseY, right? Instead of that, you want to use image.parent.mouseX and image.parent.mouseY.

Post your code if you need more clarification.

1 Like

man so many awesome people here. Thanks for the tips. That gives me the right kind of heads up.

Thanks you all, @player_03 and @afroninjadotcom.
it works like a charm :slight_smile:
though I don’t quite understand the need for:

  • stage.align = untype “”;
  • and onResize(null);
    But thank you really!

It’s not in the documentation, but in Flash, you can center the stage by setting stageAlign = "". However, Haxe wants you to use an enum value, so you have to use untyped to make it ignore that.

onResize(null) is to resize the stage instantly. On Android, the stage will start at a different width and height, but you won’t get a RESIZE event until they rotate the device.

1 Like

Just want to add that I was using this solution. And it seems like it conflicts with the project.xml tag :

window allow-high-dpi=“true”

I had to remove the above tag to make the solution work. Took me much time to figure out.

1 Like