This is my first post, so I apologise in advance if I have done anything wrong here in asking my question. I've looked all over the net for a specific answer, but can't find one, so here goes.....
I'm writing a game based on Surfaceview and so far, all is going well, however, I want to move my main sprite for example by 1 pixel on a 160DPI screen as a baseline (so basically 1 DIP as 1 pixel = 1 DIP on a 160DPI screen correct?)
I'm using the using the following forumla:
private static final float spritemovestep = 1f;
final float scale = getResources().getDisplayMetrics().density;
MoveX = (int) (spritemovestep * scale + 0.5f);
And then... something like
SpriteX=SpriteX+MoveX
First question - is this correct?
If it is, can someone explain what the +.05f is actually for, I've read that it's to 'round up to the nearest number' but....
if spritemovestep = 1, then on a 120DPI screen (which returns .75 as the scale I think) it would work out as: 1 x .75 + .5? which would be 1.25? So what is the .5 for?
Also what is the result when it's cast to an int value?
On some, the final result seems to be '0' on a low density screen so the sprite isn't moving at all.
Also some sprites which are supposed to be moving at different speed are moving at the same speed at certain densities.
I'm sure I'm being silly and missing something here but I just can't understand how this is supposed to work. If I want to move my sprite by 1 DIP/physical pixel on a MDPI screen how can it move less than 1 pixel on a LDPI screen?
Also, what is this formula I keep seeing:
px = dp * (dpi / 160) - When is this used?
Would really appreciate if someone could answer my questions.
Thanks all
The +0.5f is to round up to the nearest nukber, as you said. Ideally, when the number is scaled down for ldpi, a value of 1 becomes 0.75, which, when cast to an int is expressed as less than 1 or ~=0. By adding the rounding figure, this number is raised to 1.25 which, when cast as an int yields <2 or ~=1. This way, your sprite should be drawn with a minimum movement of 1. The only reason sprites that move at different speeds would move the same speeds is if they are so close that, when rounded, they wind up being the same size using the scale you gave. Altogether, your equation is very similar to others ive seen. Im making a game that uses surfaceview for the company i work for as well, and while i cant go into details on the code, your issue is one that i struggled with for sone time. Im not sure how your physics updates, but perhaps thats something you should check into, specifically, how it counts ticks for your game timer. It may be that your application is reading its ticks as being too close together to reach the point where it would hit the point of moving the 1.25 or 1 after casting to int, and therefore your sprite appears not to move. I briefly experienced that problem and at first was looking at my velocity until i found that the error was in the timer. One other thing i noticed is that your algorithm collects the density. On a mdpi device, does this return 1 or 160? That could make a big difference, but im not sure, as the equation i used was different. The other equation you found is a paraphrase of the equation listed in the development guide at android.developer.com to describe how the os converts pixels into dip. The reson people tend to quote that is to provide a reference to help others build their own algorithm for scaling appropriate for the jeeds of their app. Hopefully that helps, as its really the best answer i can give at this time. Sorry for any typing errors, im sending this from my phone
Related
I'm new to AndEngine and Box2D. So bear with me please.
I created a new project, set up a 480x800 camera, added a 32x32 stripe, created a physics world at Earth gravity and dropped the stripe. Lo and behold, it DID drop. But it didn't seem "natural" to me; it was too slow.
Then I realized that the gravity is in meters (m/s2) whereas the environment is in pixels. Where does the conversion between meters and pixels tak place? Somewhere there should be an assumption behind the scenes. Do I have any control over it?
How does Box2D know whether it's dropping the stripe from 100 meters above the ground (and viewing it from a distance which would appear a very slow drop) or 1 meter above the ground (and viewing it from up close which would appear very fast)?
To test that the conversion is the real problem, I multiplied the gravity by 10 and it improved the "naturalness". But I think there should be a more sophisticated way to convert pixels to meters.
Thanks in advance. I really appreciate your comments.
It's as #iforce2d said it the comment. In AndEngine the default value is 32, therefore 32 pixels is considered one meter. When converting pixels to meter, divide the pixels by this value. When converting from meters to pixels, multiply with this value. You can find this value in org.andengine.extension.physics.box2d.util.constants.PhysicsConstants class.
The ratio is then used in PhysicsFactory.create... methods if you don't specify your own. These methods create the physics body for you, measuring your sprite size in pixels and passing meters to Box2D. It's also used in the PhysicsConnector class constructor. Use your own value if 32 doesn't suit you, but then you will have to be consistent and use it every time.
I have a nice idea for android application want to make real scale, not like others which are fake i was thinking of how to do it but don't have any idea.
EDIT: want to make real scale (what means) It means for example i wanna calculate how much is the weight of a coin, then i'm putting the coin in the screen and calculates how much is the weight of the coin and if its possible the scale to get the weights to 50 grams
Hope its understood now.
Actually it is possible, just probably not precise enough. Most touch controllers can report touch pressure and it is available via MotionEvent.getPressure() call. So with some luck and tedious calibration you can measure weight of something. It is going to work better with cheaper resistive screen.
There is nothing in the Android SDK that supports measuring the weight of a coin.
You can get the pressure (0-1). Calibrate it with a quarter or known value (quarter is 2.5g). Then if a quarter gives you a pressure value of 0.2, then you know that to calculate weight, you use the formula (p * 2.5/2), where p is the value read from getPressure().
I don't know if you can scale it...
Good Luck.
I am facing multi resolution issue in box 2d.
First I needed to make bodies multi resolution, I solved it by scaling the vertices by scale factor.
Now I need to make the forces to act same of all different resolution devices,
Is there any way to do it?
I want to make this line of code to work same on all devices
obj.getBody().applyForce( new Vector2(0, -220), obj.getBody().getWorldCenter());
Here 220 is the factor should I make it multi res by this formula
public float getY(float value) {
y = (value / 540) * 100;
return (y / 100) * CAMERA_HEIGHT;
}
Here 540 is the base resolution. I call getY(220) to make it multi resolution.
When I use this code on resolution 540*960 it works fine but when I change the device say of resolution 720*1280 the game acts real slow.
Can any one help me with this issue? I tried to explain my question.
Thanks in ADVANCE.
You scale the graphics by setting your camera to something other than the device's pixel count.
Andengine will do everything else for the scaling.
All you need to get from the device is the ratio of x to y pixels.
In the example I have at this link, I just set one variable and everything is scaled to that.http://pastebin.com/WWGFvTVS
So you just decide what initial scale you want to work on, and do your Box2D stuff without worrying about scale. You just have to scale the Camera that is looking at the scene.
I'm saying the same thing as these other guys, you just don't seem to be understanding them.
Do not scale physics. Scale graphics. You should have physics coordinate system shared between each resolution to make your simulation the same on different devices.
I have recently been trying to implement my first Android game using a similar approach to the infamous LunarLander. I am rendering the graphics myself without the aid of a game engine, and that seems to be the most complicated part of the endeavor so far.
The Problem
I am determining the width of the screen, and forwarding that information into an algorithm that determines the maximum number of images that can be rendered horizontally given the width and some other margin values (see calculateMaxBeadsInWidth() below). However, the mathematics seem to not be matching up to the values computed by the algorithm. Basically, it is determining that only X amount of images can be displayed, when in actuality X + 2 images can easily be displayed on the screen.
The Calculations
I have parsed many debug outputs that show that the actual width of the screen is 800 pixels, and the image width is 44 pixels. So, given that the margin is 100 pixels (50 pixels on the far left and 50 pixels on the far right), that leaves 700 pixels to work with. Now, floor(700 / 44) = 15, so only 15 images are shown. But there is clearly space for more (see pictures)!!
The Code
My algorithm:
private int calculateMaxBeadsInWidth() {
float eff_width = screenWidth - (BOARD_MARGIN_HORIZONTAL * 2);
return (int) (eff_width / bead_width);
}
Note that the value of BOARD_MARGIN_HORIZONTAL is 50.0f.
Some Pictures
This is what is being produced by my algorithm:
However, as you can see it is obvious that you could easily fit at least 2 more beads towards the end of the lines (on the right). For instance, this picture shows what happens when I hard code the number of beads in one row to two more than the algorithm is producing:
Here is the image with the margins detailed with red lines. As you can see there is still plenty of space:
Supplemental Information
I am testing this application on the Google Nexus 7.
I am using getResources().getDisplayMetrics().widthPixels; to obtain the width of the screen. Perhaps the issue is here?
My Question
Are there some resolution values that I am not taking into consideration here that are affecting the results? Why is this being computed so inaccurately?
If you need any more information I will gladly provide it, any help would be appreciated greatly!
Your margins are the wrong value. You uploaded full-size images, but if you draw vertical lines # 50px and 750px, they intersect the drawing area. So, you are either using the wrong value in your calculations, or somewhere else you are drawing in what is supposed to be margin.
I've been writing a 2D Surfaceview game for what seems an eternity now and I simply cannot get my head around screen independence for Android.
Basically, my sprite jumps like so: Y value is decreased by an amount (I call it the 'step amount'), then the step amount is reduced by say, 1 and that goes on until the step amount is a negative number which then in effect gets added to the sprite's Y value and it 'falls' back down - works perfectly (This is the way I've always made sprites 'jump').
The problem comes when I run this on a different DPI screen - it still works, but the sprite jumps to a completely different height relative to the screen size.
I understand why this is happening, but I just can't work out a way to fix it!
How do I get it 'jumping' to the correct height on all screen res? (I'm working mainly with 160 and 240 DPI at the moment)
Thanks, would really appreciate any comments.
Regards