I am making a game using And Engine, when i tried to make it in generic way that works on all devices then i am in trouble...
I need to set a sprite on specific position of background sprite that should work on all screens... My background screen has same size as dimension of Device..
I tried to use pixel let say Glaxy S3 ha dimensions 720*1280
And i set according to it my sprite at location (584,608)
and my HTC experia ha dimensions (320,480)
SO i need to set it on (244,172) ....
I have tried all the following ways to set the position of sprites in generic way but not if any work...
I have tried alot of following things to make some formula that enables me to do it but unable to find any.. please advise
final Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
metrics.density;
metrics.densityDpi;
metrics.heightPixels);
metrics.scaledDensity);
metrics.widthPixels);
metrics.xdpi);
metrics.ydpi);
Point point = getDisplaySize(display);
CAMERA_WIDTH = point.x;
CAMERA_HEIGHT = point.y;
DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm);
double x = Math.pow(dm.widthPixels/dm.xdpi,2);
double y = Math.pow(dm.heightPixels/dm.ydpi,2);
double screenInches = Math.sqrt(x+y);
int widthPix = (int) Math.ceil(dm.widthPixels * (dm.densityDpi / 160.0));
//CAMERA_WIDTH = display.getWidth();
//CAMERA_HEIGHT = display.getHeight();
Problem is little bit complex.. As i told above I tried to use pixel let say Glaxy S3 ha *dimensions 720*1280 And required sprite location is (584,608)
so i set in manner ( CAMERA_WIDTH/1.233f,CAMERA_HEIGHT/2.112f)*
BUT HTC experia has dimensions *320*480 So the required positions according to ( CAMERA_WIDTH/1.233f,CAMERA_HEIGHT/2.112f) is (2599.5,227.27)*
but this wrong according to display...
when i set it on (244,172) for experia its working perfect.... please help.
AndEngine offers multiple resolution policies. They are used to determine the size of the RenderSurfaceView, thus the actual size of the game on the screen, depending on the screen size.
You should use RatioResolutionPolicy: It will use the largest possible size, while keeping a constant ratio between the width and the height. By keeping the camera's size constant, everything it shows will be scaled by this constant ratio which will vary on different devices.
Example: Let CAMERA_WIDTH = 720 and CAMERA_HEIGHT = 480. If we create the camera and the engine options this way:
this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
EngineOptions options = new EngineOptions(..., new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), mCamera);
The ratio is 720 / 480 = 1.5.
When placing a sprite on your scene, use constant coordinates. Let's say we place it in the middle of the screen:
Sprite sprite = new Sprite(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2, ...);
So:
On a device with screen size 720x480, the sprite will be placed at (360, 240) screen coordinates.
On a device with screen size 480x320, the sprite will be placed at (240, 160) screen coordinates.
On a device with screen size 800x480, the sprite will be placed at (400, 240) screen coordinates.
And so on...
Related
So, LibGDX rants in a bunch of tutorials about how it is not recommended to use device pixels as coordinates in your world. I can understand the logic and it seems reasonable, so I am updating my camera code to do this:
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
aspect = h / w;
camera = new OrthographicCamera(1.0f, aspect);
camera.setToOrtho(true, 1.0f, aspect);
However a large part of what I do is working with fonts. Currently my font loader looks like this:
glyphLayout = new GlyphLayout();
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("myfont.ttf"));
FreeTypeFontGenerator.FreeTypeFontParameter parameter = new FreeTypeFontGenerator.FreeTypeFontParameter();
parameter.size = 100;
parameter.characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.!'()>?:";
parameter.flip = true;
font = generator.generateFont(parameter);
This results in huge sized fonts. I am confused by the apparently conflicting coordinates systems in LibGDX - why do they not recommend using pixels, and yet all font functions deal with pixels?
How can I update this font loading code, so I get fonts which are approximately 20% of the screen size?
You can develop for one resolution (using viewports) and set your preferred font size.
At runtime, you can scale your font size based on the new screen width.
1920x1080, parameter.size = 16 => 1280x720, parameter.size = 16 / 1920 * 1280
Also, with distance field fonts, you can render smooth fonts without using the font ganerator at runtime.
I have set the background of an Imageview in android (portrait mode) whose dimensions are 400 X 400 pixels. This image looks perfect on a 10" WXGA MDPI tablet (dimensions 800 X 1280). I happen to use the same layout with no modifications in the code on a 7" Nexus 7 (TVDPI 800 X 1280) tablet. The image is looking stretched. Can I programmatically find out the dimensions of the background in the layout on the Nexus 7? I want to mathematically scale down the dimensions of the background such that it looks like a square. I feel that the image background's width looks more than 400 pixels (say X) and the height is also more than 400 pixels (say Y). Also Y > X which makes it looks like a rectangle. How do I find X and Y programmatically in android on the Nexus 7? Please help. Is there a set formula to scale down or scale up the images so that the looks remain consistent on all android phones. Thank you
bellow code will let you take the width of the image and scale it accordingly
try {
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
SCREEN_WIDTH = displaymetrics.widthPixels;
Drawable ob = new BitmapDrawable(getResources(), bm);
float h = ob.getMinimumHeight();
float w = ob.getMinimumWidth();
float Hight = (h / w) *SCREEN_WIDTH;
imageView.setVisibility(View.VISIBLE);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, (int) Hight);
// imageView.setImageBitmap(bitmap);
params.setMargins(5, 5, 5, 5);
imageView.setLayoutParams(params);
int sdk = android.os.Build.VERSION.SDK_INT;
if (sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
imageView.setBackgroundDrawable(ob);
} else {
imageView.setBackground(ob);
}
} catch (Exception e) {
e.printStackTrace();
}
Rather than manually calculating the size of the image, have you tried using android:scaleType="centerInside" in your xml? You can set the size of the ImageView in dp units to keep a consistent size across different screens. The scaleType will ensure that the aspect ratio is maintained on scaling. You can also use android:scaleType="center" if you would like to prevent scaling and place different sized images in your drawables-xxx folders.
I am trying to figure out the dimensions for the S4. What is the width and height. I want to create graphics and place them based on h and w. I read that the screen size ranges from 0-h and 0-w, but what are h and w?
S4 screen specs are 1080 x 1920, but you shouldn't use the actual screen size in pixels in your code.
Just use dp - which is a size which is independent in the screen density to design you Android app UI, this way, it will behave nicely for all screen sizes.
For more details see Supporting Multiple Screens Guidelines.
Here's some handy code if you need to find the size of various devices:
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int screenWidth = size.x;
int screenHeight = size.y;
I have coordinates corresponding to screen resolution 600x400. Now I want to get the relative position of this coordinate for the screen resolution 1280x800. After getting the coordinates, I have to create a link on that coordinate..For example
Suppose I have a coordinate (5,5) for a 600*400 device resolution, so this coordinate will be at the left-bottom of the screen.Now i want to know what will be the relative coordinate of this on a 1280*800 screen resolution device so that it looks at the same position i.e bottom left of screen.
Thanks in advance.
Well sticking to what you asked ,you can get your new pixels as per follow
suppose the coordinates are (6,4) on 600*400 screen size, now calculate the % of x,y as per screen resolution ,as follow
(6 * 100 )/600 = 1%
and
(4* 100)/400 = 1%
now calculate the coordinates as per the new screen size as follow ,
(1 * 1280) /100 = 12.8
and
(1* 800) /100 = 8
so the coordinates in the new screen size are : (12.8, 8) which were previously (6,4) .
But there are better ways to go through in requirements like these , if you could be more specific with what you are actually doing.
Here is formula for converting dp to px, and px to dp based on screen density, so either way you can convert the coordinates appropriated to relative screen density.
public int doToPixel(int dp) {
DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
int px = Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
return px;
}
public int pixelToDP(int px) {
DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
int dp = Math.round(px / (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
return dp;
}
While we're at it, what is the Android equivalent of [UIScreen mainScreen].scale?
Are the following equations correct?
[UIScreen mainScreen].bounds.size.width = displayMetrics.widthPixels
[UIScreen mainScreen].scale = displayMetrics.density
where you get displayMetrics like so:
DisplayMetrics displayMetrics = new DisplayMetrics();
Display display = ((WindowManager) someContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
display.getMetrics(displayMetrics);
The thing is that I'm confused by the wording for iOS versus Android.
The definitions for those UIScreen values are these:
bounds
Contains the bounding rectangle of the screen, measured in points.
(read-only)
scale
The natural scale factor associated with the screen. (read-only)
#property(nonatomic, readonly) CGFloat scale
Discussion
This value reflects the scale factor needed to convert from the
default logical coordinate space into the device coordinate space of
this screen. The default logical coordinate space is measured using
points, where one point is approximately equal to 1/160th of an inch.
If a device’s screen has a reasonably similar pixel density, the scale
factor is typically set to 1.0 so that one point maps to one pixel.
However, a screen with a significantly different pixel density may set
this property to a higher value.
I am wondering whether the width of the bounds is equivalent to the widthPixels of the DisplayMetrics and whether the scale value is equivalent to the density value on Android.
[UIScreen mainScreen].bounds.size.width = displayMetrics.widthPixels
Correct, width of the screen (display) in pixels, nothing complicated here.
[UIScreen mainScreen].scale = displayMetrics.density
Not really. They are similar values but definitely not equal.
I'll try to explain what scale is. We have iPad 1 with screen resolution 1024x768 and we have iPad 3 with double resolution (apple marketing calls it Retina) and we want applications to work on both devices. So, the application works on resolution 1024x768 (logical points) but the OS translates to physical pixels on every device using the scale (scale=1.0 on iPad 1, scale=2.0 on iPad 3).
For example, when you draw a rectangle in logical coordinates (1, 1, 20, 40), on iPad 3 it will be drawn on pixels (2, 2, 40, 80).
There are currently only two values defined: 1.0 and 2.0.
The density is a similar scaling factor but calculated differently
This is a scaling factor for the Density Independent Pixel unit, where one DIP is one pixel on an approximately 160 dpi screen
Note that again it converts logical points (called DIP on Android) into screen pixels.
The difference between iOS scale and Android density is that the logical unit is defined differently.
I use this:
private void SetScreenSizes() {
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
intScreenWidth = displaymetrics.widthPixels;
}