AutoFit (update)Monkey General Forums/Monkey Code/AutoFit (update)
| Here's an update to my AutoFit example from the Monkey distribution, which scales a fixed virtual display size to the current device size, adding black borders where needed, taking aspect ratio into account.|
The old version recalculated pretty much everything on every update; now it just does a few checks and recalculates only when the device or zoom level has changed, something I've meant to sort out for ages. This is the new typical codepath (after the first call):
Method UpdateVirtualDisplay (zoomborders:Bool, keepborders:Bool) If (DeviceWidth <> lastdevicewidth)... ' Early out here and nothing to do... If device_changed... ' Nothing to do here... If vzoom <> lastvzoom... ' Nothing to do here... If zoom_changed Or device_changed... ' Nothing to do here... SetScissor 0, 0, DeviceWidth, DeviceHeight ' Set outer border... Cls 0, 0, 0 ' ' Clear to black... SetScissor sx, sy, sw, sh ' Set inner area... Scale multi * vzoom, multi * vzoom ' Set scale to fit... If vzoom Then Translate vxoff, vyoff ' Always called unless zoom is zero... End
It's been tested on HTML5, Flash, GLFW, XNA (Windows) and Android (SDK emulator).
Finally, here's a realtime capture of the new code applied to an existing game (using AutoFit) with no changes required, in the slow Android emulator:
(Device rotates at 00:05, change detected by device a second later, then display updates to adapt. Changes back at 00:13.)
| Well done, DB! :) |
| Here's a stripped-down demo that shows how you can treat a virtual resolution as if it's a fixed display size and simply hard-code your positions for that display size if you want to:|
| Cool. im using the older version for crime solitaire so ill update tomorrow. |
| Excellent -- it should just drop in with no side effects, hopefully. |
| Marvelous, - dropped it right in and it works great! |
| Just tried this in 1.45b - I'm assuming it'll work but there are shedloads of errors when compiled in Strict mode. |
| it has virtual mouse coords too, thanks! |
| @Gfk, sorry, I'll sort that... I'm really surprised I didn't use SuperStrict, but you're right, I didn't!|
@Slenkar: yeah, I'll probably add the Touch* stuff as well.
| OK, I've updated AutoFit so that the module is now Strict, and added VTouchX/Y calls too, plus the simpler demo above:|
Don't know why I was rambling on about SuperStrict, since Monkey doesn't have it -- mustn't post while hung over. However, I've realised that I don't use Strict in Monkey because of the forced returns values/function types, etc -- non-Strict catches undeclared variables anyway, which is what I mainly want.
| Good job. So if I understand it's better to work with high resolution to avoid black borders ? On a phone graph could be more small. |
| No, the black borders only appear if your 'virtual' resolution's aspect ratio doesn't match that of the device's real display.|
For example, a 320 x 240 display, a 640 x 480 display and an 800 x 600 display all share a 4:3 aspect ratio (width:height). If you set your virtual resolution to 640 x 480, and the game runs on a device with 320, 640 or 800 resolutions, there will be no borders.
If you run that game on a device with a 16:9 display (eg. 1920 x 1080), because the aspect ratios don't match, you use black borders to show the game at its 4:3 aspect ratio within the 16:9 display.
In short, you choose what aspect ratio your game is going to use via your choice of virtual resolution, and the game will automatically adapt to the aspect ratio of any display it finds itself running on, using the full width or height of the display available while maintaining your chosen aspect ratio.
Hope that makes sense!
| Is it possible to lock the screen orientation? I only ever want my game to display in portrait view, and not switch to landscape (with borders) when the device is tilted (although I don't mind it flipping if the device is turned 180 degrees). |
Is it possible to lock the screen orientation? I only ever want my game to display in portrait view, and not switch to landscape (with borders) when the device is tilted (although I don't mind it flipping if the device is turned 180 degrees).That's target-specific. For iOS, you'll need to open up XCode, where you'll have the option to lock screen orientation, set icons, choose ARM6/7 architecture and so on. Oh, and don't forget to switch off Debug build, which is ON by default.
I know you can do the same stuff in Android but having never used it, I don't know how.
I know you can do the same stuff in Android but having never used it, I don't know how.
Just set the option in the AndroidManifest... with Monkey you can just alter the config text file :)
'Must be one of: user, portrait, langscape, behind, sensor, nosensor, unspecified - experiment! SCREEN_ORIENTATION=landscape
| Cheers. :) |
| DruggedBunny you rock!|
This is perfect, drops straight in to my framework. Works perfectly on IOS as well, you can rotate the device from the menu like on Android and it resizes to fit. Saved me a huge headache and quite a few hours of hell.
I owe you some drugs sir! ;)
| on android you have to set the screen orientation to 'user' |
to make the game rotate when turn the android device?
| Try 'sensor'. |
| I added a method to the VirtualDisplay class that allows you to use scissors on your scaled display. Took me bloody ages to get my head around it but it seems to work. :)|
Method SetVScissor:Int (vsx:Float, vsy:Float, vsw:Float, vsh:Float) ' Allows you to set up a scissor on a scaled display ' Call UnsetVScissor when you want to continue drawing outside of the scissor area Local sclx:Float = scaledw / vwidth Local scly:Float = scaledh / vheight Local vscissor:Float vscissor = Max(sx, sx + (vsx * sclx)) vscissor = Max(sy, sy + (vsy * scly)) vscissor = vsw * sclx vscissor = vsh * scly If vscissor + vscissor > scaledw Then vscissor = (sx + scaledw) - vscissor If vscissor + vscissor > scaledh Then vscissor = (sy + scaledh) - vscissor SetScissor(vscissor, vscissor, vscissor, vscissor) Return 0 End Method UnsetVScissor:Int () SetScissor sx, sy, sw, sh Return 0 End
| Thanks for this wonderful module.|
I had uploaded my Doggy Bounce game to Google Play, only to notice that on a friend's phone it went outside of the screen. I had completely forgotten about different resolutions, thinking that it would somehow be scaled automatically.
With Autofit I just had to add two lines of code to the program, and change one call to TouchX() to VTouchX(), and now it does work perfectly, at least on mine and that other phone! :D
| Cool... I feel like Doc Brown hearing that others are making use of this in the real-world: "It works! I finally invented something that works!" |
| DruggedBunny ... it works great, actually ;-) |
| Cool, thanks for this. Getting closer and closer to my first mobile game release! |
| Nice work, saves a lot of headaches. Thank you for sharing this. |
| Well I was coming here to enquirer about using scissors on a scaled display and it seems that siread has come up with a solution. yippee.|
As always a big THANKYOU to James Boyd for autofit and a hearty handshake to sired, though I am sure sired is too busy mixing with his new high end dev friends and driving around in one of his many sports cars to care :p
| I was actually going to update it with Si's scissor stuff a while ago... will do soon-ish! |
| Just test out this module, looks great but I am having a little trouble.|
Just for testing purposes I set up a virtual display of 1280x720 but noticed that the first line of the virtual display was intermittently not being displayed. I assumed that this was just due to the physical screen resolution not matching the virtual one. So I set the virtual screen to match the physical one, so it should not really be scaling and yet the first line is still missing?
This does not draw a rectangle:-
DrawLine(0, 0, 1279, 0) DrawLine(0, 719, 1279, 719) DrawLine(0, 0, 0, 719) DrawLine(1279, 0, 1279, 719)
This does? :-
DrawLine(0, 1, 1279, 1) DrawLine(0, 719, 1279, 719) DrawLine(0, 0, 0, 719) DrawLine(1279, 0, 1279, 719)
It's not a big deal but it may be indicative of a bug.
| Hi! It's possible to "stretch" the virtual canvas to fill the screen, even if it means to lose the aspect ratio? |
| Just wanted to say a huge thanks to @druggedbunny for this awesome piece of code. I initially tried doing my own thing, which worked, but it was nowhere near as elegant as this. Thank you for making my life easier :)|
The screen rotate and scale changes are simply a godsend.
| Yeah, autofit rocks! I would like to see a possibility to stretch the virtual canvas if, for example, the black border only takes 5% of the total deviceheight or devicewidth. It will lose the aspect ratio, but not much. |
| How do I get rid of artifacts from Autofit?|
If you look at the arrow - between the squares is a red line. It is as if the images bleed through.
The second image is with Autofit turned off, and voila.. no more artifacts.
The images are 64x64 and the horizontal / vertical parameter for Autofit is 512 / 768.
I am guessing it has a lot to do with the ratio. But where does the red come from? The neighboring image from the file contains red, but it shouldn't bleed into the other image should it? I changed the image to cyan and sure enough the red becomes cyan.
The image file itself is 28 64x64 going 7 across and 4 deep.
Again.. When I disable Autofit, it goes away.
| Could you try defringing the image? Download DeFringe app from here:|
| Not sure what DeFringe is but the the site is currently down. :(|
I am going to write some code up in a bit to hopefully load up the "sprite sheet" image and cut it up into the 64x64 pieces and stick them in an array and see if that helps.
| We ( or maybe just *I* ) need a FAQ for Monkey. It appears this type of thing has been discussed many times.. just buried deep in the forums. :) |
| Be sure to pad the images, edge fringe is often the result of the bilinear filtering process grabbing pixels from beyond the borders of the texture being displayed and processing them into the end result you see on screen. AutoFit doesn't actually do this, the hardware does. There are multiple solutions to the problem, but probably the easiest (and with least impact on performance) is to simply pad the image.|
Now, gaps in tiles is another matter, there are a bunch of problems/solutions for that, depending on whether you need alpha accuracy....
| Nobuyuki and therevills, Thank you both for your help. |