Scaling for Mobile



  • Any way to make a scale mode where the black bars are not present? I come from Corona SDK, but I love Haxe and HaxeFlixel looks great! However, I have one big problem. That is, all the scale modes create black bars either on the top and bottom or left and right. I am looking for a scale mode that will letterbox just like RatioScaleMode, but will allow overflow on the sides. That is to say, images that are where the black bars are now should be visible rather than have black space there. This is to put filler so that the app will look fine on all devices. If you have any questions, ask away. Thanks.



  • I was also thinking that perhaps I could do something with the camera to see view the empty space. But that does not seem do-able.


  • administrators

    I am looking for a scale mode that will letterbox just like RatioScaleMode, but will allow overflow on the sides

    Check out what parameters RatioScaleMode's constructor has. ;)

    http://api.haxeflixel.com/flixel/system/scaleModes/RatioScaleMode.html



  • @Gama11 Thanks for the reply! And I have toyed around with the fill screen version of RatioScaleMode. The issue with that is that it cuts off the top part when scaling. What I'm specifically looking for is RatioScaleMode(false) with the option to show what's behind the black bars. Is this even possible, do you think? This engine will be close to perfect for me if it is. I'm curious as to how everybody manages to get everything to work properly on their apps with HaxeFlixel. The only example I have been able to find is Flappybalt, and that shows the black bars on some devices. Thanks again!


  • administrators

    Ah, I see. Could you perhaps place a openfl.display.Sprite behind the FlxCamera sprite to achieve the same effect? Let's take Flappybalt for example, by default it looks something like this:

    With a background Sprite and the camera bgColor made transparent:

    For this, I inserted this code after // The background city in PlayState.hx:

    // The background city.
    
    var bg = new FlxSprite(0, 0, "assets/bg.png");
    //add(bg);
    bgColor = flixel.util.FlxColor.TRANSPARENT;
    
    var sprite = new openfl.display.Sprite();
    // create a repeating background
    sprite.graphics.beginBitmapFill(bg.pixels, null, true);
    sprite.graphics.drawRect(0, 0, FlxG.stage.stageWidth, FlxG.stage.stageHeight);
    sprite.graphics.endFill();
    // -1 because we have one camera sprite to "skip"
    FlxG.addChildBelowMouse(sprite, -1);
    
    // make sure to remove() this signal listener in destroy()
    FlxG.signals.gameResized.add(function(_, _) {
    	var scale = FlxG.scaleMode.scale;
    	sprite.scaleX = scale.x;
    	sprite.scaleY = scale.y;
    
    	var offset = FlxG.scaleMode.offset;
    	sprite.x = -offset.x;
    	sprite.y = -offset.y;
    });
    


  • I think that ultimately the scaling system described in this blog post is what we need to be able to achieve in HaxeFlixel but I don't think it can be done with the currently imposed scaling system.



  • @Gama11 Definitely looks close to what I'm looking for! I'll have to try it when I have access to my computer again. @cg-tv definitely has what I'm looking for in that blog. I think there should be a scale mode that works like that. And I created something similar building off of the SceneSizeScaleMode. I made it work, but there was some really weird parts about the code that I had to write that maybe you could clear up. I'll put the code up when I get to it, and maybe you can clear part of it up for me.



  • @Gama11 Here's the code for the scale mode that works, Gamma.
    Made edit to code

    package scaleModes;
    
    import flixel.FlxG;
    import flixel.system.scaleModes.RatioScaleMode;
    
    class ProperMobileScaleMode extends RatioScaleMode
    {
        override public function onMeasure(Width:Int, Height:Int):Void
        {
            // if (FlxG.camera != null) {
            //     FlxG.camera.setSize(Width, Height);
            // }
    
            FlxG.width = Width;
            FlxG.height = Height;
    
            scale.set(1, 1);
    
            if (FlxG.camera != null)
            {
                var oldW = FlxG.camera.width;
                var oldH = FlxG.camera.height;
                
                var newW = Math.ceil(Width / FlxG.camera.zoom);
                var newH = Math.ceil(Height / FlxG.camera.zoom);
                
                FlxG.camera.setSize(newW * 100, newH * 100);
                FlxG.camera.flashSprite.x += (newW - oldW) / 2;
                FlxG.camera.flashSprite.y += (newH - oldH) / 2;
            }
    
            super.onMeasure(Width, Height);
        }
    }
    

    And it looks like this:
    https://drive.google.com/open?id=0B_idKVdY1hEmZlA2dkdTTU5mWFU
    https://drive.google.com/open?id=0B_idKVdY1hEmOTZnRVFYLU5GajQ

    Notice that I can draw outside the bounds of everything and it scales properly.

    Notice the line:

    FlxG.camera.setSize(newW * 100, newH * 100);
    

    The odd bit is that if I don't multiply the newW and newH by 100 (an arbitrary number, 75 and anything higher also works), I get this result:
    https://drive.google.com/open?id=0B_idKVdY1hEmMEJhMDkxLVFLWTA
    https://drive.google.com/open?id=0B_idKVdY1hEmZnEwMDhXM1pjM0E

    Notice how the graphics get cut into. How do I write this without using arbitrary numbers, and why are the graphics getting cut into? Part of what I'm asking is how to make this cleaner and more reliable. I'd rather not use code that I wrote that I don't understand haha. Thanks.

    PS. Remember that you must set the value for the resolution you're developing for in Main.hx when you declare a new FlxGame with PlayState.



  • @cg-tv Check the code above, and see if it works for you, friend.



  • @Twonty2 I'll give it a try this weekend. I don't have a minute to spare till then.



  • @Twonty2 I gave your code a try but it doesn't seem to work.

    Using a phone with a 480x320 resolution I created a background image with dimensions 500x340.

    My expectation was that the image would be centered in the screen with all 4 edges being clipped, but instead the top/left edge of the image was drawn at screen coors. 0,0 and only the right and bottom edges were clipped.

    Was my expectation wrong?

    Looking at the first 2 images you posted my expectation does not appear to be wrong.

    Could you post the project files for your test app so I can compare your code to mine?

    Thanks.



  • @cg-tv Yes, here is a link to the project https://drive.google.com/file/d/0B_idKVdY1hEmVWt6Z3pjM00zRWs/view?usp=sharing.

    I believe you are expecting the right thing. You must make sure that the default height is defined either in project or Main.hx. Let me know how it goes.



  • @cg-tv actually, I think perhaps your expectation was wrong. It should be centered, but any sprites drawn can be drawn outside of the bounds of the resolution that is being developed for. Try the project anyway, and see if it clears it up how it should work.



  • Hi, I gave your code a try and it works just as the images you linked above show, but if you look at your makeGraphic call for the background, you're creating a background that's the same size as the target resolution and then drawing it at 0,0 so there is no centering needed.

    If you replace the makeGraphic call with a loadGraphic call and use a bitmap image that's larger than the target res, you'll see that it's not being centered in the way the blog post I linked to above describes. It's still just drawing it at 0,0.

    Maybe we have different expectations. I found a blog post for a Unity plugin here that does a much better job of explaining what I was hoping your code would do.

    Give it a quick read and see if we're talking about the same thing.

    Thanks.



  • @cg-tv man, if you want to have centered image - use offset, idk.

    var offset = FlxG.scaleMode.offset;
    var bg_sprite = new openfl.display.Sprite();
    bg_sprite.graphics.beginFill(0xC7BA99, 1);
    bg_sprite.graphics.drawRect(-offset.x, -offset.y, FlxG.stage.stageWidth, FlxG.stage.stageHeight);
    bg_sprite.graphics.endFill(); 
    

    i think you got the idea.



  • @cg-tv I read the post, and I think we have the same expectations. That project was kind've a quick scaleMode I made to demonstrate my point. But that Unity article is exactly what I'm trying to get at. Test anything other than the main graphic there. The one game engine I have seen do this just about perfectly is Corona SDK. It's exactly what we're looking for, and I'm trying to get something just like that. If I can find something to read on Corona SDK's scaling, I'll send it your way.



  • Thanks Fyfff but it's not really about centering the image but more about maximizing the play area without any of it getting cropped off and also without having black bars.

    Technically the letterboxing/pillarboxing is there but it's filled in with the oversized background image.

    The Unity plugin that I linked to does exactly that, but unfortunately, it's looking to me like this may be the most complicated part of the HaxeFlixel framework. Over my head at least.



  • @cg-tv HaxeFlixel is not so handsome in mobile development :C


Log in to reply