Alright, this is probably gonna be a pretty simple question to answer. I haven't had a math class dealing with logarithms in a few years, so I apologize. So I have a USB Controller that I'm using to control the mouse on the screen with the left joystick. Now how this works right now is the controller returns a double between 0.00 and 1.00 depending on how far the push the joystick in the direction (0.00 center, 1.00 pushed all the way over). I'm using this to adjust the speed of the mouse movement by multiplying the returned value by a given speed (returned double * speed). This gives me a linear speed. But for the purpose of accuracy of the mouse and clicking things on screen, I'd like it to be more logarithmic, so as it's really slow when barely pushing, and then the speed increases logarithmically as you move the joystick farther. That way you can get good speed for moving across the screen, while also having good sensitivity when moving it slowly. So I just need help with the formula, as I'm sure it's pretty simple. Also, I'm working in Java.
Right now my formula is:
double value (value given by controller)
int speed = 25;
value += value * speed;
I then use this to move the mouse.
Thanks,
Brayden
I presume you meant exponential. An exponential function looks like http://hotmath.com/images/gt/lessons/genericalg1/exponential_graph.gif: the more value is, the larger the derivative (the more speed will increase for the same change in value).
double value = ...;
int base = 25;
value = java.lang.Math.pow(base, value);
Not sure if java.lang.Math is necessary in its full form or whether you need to import java.lang.Math first. I'm not a Java programmer.
I agree with MvanGeest, I think you want an exponential formula. That way its small with little distance, and very big with larger distances.
I'm not sure what mouse speed values are fast or slow, but you could do something like
double value (value given by controller);
int speed (maximum speed value);
value = Math.pow(speed, value);
You could also make the value something like 2*(whatever the controller gives you) to make a wider range of speeds.
Something like:
f(value) = value * MAXSPEED * Math.Pow (base, 1 - value)
f(0) = 0 // no movement
f(1) = MAXSPEED // maximum movement when joystick is full throttle
All values should be covered in the range. Base in this case can be any value greater than 1.
Related
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.
I know this probably isn't very hard, but I need to convert a percentage into a range of numbers. I am making a test right now, and I want to display a progress bar of sorts. The bar starts at (75, 425) and goes to (625, 425) on my JFrame. So the range of x values would be from 75 to 625. I want the left side of the screen to be 0% and the right side to be 100%. I would draw a line on the bar wherever the percentage was. Thanks for any help you can give.
To calculate the x value you simply take the following equation:
x = left + percentage/100 * (right-left)
with the numbers you provided filled in it looks like this:
x = 75 + percentage/100 * (625 - 75)
Keep in mind that this is not doable with only integer arithmetic since percentage/100 results in a value in the rage of 0..1 and therefore should be float or double.
You should consider using a JProgressBar as suggested by Ron.
Why don't you use the JProgressBar for that purpose.
You won't need to know the position of the Bar, all you have to do is add a propertyChangedListener.
I recommend reading : https://docs.oracle.com/javase/tutorial/uiswing/components/progress.html
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
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.
I am using a seekbar to change the volume of my MediaPlayer. The progress level is what I am using which gives a "1 to 100" int. I need to convert that into the float range of 0.0f to 1.0f. What is the correct way of doing that?
Thanks guys
float fVal = (float)val / 100; should do the trick.
divide by 100
int intValue = 1;
float floatValue = intValue/100.0;
Very late in the day, but as I was just reading up on this very subject I thought it worth posting an answer that doesn't just perform a straight linear scaling of the slider value 0 - 100 into a float value 0.0 - 1.0 and explain why you should be doing it differently.
So the API documentation for MediaPlayer.setVolume(float, float) states, in passing, that "UI controls should be scaled logarithmically" but doesn't explain why.
Sound as we hear it is measured in decibels (db), on a logarithmic scale. In simplified terms (over-simplified if you are an audio buff), twice the decibels = twice the volume. But because the decibel scale is logarithmic, the distance on the scale from (for example) 0 - 3db is bigger than the distance on the scale from 3db to 6db.
The most obvious effect of using linear scaling instead of logarithmic is that the volume with the slider at maximum is much more than twice as loud as the volume at half way, so most of the noticeable change in volume level happens in the lower three quarters (approximately) of the slider range rather than in an (apparently) linear fashion across the full slider range. And this is why straight linear scaling isn't quite the right way to translate a slider position into a value for the setVolume method.
Here's a simple function that will take your slider value (assumed to lie in the range 0 - 100), convert it into a logarithmic value and scale it:
private float scaleVolume(int sliderValue) {
double dSliderValue = sliderValue;
double logSliderValue = Math.log10(dSliderValue / 10);
double logMaxSliderValue = Math.log10(10);
float scaledVolume = (float) (logSliderValue / logMaxSliderValue);
return scaledVolume;
}
Now, the slider at 50 (the center position) will produce a sound that is about half as loud as when the slider is at 100 (the top position), and the slider at 25 will produce a sound that is half as loud as when the slider is at 50.
Be aware that your perception of what is "twice as loud" will be affected by the kind of audio you are playing as well as the quality of the speaker and how hard it is being pushed...
To map linearly to the range 0.0 to 1.0 use
int n = <some value>;
float val = (float)(n - 1)/99;