I'm making a breakout/brick-breaker/arkanoid clone (opengl-es/android) and I've been stuck on my collision detection code for quite some time. As the title suggests: How do I figure out which side of a brick has been hit by the ball ?
Since I only need to invert the speed in a certain direction, x or y, when a brick is hit I could think of:
if(speedY < 0) : left, upper or right
else : left, bottom or right
if(speedX < 0) : bottom, right or upper
else : bottom, left or upper
however this doesn't bring me far in deciding if it collided vertical or horizontal, and with that, which direction I should send the ball next.
I've looked at some code examples on the internet, however those often are very vague, complicated or off-topic for me.
Well, if you know the position of the Brick and the position of the ball you can do tests on each object to determine the side of the brick.
Assuming the standard Java origin in the top-left:
+----+
( )| |
+----+
If the ball's Max-X is < the Min-X of the brick, you know that it has to be on the left side, and vice versa with the right and left. You would also test the Y values for top and bottom collisions.
Of course this assumes you've gotten the collision detection working first.
EDIT
This is an excerpt from my Collision engine, this is just a small bit for an example, but this is how I test if the object is to the left of the thing it's colliding with.
else if ((oCenter.getX() < sCenter.getX())
&& ((oCenter.getY() < (sCenter.getY() + sourceHalfHeight))
&& (oCenter.getY() > (sCenter.getY() - sourceHalfHeight))))
return LEFT;
In my example here oCenter is a Point2D and it's the center of the ball. sCenter is a Point2D and it's the center of a rectangular shape. sourceHalfHeight is half the height of the rectangular shape (the object with the center point sCenter).
The Pseudo-code algorithm:
if (the center X of the ball < the center X of the rectangle
AND the center Y of the ball is BETWEEN the max Y and min Y of the rectangle)
then the ball is to the LEFT of the rectangle
end if
The thing is, you cannot know it with the speed only, as the ball could hit 2 different sides at 2 different times, both times with the same speed in the same direction.
Ex:
First line hits the top, second one hits the side, but both have the same speed and direction
/
/ /
_____ /
|_____|
You would have to use the ball's position and compare it with each sides of the brick
Related
I'm not necessarily looking for code to solve this problem but more how to figure out the logic behind it.
I'm doing a homework problem for a Computer Science class I'm taking and one of the problems states, "Method isUntangled that accepts two parameters: a circle’s diameter and a square’s side length, both of type double. It returns true if and only if the circle and square do not intersect when their centers are aligned"
This is the image provided to help with understanding:
Image
I have tried to just simply return True if the diameter is less than the squares side length or return True if the side length of the square is less than the diameter of the circle. Looking back at it now I see why it didn't work.
I'm more seeing if someone could explain the logic/math that could be used to figure this problem out.
Thank You
there is 2 ways to understand logic
1. medium square flexible circle
assume there is a medium size square & at it center, very small circle.
increase the diameter of circle & check all cases.
firstly circle fully inside of square.
when diameter & side length become same, circle touch side at midpoint. (total 4 touch)
after that, circle intersect 2 time with every side until step 4.(total 8 intersection)
last time circle only touch corners of square. at this time we need to find what is the diameter of circle ? (total 4 touch)
that time diagonals of square touch circle (it's chords) & also pass through center of circle, so diagonals are diameter
diameter = diagonal = side * √2
after that, circle leave square totally.
2. medium circle flexible square
assume there is a medium size circle & at it center, very small square.
increase the length of side of square & check all cases.
firstly square fully inside of circle.
first time square's corner touch circle. (total 4 touch) at this time we need to find what is the length of side ? (total 4 touch)
that time diagonals of square touch circle (it's chords) & also pass through center of circle, so diagonals are diameter
side = diagonal / √2 = diameter / √2
after that, square's every side intersect 2 time with circle until step 4.(total 8 intersection)
last time, when diameter & side length become same, only square's midpoint of sides touch circle.
after that, square leave circle totally.
so, in this both case circle & square are tangent between those 2 state (same in both cases).
With the centers aligned, there are three cases:
circle outside the square
circle and square intersect
square inside circle.
'3' applies if the diameter of the circle is less than one-half the square length.
'1' applies if the diameter of the circle is greater than the distance from the square center to a square corner. that's half the length of the square's diagonal.
'2' applies in all other cases.
return diameter > length && diameter / 2 < length / Math.sqrt(2)
First condition checks that circle not inside the square and second condition checks that square not inside the circle
The equation of a circle is x^2 + y^2 = r^2
You only need to work out if one of the square's lines collides with the circle to see any if them collide since they're aligned in the center. The equation of a line is x = c where c is a constant. You can substitute the value of x or y into the circle equation. For example, for x = 2:
2^2 + y^2 = r^2 => 4 + y^2 = r^2
r is given to you too, so substitute that in r = 1 => 4 + y^2 = 1^2 = 1
=> y^2 = -3
Hence, since there's no (real) square root of -3, they don't collide.
If the circle is sufficiently big enough, relative to the square, there will be a real solution to the last part. Our equation of a line that represents the square's side should actually be constrained since the squares straight lines don't go on forever, they stop at x = y = +- square_length/2. So check if y(from equation) < y(square_height) (or x and width, they're the same). So essentially, there are 2 cases you need to check. You can turn that into code.
I am writing a program that allows a user to left-click the panel and add a bouncing ball, and right-click to remove a ball. The balls bounce off of all walls with a constant velocity. I have all of this finished. The last part that I cannot figure out is handling the collisions with other bouncing balls. The same results as bouncing off of the walls should occur. Any help will be greatly appreciated. Here is the code for the movement of the ball so far...
#SuppressWarnings("AccessingNonPublicFieldOfAnotherObject")
private void processMovement(long interval)
{
/* Compute the distance moved in the interval. Decompose the distance
moved into x and y components, and determine the next position of the Ball
by those amounts. */
float x = position.x + velocity.getDistanceX(interval);
float y = position.y + velocity.getDistanceY(interval);
position.setLocation(x, y);
/* Collisions with the walls. If so, adjust the speed and direction for
the next period. */
/* Collision with the east or west (vertical) wall. */
float wall;
if( x <= (wall = 0.0F) ||
x >= (wall = model.getDimension().width - SIZE) )
{
x = wall;
velocity.reverseX();
}
/* Collision with the north or south (horizontal) wall. */
if( y <= (wall = 0.0F) ||
y >= (wall = model.getDimension().height - SIZE) )
{
y = wall;
velocity.reverseY();
}
position.setLocation(x, y);
}
When I wrote a program like this, I ended up creating a wall object, which had a start x/y and an end x/y. Geometry was needed in order to determine the correct ricochet/bounce angle since walls could be at any orientation. Essentially the direction of the ball changes by two times the difference in orientation between the wall and the ball's direction. For example, if the ball is moving at 45* above the X-axis, and the wall is oriented at 90* above the X-axis (i.e. it's straight up and down), then the ball's new heading is its original heading plus two times the difference between its heading and the wall's direction, or in other words 45* + 2*(90*-45*), or in other words, 135*. The problem is that it doesn't work if you consider the wall's orientation to be -90* (i.e. 90* below the X-axis, which is still straight up and down). In that case you'd calculate the ball's new heading as -45* which is wrong. It also matters if you hit the wall from the left or from the right. Fun, right? Lots of things to think about.
Balls collide when their centers are within (R1 + R2) distance of each other, where R1 is the radius of the first ball, and R2 is the radius of the second ball.
Essentially, what I did was I created a temporary (invisible) wall that was perpendicular with the vector from the center of one ball to the center of the other, and then I ordered the two balls to bounce off of this wall. This gave the correct ricochet behavior.
I know you probably don't care about my "wall collision" stuff, but I think what I have described could give you something of an idea of the kind of geometry you're going to need to perform in order to solve this problem.
In short, bouncing balls off of each other correctly is difficult. Consider removing/abandoning this functionality if it's not required and/or you're not willing to spend the effort.
You could also put together something less correct, but easier. You could simply have balls move away from each other when they collide, but then you'd get "unnatural" looking ricochets.
I know it certainly doesn't solve your problem, but hopefully this helps.
In Java (at least when using Bluej as the environment), the top left corner pixel is (0,0) and bottom left is (600,600)(depending on window size). Your logic is unfamiliar to me, but assuming your math is correct to have the balls reverse direction when hitting a wall you should have 4 if statements per ball. I know there are ways of getting away with 1 or 2 and my way is ugly and not very effecient, but a least it will isolate if the problem is your math of logic.
if (X<=0 || X>=600)
{
velocity.reverseX();
}
if (Y<=0 || Y>=600)
{
velocity.reverseY();
}
I hope this helps :)
I've implemented a kind of Pong where the paddles (Rectangle2D) can rotate.
To obtain more accuracy, many things are managed by Graphics2D.
The rotation too is managed by the methods rotate(...) of the previous told class.
To reach a realistic bounce, I need to know where the ball hits the paddle (only the side, not the particular point).
I've tried to define (and rotate) two Rectangle2D that represent the back and the front side of the paddle and then recognize the bounce in one of these two by the method hit(Rectangle2D r, Shape s, boolean onStroke), but it doesn't work properly.
Here is the java class Graphics2D:
http://docs.oracle.com/javase/7/docs/api/java/awt/Graphics2D.html
Have you any idea?
Assuming you have one rectangle for your paddle and know the center of rectangle and circle and the rotation of your rectangle.
Assuming a rotation of zero means, your rectangle is aligned horizontally (width > height).
Calculate the difference vector (center of circle) - (center of rectangle)
Get the angle of that vector and subtract the rotation of your rectangle (angle of vector is Math.atan2(y, x))
The resulting value a tells you the relative direction of your circle
Make sure a lies between 0 and 2*pi
q = Math.atan2(height of rectangle, width of rectangle)
If a is between q and pi-q, your circle has hit on the front long (upper) side.
If a is lower than q or bigger than 2*pi-q it's on the right side.
If a is between pi-q and pi+q it's on the left side.
If a is between pi+q and 2pi-q it's hit the bottom of your rectangle
I am writing a Java program that closely mimics Microsoft Paint. It can draw four different shapes: Lines, Ovals, Rectangles, and Squares. I am very close to finishing this but I am stuck on the logic for drawing squares.
There are two Points involved while drawing these shapes. The first Point(point1) is when the user presses the mouse button and the second Point(point2) is while the user drags the mouse across the canvas. I believe drawing Rectangles and Squares should be quite similar but the part that has confused me is when drawing a square the sides are equal length so point2 isn't exactly where the mouse is.
Here is the fillRect() method header for reference:
fillRect(x, y, width, height)
My functioning code for drawing rectangles is as follows:
g.fillRect((((point1.x < point2.x) ? point1.x : point2.x)),
((point1.y < point2.y) ? point1.y : point2.y),
Math.abs(point2.x - point1.x),
Math.abs(point2.y - point1.y));
I tried using the same code for drawing squares except changing the height parameter to be equal to the width parameter because squares have equal length sides:
g.fillRect((((point1.x < point2.x) ? point1.x : point2.x)),
((point1.y < point2.y) ? point1.y : point2.y),
Math.abs(point2.x - point1.x),
Math.abs(point2.x - point1.x)); //same as width
I don't know what the problem is with making both width and height equal. It works when drawing downwards to the left or right but of course the shape does not expand if you pull straight down. Clicking and dragging up does not work; the square simply moves up with the mouse along the Y axis instead of expanding.
Could anyone point me in the right direction regarding the logic for drawing square from two points?
I can explain my code a bit better if need be.
If I were using a tool to draw a square, I would expect that my mouse cursor would remain on one of the sides of the square while drawing. If you always use the x distance as the side, then if I've drawn farther down than across, the cursor will be outside the square.
I think, while the dragging is going on, the code would need to calculate whether the x distance or the y distance to the origin is the longer, and use that as the side of the square-in-progress. Then the cursor will be on one of the sides, and that side will extend out beyond the cursor to the corner of the square-in-progress.
I don't know why the drawing is going awry -- it is difficult to be sure I understand what you say is going wrong.
You should do two calculations in your MouseDragged method -- first you should calculate the two corner Points of the rectangle, p1, and p2, and only then should you calculate the width. Point p1 is easy -- it's always the first Point pressed, but p2 will require a simple calculation. Once these are clarified, your calculations should fall out correctly.
i.e., something like:
int width = Math.abs(pointA.x - pointB.x);
int height = Math.abs(pointA.y - pointB.y);
width = Math.max(width, height);
height = width;
int x = pointA.x > pointB.x ? pointA.x - width : pointA.x;
int y = pointA.y > pointB.y ? pointA.y - width : pointA.y;
g.fillRect(x, y, width, height);
I'm creating a 3D renderer in Java, which currently can render the wireframe of a cube using Points and lines and rotate the cube, the question is, what should Z be? And what should be set to Z? I'm guessing that the size of the cube should be set to Z?
Thanks for your time! Any answers would be much appreciated.
Z usually means the out-of-plane direction if the current viewport lies in the x-y plane.
Your 3D world has its own coordinate system. You'll transform from 3D world coordinates to viewport coordinates when you render.
I think you might be missing some basic school math/geometry here. However, it's actually not that hard to understand.
Imagine a flat plane, e.g. a sheet of paper.
The first coordinate axis will go straight from left to right and we'll call it X. So X = 0 means your point is on the left border. X = 10 might mean your point is on the right border (really depends on how big you define a unit of 1; this could be in centimeters, inches, etc.). This is already enough to describe some point in one dimension (from left to right).
Now, we need a second axis. Let's call it Y. It's running from the top border (Y = 0) to the bottom (Y = 10). Now you're able to describe any point on the plane as you've got two positions. For example, (0, 0) would be the top left corner. (10, 10) would be the bottom right corner. (5, 0) would be the center point of the top border, etc.
What happens if we add yet another dimension? Call it Z. This will essentially be the height of your point above the sheet. For example, Z = 0 could mean your point is sitting on the sheet of painter, while Z = 10 means your point is sitting 10 cm above the paper. Now you use three coordinates to describe a point: (5, 5, 0) is the center of the paper. (5,5,5) is the center of the cube sitting on your paper filling it and being 10 cm high.
When programming in 3D, you can use the same terminology. The only real difference is, that you're using a so called projection/view matrix to determine how to display this 3d positions on screen. The easiest transform could be the following matrix:
1 0 0
0 1 0
Multiplying this with your 3d coordinates you'll get the following two terms:
2d-x = 3d-x
2d-y = 3d-y
This results in you viewing the cube (or whatever you're trying to display) from straight above essentially ignoring the Z axis again (you can't render something sticking out of your display, unless using some kind of 3d glasses or similar technology).
Overall, it's up to you how you use the coordinates and interpret them. Usually x and y refer to the plane (position on the ground or position inside a 2D world) while z might be the height or the depth (front or back). It really depends on the specific case. But in generic, it's really just another dimension like x and y.
3D means 3 "Dimensions". One dimension is "X", the other "Y", the third "Z". None have a sepcific direction, though it's convenient to conventionally assign a direction, for example "Forward", "Left", and "Up".
Something whose X, Y, and Z values are all equal to 0 resides at the origin, or center of the space. You can write this as (0,0,0) where the order of the parameters are (x,y,z).
A point or vertex at the location (1,0,0) is one unit in the X direction from the origin. So if you moved from (0,0,0) to (1,0,0), you would be moving purely in the X direction.
(0,1,0) is one unit in the Y direction away from the origin.
(0,0,1) is one unit in the Z direction away from the origin.
(1,1,0) is one unit in the X direction and one unit in the Y direction. So if X means "Forward", and Y means "Left", then (1,1,0) is forward-and-left of the origin.
So a basic cube can be defined by the following vertices:
(1,1,-1)
(1,-1,-1)
(-1,1,-1)
(-1,-1,-1)
(1,1,1)
(1,-1,1)
(-1,1,1)
(-1,-1,1)