My pong ball has x and y values from 0.0 to 1.0, which are the bounds the screen.
It bounces off the screen just fine, but won't recognize my paddle. My paddles have values outside the range detectable, I don't know how to get the values to be between 0.0 and 1.0.
I need to get the values to be between 0.0 and 1.0
float paddleHeightTop = (float)(rPaddle - (height/10));
float paddleHeightBottom = (float)(rPaddle + (height/10));
float paddleLeadingEdge = (float) (rPaddle/1000);
paddleLeadingEdge has value 897.0, needs to be 0.897... Refuses to convert, remains 897.
I haven't worked out the math on the paddleHeightTop or Bottom, but they also need to have a value between 0.0 and 1.0...
paddleHeightTop has value 183.0.
paddleHeightBottom has value 1.8970001.
rPaddle updates it's value from on 'onMotionEvent'.
My code for onDraw for paddle looks like this (and draws and updates position correctly):
canvas.drawRect( 93 * (width / 100) , rPaddle - (height/10), 95 * (width / 100), rPaddle + (height/10), light);
I'm putting that here because I'm sure there some relationship I'm missing.
Thanks ahead of time.
PS:
This is my collision detector (moved from comments):
if (ballY < paddleHeightTop && ballX > paddleLeadingEdge && ballY > paddleHeightBottom ) {
soundPool.play(paddleSound, 1, 1, 0, 0, 1);
ballSpeedX *= -1;
}
My Android Studio Debugger was having an error, never mind.
Related
I am trying to get into creative coding mainly for creating live visuals. I have recently stumbled upon this great website called https://www.openprocessing.org/ where people can share their creations.
I have attached code below for creating two moving circles but I am having trouble understanding how the creator went about doing so, If anyone could explain to me how the for loop is working as well as how the x += 0.006; y += 0.006; if (x > TWO_PI) {x = 0;} section works, it would be greatly appreciated. The use of sin, cos and the Two_PI functions has me puzzled. Here is a link to the original code:
https://www.openprocessing.org/sketch/467333
//comment
float x = 0;
float xx = 0;
float y = 0;
float yy = 0;
float sizecircle = 250;
void setup() {
size (800, 650);
frameRate (60);
strokeWeight (1);
stroke (223, 170, 22);
}
void draw() {
background (51, 51, 51);
for (float i = 0; i < TWO_PI; i += TWO_PI/100) {
line (350 + sin(x+i) * sizecircle, 275 + cos(y+i) * sizecircle, 450 + cos(xx+i) * sizecircle, 375 + sin(yy+i) * sizecircle);
}
x += 0.006;
y += 0.006;
if (x > TWO_PI) {
x = 0;
}
if (y > TWO_PI) {
y = 0;
}
xx += 0.002;
yy += 0.002;
if (xx > TWO_PI) {
xx = 0;
}
if (yy > TWO_PI) {
yy = 0;
}
}
The unit of the angle for sin and cos is Radian. 360° are 2*PI, this is the reason for TWO_PI.
The variables x, y, xx and yy are incremented for 0.0 to 2*PI. If they reach 2*PI, they start form 0.0 again.
With the following code will draw lines from a center point (cx, cy) to 100 points around a circle with radius r.
for (float i = 0; i < TWO_PI; i += TWO_PI/100) {
line(cx, cy, cx + cos(i)*r, cy + sin(i)*r);
}
The trick in the code of the question is that the lines are connection the points around 2 circles, which are rotating opposite direction:
line(cx1 + sin(i)*r, cy1 + cos(i)*r,
cx2 + cos(i)*r, cy2 + sin(i)*r);
Note, that the order of sin and cos is swapped for the start point in compare to the end point, this causes that the circles are rotating opposite directions.
The different rotation speed is caused by the different constants 0.006 respectively 0.002.
By the way, the code can be simplified, because x == y and xx == yy. It is sufficient to use 2 angles in the range [0, TWO_PI]:
float a1 = 0;
float a2 = 0;
float sizecircle = 250;
void draw() {
background (51, 51, 51);
for (float i = 0; i < TWO_PI; i += TWO_PI/100) {
line (350 + sin(a1+i)*sizecircle, 275 + cos(a1+i)*sizecircle,
450 + cos(a2+i)*sizecircle, 375 + sin(a2+i)*sizecircle);
}
a1 += 0.006;
a2 += 0.002;
}
Since sin(x) == sin(x + TWO_PI*n) and cos(x) == cos(x + TWO_PI*n) (n is an integral number), it is not necessary to "reset" the angles.
It's more about math than about programming (well, both these things goes hand in hand).
He's doing the same thing twice, once for each circle, but one of the two will "move" faster than the other, hence the difference in x += 0.006; and xx += 0.002;.
There are 2 PI radians in a full circle (so 2 PI radians == 360 degrees). That's why he's using this measure.
This line
line (350 + sin(x+i) * sizecircle, 275 + cos(y+i) * sizecircle, 450 + cos(xx+i) * sizecircle, 375 + sin(yy+i) * sizecircle);
defines how each circle is "attached" to the other one by drawing a bunch of lines between them. The idea is that the author created a loop that updated the beginning point and the end point of a line, and this loop runs as long as there are lines to draw (it goes around the circle using the 2 PI number).
So in the for (float i = 0; i < TWO_PI; i += TWO_PI/100) loop he draws every line for this position of the circles.
Than he changes the "starting point" where he'll draw the first line by increasing variables x, y, xx, yy a little bit. As they are used in the context of radians, they "circle" around the circles.
Then the draw() loop start over again and he re-draws the whole thing, but a little different as the starting points changed. This makes the drawing look like it moves.
When the "starting points" variables x, y, xx, yy are finished doing a complete turn (so when they are over 2 PI radians), he resets them. As it's a full turn, it's not a huge reset. It's like rounding the time when the clock is one minute past the hour.
Hope it helps.
I am trying to rotate a 2D Point in java around another with a specified degree value, in this case simply around Point (0, 0) at 90 degrees.
Method:
public void rotateAround(Point center, double angle) {
x = center.x + (Math.cos(Math.toRadians(angle)) * (x - center.x) - Math.sin(Math.toRadians(angle)) * (y - center.y));
y = center.y + (Math.sin(Math.toRadians(angle)) * (x - center.x) + Math.cos(Math.toRadians(angle)) * (y - center.y));
}
Expected for (3, 0): X = 0, Y = -3
Returned for (3, 0): X = 1.8369701987210297E-16, Y = 1.8369701987210297E-16
Expected for (0, -10): X = -10, Y = 0
Returned for (0, -10): X = 10.0, Y = 10.0
Is something wrong with the method itself? I ported the function from (Rotating A Point In 2D In Lua - GPWiki) to Java.
EDIT:
Did some performance tests. I wouldn't have thought so, but the vector solution won, so I'll use this one.
If you have access to java.awt, this is just
double[] pt = {x, y};
AffineTransform.getRotateInstance(Math.toRadians(angle), center.x, center.y)
.transform(pt, 0, pt, 0, 1); // specifying to use this double[] to hold coords
double newX = pt[0];
double newY = pt[1];
You're mutating the X value of center before performing the calculation on the Y value. Use a temporary point instead.
Additionally, that function takes three parameters. Why does yours only take two?
The following code rotates the line towards the mouse position using a simple ease function, but the problem is that the atan2() methods works form -PI to PI, making the line to rotate backwards when the angle reach either of the limits, I can make it to rotate from 0 to TWO_PI but there is no different as the line will rotate backwards until it reach the targetAngle, if I dont use the easing calculation works fine because there jump from -PI to PI is unnoticeable, so how can I ease my rotation and avoid this problem?
float angle = 0;
float targetAngle = 0;
float easing = 0.1;
void setup() {
size(320, 240);
}
void draw() {
background(200);
noFill();
stroke( 0 );
// get the angle from the center to the mouse position
angle = atan2( mouseY - height/2, mouseX - width/2 );
// check and adjust angle to go from 0 to TWO_PI
if ( angle < 0 ) angle = TWO_PI + angle;
// ease rotation
targetAngle += (angle - targetAngle) * easing;
pushMatrix();
translate( width/2, height/2 );
rotate( targetAngle );
line( 0, 0, 60, 0 );
popMatrix();
}
Thanks
Not sure if I understood the problem correctly... Do you mean that if the mouse position is slightly less than +PI, and targetAngle is slightly greater than -PI, then the line rotates away from the mouse? The thing is that even if both values are in the same range (-PI, PI), they still can be quite far away from each other. You must adjust angle to fit the PI-neighbourhood of the current targetAngle value.
// get the angle from the center to the mouse position
angle = atan2( mouseY - height/2, mouseX - width/2 );
// check and adjust angle to be closer to targetAngle
if ( angle < targetAngle - PI ) angle = angle + TWO_PI;
if ( angle > targetAngle + PI ) angle = angle - TWO_PI;
This will work if targetAngle is in the range (-TWO_PI, TWO_PI). It seems that it will work for you. If targetAngle can have any value very far away from the working range, then you can use something like this:
// get the angle from the center to the mouse position
angle = atan2( mouseY - height/2, mouseX - width/2 );
// calculate the shortest rotation direction
float dir = (angle - targetAngle) / TWO_PI;
dir = dir - Math.round(dir);
dir = dir * TWO_PI;
// ease rotation
targetAngle += dir * easing;
i ran into a strange problem when trying to flip the y-axis of a coordinate system that im creating:
private AffineTransform getTransform() {
if (transform == null) {
transform = new AffineTransform();
double scaleX = (double) this.getWidth() / (coordinateSystem.getMaxX() - coordinateSystem.getMinY());
double scaleY = (double) this.getHeight() / (coordinateSystem.getMaxY() - coordinateSystem.getMinY());
transform.setToScale(scaleX, scaleY);
double deltaX = (coordinateSystem.getMaxX() - coordinateSystem.getMinX()) / 2;
double deltaY = (coordinateSystem.getMaxY() - coordinateSystem.getMinY()) / 2;
transform.translate(deltaX, deltaY);
}
return transform;
}
The AffineTransform is set to scaling and translation. and everything works fine except that my y-values are inverted (max value is a the bottom of the coordinate system, min value is at the top). I tried switching this by inverting the scale factor for the y axis. but this was not working.
Do i have to let the Transform rotate by PI, to achieve the flipped y axis?
Shouldn't multiplying the scale factor for the y axis by minus 1 be the same?
You have a typo on
double scaleX = (double) this.getWidth() / (coordinateSystem.getMaxX() - coordinateSystem.getMinY());
(Last Y should be an X.) Perhaps that's it.
Rotating by PI is actually NOT a right solution at all, since it will flip the X axis as well as the Y.
What is the logic that goes behind rotating an image via mouse movement. I know how to rotate using graphics2d.rotate...but having difficulty doing it with the mouse as the source for rotation. Here is basic steps:
get mouse x(dx) and mouse y(dy) distances from anchoring point( in this case that would be
the center of the image we want to rotate).
use this point in Math.arcTan2(dy,dx) to obtain the angle or rotation.
use the value from step to for Graphics2D.rotate method.
With that strategy, everytime i rotate the image, the image starts rotating from -pi and after 90 degrees of rotation it go goes back to -pi. I don't understand what I'm doing wrong here, it should be pretty basic.
Here is a part of the code :
// mouse dragged events get sent here.
public void mouseDragged( MouseEvent e ) {
int mx = e.getX( ), my = e.getY( );
// just checking if it falls within bounds of the image we
// want to rotate.
if( mx > speedKX || mx < speedKX + speedK.getWidth( ) || my > speedKY || my < speedKY + speedK.getHeight( )/2 )
{
theta += getTheta( e.getX( ), e.getY( ) );
}
}
As I understand you should look for the initial angle (when you clicked, the line between the anchor and your click) and the current angle (when you are dragging, same line). That angle (independent from the current distance to anchor point) will give you the rotation.
So you have to:
rotate(anglenow - angle0)
How to find it:
In both cases (initial click and mouse move event) you have to find angle between anchor and mouse point thinking the anchor as the origin.
I would use a method (getAngle(x1,y1,x2,y2). That method (except for race conditions like same x or same y, easily detectable) should calculate arctan(dy/dx).
Sign
But when you are dividing dy/dx it can be:
+ / + -> +
+ / - -> -
- / + -> -
- / - -> +
It is, four posibilities give you two kind of results. So, you have to look some condition to detect them.
I should review arctan doc or source to see what values it gives (between 0 and pi, or -pi/2 and +pi/2) and check then sign of the dx or the dy (depending on what range arctan returns) and use it to add/decrement pi to then resulting angle.
Then you'll get a getAngle method that return correctly the 360º space.
Edit
Javadoc says:
Math.atan retuns the arc tangent of an angle, in the range of -pi/2 through pi/2.
So, assuming your angle of value 0 is for the X axis as I assumed, the range it returns is the right hemisphere. So you have to distiguish the right hemisphere from the left one.
If you calculate dx = xtarget - xorigin (as you did for the division) it will be positive if the correct hemisphere is the right one, and negative if it's not.
So if dy < 0 then you have to add pi to your resulting angle. It will be between -pi/2 and 3pi/2. You also can correct the result by passing all to (-pi,pi) range or (0,2pi) range.
Edit: pseudocode, please double check!
onmousedown {
startpoint = (x,y);
startangle = getAngle(origin, startpoint);
}
onmousemove {
currentpoint = (x,y);
currentangle = getAngle(origin, currentpoint);
originalimage.rotate(currentangle - startangle);
}
getAngle(origin, other) {
dy = other.y - origin.y;
dx = other.x - origin.x;
if (dx == 0) // special case
angle = dy >= 0? PI/2: -PI/2;
else
{
angle = Math.atan(dy/dx);
if (dx < 0) // hemisphere correction
angle += PI;
}
// all between 0 and 2PI
if (angle < 0) // between -PI/2 and 0
angle += 2*PI;
return angle;
}