Showing posts with label display density. Show all posts
Showing posts with label display density. Show all posts

Wednesday, April 11, 2012

Getting the "density" of your Android device

This is one of those crazy small things you'll be needing sooner or later in game development on Android devices.

How to get the "density" of your device?  Or more specifically, how many physical pixels are there per inch, how big is my display?

Well, first of all, we need to get data from our device.

DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);

That will fill in everything we will need to know. From there, we can get all sorts of useful information.

How many pixels can we work with horizontally and vertically?  *Warning*: These are filled in based on the current orientation of the device!!!
xpixels = dm.widthPixels;
ypixels = dm.heightPixels;

How about pixels per inch on the display?
xpixelsPerInch = dm.xdpi;
ypixelsPerInch = dm.ydpi;

If we know how many pixels are given in a dimension, and how many pixels there are per inch, we can determine the exact inches of our display (more or less).
displayWidth = xpixels / xpixelsPerInch;
displayHeight = ypixels / ypixelsPerInch;

Now, for the part that can be a little bit more mysterious.  What about the actual "density"?  Well, in Android API 4+, our DisplayMetric (dm) has a property conveniently called "densityDpi".  This is well and good for Android 1.6 and beyond, but what about our poor Android 1.5 customers where this field didn't exist?  Fear not, we can still get this information!

There is a field called "density" which is a floating number based on the scaling factor of our pixels in comparison to a 160 DPI device.  In other words, if our device is "160 dpi", this scaling factor is 1 (160/160 = 1).

Common DPIs for Android devices are: 120, 160, 240, and 320.  Knowing this, we can now cater to Android 1.5's missing densityDpi field by making our own.
if (dm.density == 0.75)
    densityDpi = 120;
if (dm.density == 1.0)
    densityDpi = 160;
if (dm.density == 1.5)
    densityDpi = 240;
if (dm.density == 2)
    densityDpi = 320;

Normally it is NOT a good idea to do a straight floating point equality comparison check (rounding errors, precision point problems, etc), but in this case, there shouldn't be any issue.


Correction: Do not do it this way.  We recently received a problem report from a user with a 148 density, which is seemingly not standard.  I will leave this code in here for illustration and so that the reader gets an idea of catering to different hardware displays.

The following way is how you should calculate the density.

densityDpi = (int) (dm.density * 160.0f);

*Update* 4.29.2012 : Added the note about a user with a 148 density.

Monday, February 13, 2012

Design to Product on Android - Art Design (8 / 17)

Ahh, what the game will look like.  More importantly, how does the art work in a game title anyways?  What is the visual play experience?  Also, the design of the art had better match the programming capabilities of the game engine!  No point in making beautiful 3d graphics if the software you're making cannot do 3d anything!

For sake of simplicity, our studio is currently using mostly Inkscape (it's free!) for high quality Scalable Vector Graphics.  We have limited talent in-house for art, so this takes us a little while to "get right".

Android apps require some special handling when it comes to the artwork, specifically with catering to different graphics densities on various displays.  This means that ideally, we will have a couple different versions of the same piece of art so that displays that can do "high definition" can use higher quality graphics, while displays that are from forever-ago can still render something (albeit very pixelly - hah new word).

The design of the art should be such that the same art can be easily scaled up and down.  This requirement led us to Inkscape (or Illustrator I suppose if you wanna pay money) so that we retain ultimate flexibility with scaling stuff up or down while using the same piece of art.  Short of pixel art, vector graphics are simply amazing and save a ton of time later down the road when you want to recycle graphics.

To keep things simple, we usually try to make hard colored, cartoony like graphics.  The lighting and shading  usually translate very well to small display sizes, and that is a big bonus for small displays.

Something that we learned from our earlier title Blocks Away! Is that we can use a grayscale version of a graphic and apply colors (using a multiply colorfilter) to the graphic in the game engine, this reduces the graphics work needed by quite a lot if the graphics themselves are simple enough and don't require too much recoloring work.  For example, in that game, we used a single white block, then just recolored the other blocks in the engine.  For this new game, we will try to reuse this trick to save work on the art, but ultimately, we may need to have different graphics for differing colors of game pieces.

Regardless of what we do, we need to consider the design of the art itself.  Shy away from ultra realistic and super mega amazing high quality stuff -- it simply does not translate well to small screens of phones, plus the production time and cost involved can be astronomical for small studios if this is outsourced, meaning we sort of have to do this ourselves with out limited experience in this area.

Some of the graphics we're probably going to use are here, don't worry, these are just samples and are really low quality -- they are meant to be teasers, rather than directly useful to you the reader.  Let's not go stealing people's work now (something that is rampant in the app markets as it is anyways!).

Sampling of actual game graphics

I probably should have mentioned this in the beginning of this article, but our first step here was to more or less finalize what the game visual layout would be.  In other words, we took our doodles, cleaned them up, and made actual graphics that represented what the game layout would be.  Where does the ad go?  How much space would it take up?  Where is the playing field, how big is it relative to other graphical assets?  From there, then we started making the actual graphics that filled in those zones.

The pic here is our first draft of the layout of the playable game area and where stuff goes.  Naturally, this can change a bit over the course of development, but this serves us sufficiently for now.

Layout

As a bonus to this article I should mention a bit about display densities.  When first developing for Android, I was accustomed to dealing directly with pixel sizes and spaces.  This is not generally a good thing for the novice Android developer.

Each Android device has something called a display density, or how many pixels per inch exists on the physical display.  This is stupendously important for knowing about how your graphics work with Android apps (specifically for placing them in the correct position!).

A point of reference:

Low density (LDPI) -> 120 dpi
Medium density (MDPI) -> 160 dpi
High density (HDPI) -> 240 dpi
Extra high density (XDPI?) -> 320 dpi (used for tablets probably)

In other words, when making mobile apps and games, you will likely need code that handles each specific density because you definitely have no guarantee that all your customers will be running on the same display density!

For example, if you want to place a graphic "in the middle of the screen", what does that mean?  How do you know at what pixel location is the middle of the screen?  I will get to these answers during the development cycle in a couple of articles from now.  However, an honorable mention happened here because when designing your artwork, you will likely want separate graphic assets for each different density that exists.  This directly translates to additional time required to make your product, catering to differing hardware by your customers, and this is only the graphics end of the deal.

Next up, we will start talking about some code (finally!).