What happens when converting double (or floats) to ints? - java

I'm practicing some simple 2D game programming, and came up with a theory that during animation (the actual change in a image position is best calculated with floating point numbers). I have a feeling that if you move an image around with ints the animation won't be as smooth.
In Java it seems you can't draw an image with floating point numbers to give an image a position. But apparently when you initially declare your x and y 's, you can declare them as Double, or Float, and when it comes to actually drawing the image you have to cast them to ints. Like I find HERE :
/**
* Draw this entity to the graphics context provided
*
* #param g The graphics context on which to draw
*/
public void draw(Graphics g) {
sprite.draw(g,(int) x,(int) y);
}
My question is about how Java handles the conversion?
If the code casts these doubles at the last minute, why have them as doubles in the first place?
Does Java hide the numbers after the decimal?
I know in C and C++ the numbers after the decimal get cut off and you only see whats before it. How does Java handle this casting?

Pixels on a display are discrete and limited in number; therefore display coordinates need to be integer numbers - floating point numbers make no sense, as you do not physically have a pixel at e.g. (341.4, 234,7).
That said, integers should only be used at the final drawing stage. When you calculate object movement, speeds etc, you need to use floating point numbers. Integers will cause an amazing number of precision problems. Consider the following snippet:
a = 1;
x = (a / 2) * 2;
If a and x are floating point numbers, x will finally have the expected number of 1. If they are integers, you will get 0.
Baseline: use floating point types for physics computations and convert to int at drawing time. That will allow you to perform the physics calculations with as much precision as required.
EDIT:
As far as the conversion from FP numbers to integers is concerned, while FP numbers have a greater range, the values produced by your physics calculation after normalization to your drawing area size should not normally overflow an int type.
That said, Java truncates the floating point numbers when converting to an integer type, which can create artifacts (e.g. an animation with no pixels at the rightmost pixel column, due to e.g. 639.9 being converted to 639 rather than 640). You might want to have a look at Math.round() or some of the other rounding methods provided by Java for more reasonable results.

Java truncates the decimals. Eg:
(int) 2.34 == 2
(int) 2.90 == 2
The reason for not being able to draw at a floating position is simply that there's no half pixels etc :)

Java casts floats to int by dropping the decimal. But I don't think having x and y coordinates in floats make any sense. You have pixel on the screen which cannot be presented in anything less than one pixel. For example you can't draw a pixel .5px x .5px because on the screen it will just be 1px x 1px pixel. I am not a computer game programmer but I have written one animation engine in Java and it was very smooth. I can share this if you'd like.
Note that you should draw using ints but do all your calculation using doubles. For things like rotating or anything that relies on a mathematical formula should be done in decimal.

The reason x and y need to be doubles is for when they need to be computed mathematically, for example:
x += (delta * dx) / 1000;
You want to avoid overflows and loss of precision up until you paint the pixel.

Related

How to use a gaussian distribution to calculate a random point on a bullseye in java

I've been working on a project and I need to be able to return a point in a square that acts kind of like a bulls-eye. I wanted to make it return a point that would follow a Gaussian distribution, meaning after a lot of generated results we would see the majority of the points generated near the center and the number would diminish as it goes towards the outer limits of the square. What would be the best way to go about this?
I have a method as seen here:
public static Point randomPoint(final Random random, final Point center,
final double sd) {
Point p = null;
return p;
}
But I am really stuck on where to go from here. With general numbers, a random gaussian number would just use a min and a max with a mean and standard deviation. would I do something similar here but do the min and max for both x and y?
To generate a symmetric 2d Gaussian distribution, you actually only have to generate 2 separate Gaussian numbers and take them as x and y, like this:
new Point(center.getX()+random.nextGaussian()*sd,
center.getY()+random.nextGaussian()*sd);
Note however that mean (the center) and deviation (I assume 'sd' in your example) does not equal min/max. It basically means that roughly 2/3 of all points will be less then 'sd' far from the center, roughly 95% will be at most '2*sd' far. However there is a non-zero probability for all points, however far.
This means, you might want to 'crop' the points to the rectangle of your interest. Note however, there are two approaches to do this:
If a point is outside the rectangle just put it on the border (aka. do min/max checking and take min/max if it's out of bounds)
Repeat the generation if point is outside of bounds
The first one will potentially deform your distribution, as it will be more likely that a point is on exactly the border than it should be. The second one costs a bit more processing, however it will preserve the distribution.

How to convert an angle to a vector

I'm making a simple 2d Java game similar to goemetry wars. I'm currently programming the player's shooting.
I have a target point specified by the mouse location. Now I want to add a bit of randomization, so that the shooting angle has a random offset. I am currently converting the point to a vector directly. My idea was to convert the vector to an angle, apply the randomization to that angle, and then, convert the angle back to a vector (given the length of the vector).
I can't figure out how to convert the angle back to a vector. I don't need code, it's basically just a question about the maths.
If there's a better way to randomize the shooting, I would love to hear that too! I can!t apply the randomization to the point because there are other things then the mouse that can set it.
Polar coordinate system
As everybody seems to have just answered in the comments, here goes the answer to your question as it is formulated : you need to use the polar coordinate system.
Let's call your angle a, the angle you want to add to it b, so the modified angle is a+b.
In the polar coordinate system, your point is represented by an angle a = Math.atan2(y, x) and a radius r = sqrt(x*x + y*y). If you just use the angle, you loose some information, which is at which distance the mouse is from your (0,0) point.
Converting back from your polar representation (after the angle has been modified) is now possible : x = r * Math.cos(a+b), y = r * Math.sin(a+b)
Without computing the angle
By using some cool trigonometry formulas, we can do better. We don't need to go to an angle and come back to a vector, we can modify the x and y values of the vector directly, still changing the angle like you want.
Remember that we want to find x'=r cos(a+b) and y'=r sin(a+b). We will obviously the following formulas :
Now let us multiply by r on both sides to get what whe want.
We now recognize x=r cos(a) and y=r sin(a), so we have the final expression :
If you come to think of it, for small values of b (which is what you want), sin(b) is close to 0, and cos(b) is close to 1, so the perturbation is small.
Not only do you reduce the number of trigonometry operations from 3 to 2, but you also have a cos and a sin of small values, which is nice if they are computed from Taylor series, makes convergence very fast. But that's implementation dependent.
NB: An alternative (and more elegant?) way to find the same result (and exact same formulas) is to use a rotation matrix.
I can haz cod
Whoopsie, you said you didn't want code. Well let's do it like this : I don't post it here, but if you want to compare with how I'd do it once you're done coding your implementation, you can see mine in action here : http://ideone.com/zRV4lL

Calculate Distance between two points- Java

I have inherited a code and it has this small function written to calculate distance between two points.I'm wondering , what it does. I know the lat long data is in decimal degrees. Could anyone please throw some insights, if this calculation is right?
private double calculateDistance(QuoteItem quoteItem, RouteInfo routeInfo) {
final double distance =
((Math.max(routeInfo.getLatitude(), quoteItem.getLatitude()) - Math.min (routeInfo.getLatitude(), quoteItem.getLatitude())) +
(Math.max(routeInfo.getLongitude(), quoteItem.getLongitude()) - Math.min(routeInfo.getLongitude(), quoteItem.getLongitude()))) * 60.0;
return distance;
}
This is a variant of the Manhattan distance calculation where it's not a true Euclidean hypotenuse distance calculation, but rather a simple sum of the two sides of the right triangle multiplied by some multiplier, 60. I usually see it written more simply as
Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y)
Which is essentially what your calculation is, except you're also multiplying it by some scaling factor, 60.0.
I've used this in programs where I want to get a quick and dirty estimate of distance with an emphasis on quick since it involves no square roots. For instance, I used it once for very rough (and incorrect but correct enough for the purposes) calculation of the differences between pixel colors, where I had to make this calculation repeatedly for the pixels contained two images, in real time, and where need for speed trumped the need for accuracy.

scaling operations on a 2D graph, size of output sequence must not be the same as input

I am looking for an open source package (preferably Java but R or other languages would be ok too) that provides these 2 functions
1) points output_seq[] SCALE(points input_seq[], double factor)
In other words a sequence of doubles (x1,y1), (x2,y2)... is given as input that represents a graph (each point is connected to the next by a straight line) and a scaling factor is given. Then it returns a similar sequence as output. The catch is that the output sequence may have fewer or more elements than the input. For example, if I request magnification by a factor of 2.012 then the output sequence may have twice as many elements as the input. The scaling factor should be a double, not an integer.
Lastly, it's important to return the output sequence as points (doubles), I have very little interest in the actual drawing on a screen beyond proving that it does the right thing.
2) points output_seq[] ROTATE(points input_seq[], double angle)
same as above, except there is no scaling but just rotation, the angle is from 0 to 359.9999 and is given in radians.
The size of the output is always the same as the size of the input.
Again the emphasis is on getting the output sequence as doubles, not so much on the actual drawing on a screen.
If you know the right terminology I should have used then let me know.
Thank you so much.
In Java, Path2D is suitable for 2D floating point coordinates. The lineTo() method will add straight lines to the path. Because Path2D implements the Shape interface, rotate and scale are possible via createTransformedShape(). One approach to interpolation, using PathIterator, is shown here.

How to get mouse position in float or double with exact resolution?

I need to take the mouse click position in float or double, how can I do that?In mouse listener, I take the point like this,
e.getPoint();
but Point object's x and y values are integer, I need position in float or double.
Any help will be appreciated.
Edit
I need exact resolution.
getPoint() gives you integer values because that is the precision in which coordinates are specified. See http://java.sun.com/j2se/1.4.2/docs/api/java/awt/Point.html.
Why do you need floating-point values?
Edit: in response to your comment, you will need to map your absolute positions to onscreen pixels, using a function like floor (always round down) or round (round to nearest int). The system has no notion of 0.2 pixels or anything like that. You can either continually truncate the decimal part of your calculations, or maintain the exact coordinates at all times and map them to pixels as needed.
From int you should be able to cast to double or float without any problems:
double x = e.getPoint().x;
double y = e.getPoint().y;
There are however methods that already do that:
double x = e.getPoint().getX();
double y = e.getPoint().getY();
Am I missing something here?
Please note, that the precision will not be higher - the mouse can only snap to full pixels, hence usually integer is fine. But if you need to calculate based on these values, the floating point representations might be useful.
You cannot get a more precise point then getPoint(), wich returns a Point object that only holds two integers.
What would like to achieve with this?

Categories

Resources