Libgdx - Font that is smotth uses mega RAM - android

I have a viewport (360x640), but if I render fonts on that they are ugly. So I made higher size's and downscaled them. But now they go disoriented. (size == 30)
I made a 4x bigger viewport then so I didn't need to downscale them. But now my game instead of taking 15mb ram takes up 50mb. (size == 120)
And this is not acceptable. That my textures take 30x less ram than shitty 3 TTFs.

See https://github.com/libgdx/libgdx/wiki/Coordinate-systems#world-coordinates.
Use 2 viewports:
One which is near pixel perfect (around the same as the screen resolution of your reference target device), which you use only for the GUI like labels, buttons, etc.
And one which fits your game logic best (although 360x640 gives the impression you are using banana units (imaginary pixels), which you shouldn't do) and you only for rendering game objects and such.
Either way, the size of your assets (either on disk, in RAM or in VRAM) are not in any way related to the size of your viewport: when you change the size of your viewport then you should not scale your assets. The size of your assets should be around the same size as they are when they are projected on the screen. So it doesn't matter whether you use a viewport of 3 by 5 meters or a viewport 1440 by 2560 bananas. What matters is the size in pixels on the actual screen (e.g. take a screenshot and measure it). The size of the assets should be around that same size for best results.
If that means that you need a very large font, e.g. because you use a reference target device with a very high resolution (e.g. Retina Display), then that's how it is. You could work around that in several ways, e.g. by rendering to a smaller FBO, using texture filtering, etc. But reality is that devices with such large resolutions are equipped with at least enough memory to hold the assets for such resolution. So, in that case using more memory isn't really an issue.
If you like to target multiple resolutions which have different restrictions on the asset size then you can use multiple assets sets. For example by using ResolutionFileHandleResolver.
Although not related to your question, note that BitmapFont by default assumes a near pixel perfect projection and therefor uses integer positions to prevent aliasing. If you really don't want use a near pixel perfect projection then you disable that using the BitmapFont#setUseIntegerPositions method.

Related

My app slows down when background image is added in the drawable folder

I have read on this forum that the answer is to split the image in different resolutions and put it in different folders and the other way is to put the image in one folder without splitting it up so that android doesn't resize it.
My question is in which folder exactly do we put it on so it doesn't resize itself and shows as it is?
My res folder looks like this
Based on your updated question with the image and the clarity.
You are asking how to avoid scaling. You can either use the drawable directory or the drawable-nodpi to avoid prescaling. Either one will work for you.
I made a document on this once for the UI team I was working with, so this document is a little specific to their request and that app, but it might help you.
https://drive.google.com/file/d/1gJjT-F5AU57TCAr5I18l0jAvNG5-vLUb/view?usp=sharing
For vector drawables just use "drawable" standard directory. Make sure you are not violating any of the unsupported tags such as gradients and linear tags or you will have issues.
Next the -24 -26, etc.. folders are used for version specific. For example, let's say you have one type of image for pre 24 Android, but a different type for post 24, you can use -24 for the post image, and all others will check standard folder for it. This sometimes happens when you use something bleeding edge that isn't supported back far enough for your app's minimum SDK. You are not likely to use this for images, I can't even think of a problem where this would arise in the image buckets, but it's there all the same.
For deciding what resolution you need for each bucket, there are a couple of options here. First you could simply do the math. Decide how many inches you want it to take up and determine how many pixels are needed to accomodate that size and label that MDPI, than scale from there using the multipliers. Another less mathematical solution would be to open a preview on Android select an MDPI device and start playing with width = 100px height = 100px and adjust until you like the size. Write that down, it is MDPI, and begin your scaling from there.
As for a rough estimate of pixels to size, you can see what an app icon looks like and see what Android uses for that below.
So even though each bucket has a different pixel by pixel resolution, they will be identical sized and pixels per inch resolution on all devices due to bucket placement.
Hopefully that all makes sense.
--I'll leave the below from the original answer in case it helps someone--
You may have gotten some bad information.
https://developer.android.com/training/multiscreen/screendensities
Android is a widely dispersed resolution and size market.
In order to accommodate this they allow for DP and Buckets.
There are buckets for languages, screensizes, orientation, and resolutions.
You are looking for resolution support.
drawable-ldpi -.75 multiplier on size (1dp = .75px)
drawable-mdpi -baseline 1dp = 1px
drawable-hdpi -1.5x multiplier on size (1dp = 1.5px
drawable-xhdpi -2x multiplier on size (1dp = 2px
drawable-xxhdpi -3x multiplier on size (1dp = 3px
drawable-xxxhdpi -4x mulipvlier on size (1dp = 4px
each bucket has a multiplier associated to help the image look the same approximate size on each device. So even though it is 1 inch by 1 inch on one mdpi phone with your 100px x 100px image (pseudo size, don't calculate it ;)
it will need to be 150px x 150px on the hdpi to have the same quality and resolution of pixels per inch.
Now if you put all your images in the drawable bucket. Android will just ignore the scaling of these and you end up with varying space consumption depending on the device which will be very inconsistent on how much space it takes up on each type of phone.
If you put all your images in the correct folder you will at least have better quality. For example, let's say you have maybe 750px x 750px image that is meant to fill up a 1 inch area. You would be better suited to put it in the XXHDPI folder or XXXHDPI folder so Android knows to scale it DOWN rather than UP. This will give you better resolution for each device resolution that it scales for.
However, this is still poor practice. You are relying on Android operating system which can be very slow and weak on many cheap devices to do your scaling for you. I would recommend using GIMP and scaling to each multiplier on your own, then putting it into the respective resolution buckets.
This way Android decides based on the device which bucket resolution image it needs which decreases the amount of scaling exponentially.
Now, if you have Vector Graphics that you have imported, those will end up in the drawable folder which tells Android to ignore the resolution, and just draw these as vector graphics. This is the best option in my opinion as you only need one set of images per image. Although, Vector graphics aren't quite as fast at loading as a JPG or PNG, but it keeps your package size down quite a bit and development maintenance is so much nicer.
Hope that helps.
Happy Coding.

Android Tablet "dp" difference

I would like to create a adaptive UI for both mobile and tablet devices. I would like to know for example for mobile devices if I give android:textsize="2dp then how much I should give for tablet devices. I know I should give them in values-w820dp and appropriate folder but how to calculate the difference of this dp. I couldn't find any resource for this. Help me out.
(1) For most text, it's best to size it in sp units so it scales automatically relative to the user's text-size preference. Folks with lesser vision can pick larger text and then be able to read your app without eyestrain.
(2) If you need some text to appear in a fixed size, e.g. a big headline, then use dp units so it scales automatically relative to the screen's pixel density. (Pixel density is independent of the overall screen size. It's a high vs. low density thing, not a phone vs. tablet thing.)
But don't use size 2dp! That'd be unreadably tiny -- the height of 2 physical pixels of a 160 dpi screen.
(3) If you need some text that uses approximately a fixed proportion of the screen size, then it makes sense to either define screen-size-dependent parameters, e.g. in values-w820dp, or to size it in code.
(4) If you need some text in a fixed number of pixels tall even when the pixels are really tiny, e.g. to draw into a raster image, then use px units.
See Supporting Multiple Screens - best practices.
There are no strict rules here. You can have android:textsize="2dp on your tablet as well if you wish so. You can have a look at the following android developer page which tells how to support tablets and contains chapter called: 5. Adjust Font Sizes and Touch Targets

High resolution app backgrounds?

and i would like to have a nice high resolution background for it.
If i mind galaxy S4 and galaxy Note3, they have 1080 x 1920 px screens.
That means my 1080 x 1920 px background will be 3 MB.
What!?? Yes. My whole app should be 3 MB not only one drawable piece.
So my question is, how developers solve this? I would like to have a nice textured well designed background, if it would be flat design, there wouldnt be problems like this.
And okay.. lets say Galaxy S4 and Note3 have really big amount of memory and fast processor and i use that 3MB background, but... what happens when somebody would like to use my app with a low budget device? Maybe its cannot even show that big image.
Any ideas about this?
If you are worried about other devices you should simply define different resources along with the correct size qualifiers, like stated in the Android guidelines.
smallestWidth sw<N>dp
Examples: sw600dp sw720dp
The fundamental size of a screen, as
indicated by the shortest dimension of the available screen area.
Specifically, the device's smallestWidth is the shortest of the
screen's available height and width (you may also think of it as the
"smallest possible width" for the screen). You can use this qualifier
to ensure that, regardless of the screen's current orientation, your
application's has at least <N> dps of width available for it UI.
...
Basically you can define a drawable-sw<N>dp for each family of screens you want to support, putting in there targeted pictures as you need.
I think you need to change the resolution of your image. I created a 1024 x 768 PNG background image and its size was only around 300kb.
Check your image resolution. I recommend 72 pixels/inch. I'm not sure if there's any other softwares, but you can check and change your resolution on Adobe Photoshop if you go to Image -> Image Size. You might need to uncheck 'Resample Image' I think.

Android game working on all screen sizes

I'm trying to specify the art sizes for an Android game with ~10 screens. I want the game to run on API 8+, and on all size screens except "small".
Since we're using API 8, I use the old "4 categories of screen" feature - I plan to support
normal (480 x 320, and up to 640 x 480)
large (640 x 480, and up to 960 x 720)
xlarge (960 x 720, and up to 1920 x 1200)
A 1920x1200 png file is ~4.1MB. So 10 of them is 41MB, and we've almost blown our 50 MB app size limit (Play Store).
So three questions:
1. how do people support detailed artwork for game screens? Do I have to use bland colored 9 patch pngs files for the backgrounds? Or is it feasible to store all art at the 960x720 size, and allow it to be resized by Android for large and normal screens? 10 background files of this size total to about 15 MB, which leaves 35 MB for everything else.
What if I used jpgs instead of pngs? How much quality would I lose? Since I would only ever be downsizing, this should be OK, right? 10 jpgs of 960x720 is only 4.3MB.
If I allow Android to resize it, how do I support screens that have a different aspect ratio than the 4:3 of 960x720? Is there a way to specify in the layout XML "use the drawables from the large folder, but "letter box" it onto the screen, so that the longest dimension just fits" ? (And for xlarge screens bigger than 960x720, just put the drawable in the middle of the screen - don't stretch it at all)?
DPI resolution of the screen doesn't factor in this at all? DPI only needs to be taken into account when you want something to be roughly the same size on different res screens, like an icon or button. Correct?
Seems like this should be a solved problem with a well known pattern or template to follow. How have other people done it? Does everyone use either huge downloads post install (want to avoid) or 9 patch backgrounds?
Thanks in advance for any advice. I searched here on several terms, and looked at about 25 past answers, without finding what I am looking for.
Peter
Resurrecting the dead (thread): one way of doing things could be to provide just one set of bitmaps and do the scaling yourself. You can either provide large bitmaps and scale them down, or provide middle of the road bitmaps and scale them up (for large screens) and down (for smaller sizes).
The benefits of the former are that your art looks great on large screens and you are a bit more future proof (if you provide for this in your code). The downside is that you could (and actually likely will) run into Out Of Memory/Exceeding VM errors when decoding/loading these bitmaps on lower-end devices, even when doing it carefully. So I usually go for the second approach.
Scaling up can be done a number of ways, but one is to just load in the bmp at it's default size (use getResources().openRawResource(id) or BitmapFactory.decodeResource(etc) or even better use inputstreams or [according to some the best method] load/create using the FileDescriptor methods) and then scale it either by creating another bmp using createScaledBitmap() or if drawing to a canvas draw it to a destination Rectangle (better memory wise).
For scaling down you can either use BitmapOptions like .inScaled or, again, use a smaller destination Rect in your canvas drawcall.
Doing it this way is way better and (for a game) faster than letting Android scale for you using those buckets (hdpi etc) and uses less memory if done right.
But beware as some bitmap loading methods are a bit buggy and create 'the bmp is too big for the VM' errors. Also learn to dispose of your bmps properly; a lot of people and Google/Googlers say Android does this and you don't have to set your bmps to null and recycle() them, but so far I've found that you do. Another caveat is to set the proper options (filtering/antialiasing etc) to prevent blurry bmps. And take care of un-optimal color/format/dpi settings on BitmapOptions/canvasses/SurfaceViews and even windows.
There's much more, but this should help anyone get started.

Reducing Android Alternative Drawable Resources

I have images that need to scale to the screen's size. The images will also have text in it that needs to be translated to a second language. So there will be two versions of each image to start, one for each language.
Google recommends having an image resource per density. So I'd take my two images and multiply them by four: xhdpi, hdpi, mdpi, and ldpi. But then Google say to have different image resource for different screen sizes. This multiplies my images by four again: xlarge, large, normal, and small. I don't want to create 32 copies of every image!
I'm wondering if there is anything wrong with making the images for xlarge screens and xhdpi densities only. IE – Best quality. Let Android scale down the images for lower densities per its standards for dp units. And when I draw on smaller screens, I could use the Canvas class to scale down further. I could cache the resulting scaled Bitmap object for use every time it needs to redraw the bitmap to avoid expensive scaling computations running over and over.
Is there any drawback to doing this? Or is there a better way to avoid making so many copies of the same image?
There will be a performance penalty in downscaling large images on smaller (low-end) devices. Whether this will be noticeable depends on the number of images you have to show.
The same holds, mutatis mutandis, for memory.
I create bitmaps only for the highest xhdpi pixel density, and then test on other screen types.
If a bitmap looks bad on some lower-density screen, I remake it specifically for that density. And this happens quite rarely...
Also, making special bitmaps for different screen sizes (small/xlarge) is not needed - just make your ImageView-s smaller/larger - image scaling is not a slow operation, so in most cases you don't need to worry about it either (unless your bitmaps cover the whole screen).

Categories

Resources