Sunday, April 17, 2016

java - Fitting Android game to different screen sizes


I am making an Android game that is only in portrait screen orientation. It works great when I run it on my phone, but when I run it on a tablet, even though the screen size is bigger, all of the bitmaps are the same size. Is there any way to make the bitmaps stay the same proportion even on different size screens?



Answer



Unless you're using AbsoluteLayout (Usually a very bad idea, as you design your layout using x/y coordinates, which will only suit the device it's been designed on) this should not happen - Android applications automatically adjust to the device's screen-size. However from what you describe (Layout does not adjust to Table Screen), it sounds like AbsoluteLayout might be the issue here.


Make sure that in your layout XML files you're NOT using absolute layouts (this includes setting explicit coordinates/widths/heights on any kind of View). Instead consider using:



... whatever best suits your purpose.


If you're new to Android, then Google offers a nice tutorial that introduces to the different Layout Types mentioned above. More tutorials can be found here.


Furthermore your API Level would be relevant (to know whether you're using Android 2.x or 4.x - I don't assume 3.x as it's not available for Smartphones) to figure out the cause of your issue.


Are you forcing your Application into Portrait mode by setting:


@Override

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set screen orientation for this dialog to portrait
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}

... in your Activity that displays the game's views?


Please provide more info on how you're layouting your views (are you using XML for the layout that you later inflate in your Activity, or are you using in-code layouting in your Activity etc....) ? Furthermore: Did you try running your app in a Smartphone - and Tablet-sized Emulator? If yes, does the issue persist?




UPDATE: HOW TO SCALE BITMAPS



The OP asked how he can scale the bitmap's he's using in his game. One option (from all I know about the OP's setup): The SurfaceHolder.Callback that you're overriding to display your game and on which you render all the Bitmaps etc... has a method called:


surfaceChanged(SurfaceHolder holder, int format, int width, int height)

That method gives you the width/height of your surface, so you could now use:


Bitmap.createScaledBitmap (Bitmap src, int dstWidth, int dstHeight, boolean filter)

from the Bitmap class. To resize your images in proportion to the size of the surface you're drawing onto.


What you need to do is this: If you know the dimensions of your bitmap in relation to a given screensize, for instance the screen-size of your smartphone. Then you can calculate the target dimensions of the scaled bitmaps. Here is the math (wrapped in an example):


Say you have a Bitmap A with the dimensions 25x50 (widthxheight) which is displayed on a screen with the dimensions 100x200 (widthxheight). For that screen size (100x200) the bitmap has the correct dimensions - now if you want to display the bitmap on a larger screen you need to:




  • Calculate the scale factor for the bitmap size

  • Maintain the aspect ratio of the bitmap (so it does not get distorted)


Say the larger screen is 200x300 (widthxheight) then the scale-factor for the width is:


200(target screen width)/100(default screen width) = 2

So 2 is our scale-factor for the width and height value of the bitmap, since we need to maintain the aspect ratio of the bitmap, we can simply multiply the scale factor with the width and height of the bitmap:


bitmapWidth * 2 = scaledBitmapWidth
bitmapHeight * 2 = scaledBitmapHeight


So using our example bitmap A from above and the mentioned formula, the new dimensions of the bitmap would be: 50x100 (widthxheight) because:


 2*25(width) = 50 height
2*50(height) = 100 height

Soo now that we know the new size of our bitmap we simply use the API call I mentioned above and fill in the blanks:


   Bitmap.createScaledBitmap (myBitmap, 50, 100, false)

myBitmap in the above example is the original bitmap A that had the dimensions 25x50 and is scaled to 50x100 using the above code-snippet.




However - this wouldn't solve your original issue of the application taking up only the upper right corner of a tablet-sized device. To answer that one we'd require answers to the questions we asked you regarding your setup. I'll quickly sum them up here:




  • Are you using a game-engine such as AndEngine or Unity ?

  • Are you writing your layout in xml? If yes, what's your root-layout for rendering your your game content?

  • You mentioned that you're implementing SurfaceHolder.Callback? The width/height provided in the method call of surfaceChanged gives you the size of the surface - is it the same size when your app runs on a smartphone or a tablet?

  • Do you have any access to the SurfaceView (or whatever is linked to that SurfaceHolder.Callback you're implementing), so we could determine if that's the one rigidly setting the app size to smartphone size.

  • Do the same resize-issues occur in the emulator with different screen resolutions?


A general suspicion: Not every smartphone has the same screen size, in fact there's a wide range of screen sizes, which makes me wonder: Did u ever test your app on a smartphone with a different screen size than your screen? Because - the fact that it fits your screen, but not a tablet, makes me wonder who sets those dimensions and when. Because I doubt that an app can adjust to all smartphone-screen-sizes, but not to tablet sizes - won't make much sense (because they more or less have the same android core running on them, some differences between s.x, 3.x and 4.x aside) UNLESS you're using a framework which does not support (for whatever reason - maybe you'd have to buy tablet support extra or whatever) tablet-sized screen sizes. That's why it's really important to know, whether the app resizes properly on your phone only, or on other smartphones as well. The only way I am aware of how an app can be limited to the screen size of one specific phone is by using AbsoluteLayout and generally absolute dimensions for widgets etc...




UPDATE: Scaling x/y Coordinates



In order to adjust your bitmap's location to the screen size, something like the following should do the job:



  • Screen dimensions: 100/200 (width/height)

  • Bitmap location: x=50/y=100


Now, if you increase the screen size, you'd have to scale those x/y values along:



  • Screen dimensions: 200/400 (width/height)


The scale factor would be 2, because the width and height equally increased by two. Hence the dimensions would be...




  • Bitmap location: x=100/y=200


Another try - this time with different scale factors for width/height



  • Screen dimensions: 100/150 (width/height)

  • Bitmap location: x=50/y=50


If the new target screen is 150/250 then calculations are:




  • Scale factor for width = targetWidth / originalWidth = 1.5

  • Scale factor for height = targetHeight / originalHeight = 1.666... (Period)


Now we need to scale the x/y coordinates, x is scaled using the width-scale and height is scaled using the height-scale, here's the result:



  • x = originalX * 1.5 = 75

  • y = originalY * 1.666.. (Period) = 83.333... (Period)


So the new screen dimensions and the scaled x/y coordinates are:




  • width = 150

  • height = 250

  • x = 75

  • y = 83,333... (Period)


To make a long story short, the algorithm for scaling bitmaps is:


X = (targetScreenWidth / defaultScreenWidth) * defaultXCoordinate
Y = (targetScreenHeight / defaultScreenHeight) * defaultYCoordinate

No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...