So I am making a simple pool game (no ball to ball collisions only ball to wall) and I'm kind of struggling (especially with an actual ball (diameter>0)). (After I figure out the logic and physics I am going to make it on c++ code)
So basically I have a coordinate system with the 4 edges of the pool table, ball coordinates, direction of hit and power of the hit.
So far I've semi-figured out 2 ways of calculating the end position of the ball when it meets a collision with the wall with a ball with 0 diameter:
A 5 formula algorithm combining vectors and lines to figure out the formula of the result line that the ball will travel on when it has collided with the wall. The problem here is that after I got this line I have no idea how to find the exact end position of the ball on this line(coordinate). (I use a perpendicular to the wall line to calculate the result angle at which its gonna bounce and then using some formulas and sin() cos() of that angle I find a and b for the ax+b = y formula of the line. To be more exact I find the perpendicular line formula with a system of 2 equations, then cos() of angle between 2 vectors, then sin() of that same angle to use it again in the same formulas but reversed in order to find the other coordinate, then using the two points I have I make a line)
I basically find where it's gonna hit the wall and since the power and direction of the hit is given I will just have 8 cases where the ball will hit each of the four walls and check which case I'm in and just reverse whatever x and y I need to. The problem with this is that if the ball has a diameter > 0 (so its an actual ball and not just a point) the ball is going to collide with the wall not at its center but at the side of the ball and I have no idea how to find exactly where the ball will collide with the wall and how that will change the line that it's gonna travel on/angle of the collision and the end position respectfully. (This method is likely to work but it would be really hard to implement, because of 8 cases to check which wall and what direction its going to hit it at also calculate the formulas of the lines of the edges and check where its going to hit exactly and a lot of other stuff) EDIT: This is going to be a little different since I'm changing a few things in the original logic.
Examples(I already made this part on code):
Ball is at (10, 10). A hit is given with direction (20,20) and power 1. Output: End Ball Pos = (20, 20)
Ball is at (10, 10). A hit is given with direction (20,20) and power 2. Output: End Ball Pos = (30, 30)
Example with wall being hit(playing field in this case is (0,0);(320,0);(320,160);(0,160):
Ball(300, 60), hit(250, 30), power 3 diameter 0: Output(150,30) (hits wall(200, 0))
Same case, but diameter 10: Output(150, 40) (hits wall(208.3333333, 5))
I don't need to find where it hits the wall only where the ball is going to end up after a hit(multiple wall collision are possible in one hit).
More info(playing field is always 1:2; isn't always parallel to x and y axis; ball can have any diameter; power ranges from 1 - 10; hitting corner is a different case not included in this question; friction is ignored and I I just need to move the ball to the designated position, doesn't mean that it will travel forever)
TL;DR need to find coordinates of ball after a collision with a wall.
Any help is appreciated! Thanks in advance!
Going from a point-like ball to a ball with a diameter is quite simple.
(I can't prepare images easily, so I must rely on your imagination.)
You have already experimented with a point-like ball bouncing off a wall. For example, if the wall is at x=W, and the "ball" approaches from the x<W side, with positive x-velocity, it will rebound at x=W and take on negative x-velocity.
Now consider a ball with radius r approaching the same wall, again from the x<W side with positive x-velocity. The collision will occur when the center of the ball is at x=W-r. Notice that the center point of the ball will move exactly as if it were a point-like ball striking a wall at x=W-r.
So to get the motion of a ball with radius r, simply move the walls in a distance r, and calculate the motion of a point-like ball. When you have that, draw a ball of radius r centered on that moving point.
Related
I have a bouncing ball which can collide lines with random slope. The ball pass through the lines of a bit and i need to set back the ball at a "radius" distance from the line.
Ball (with variables x, y and radius) travels at speedX and speedY (obtained from vectors directionX and directionY multiplied for a variable) and i can know the distance (dist) between the center and the line so i can know how many pixels the ball passed through the line
Think that in the example the ball passed 10 pixels (radius - dist) after the line, i need to set back the center of the ball 10 pixels in the opposite vector (directionX directionY). My question is:
How can i calculate how to split those n pixels between x and y so i can subtract them from the center coordinates?
I can imagine 4 different resolutions of what you have, and it is unclear which one you want.
Here they are, where the black arrow is the movement of the centre of the ball between the frame before collision and the frame you are asking how to draw.
A) the situation which you have now.
pro : simple
con : ball is in a physically unacceptable position
B) you compute where the ball should be after having bounced (assuming an elastic chock)
pro : most accurate
con : you don't have a frame with the ball in contact with the surface (but do you care ?).
C) The position of the ball is A, brought back to being tangent at the surface, with a correction that is orthogonal to said surface
pro : conserves accuracy in direction parallel to surface
con : centre of the ball not on the reflected line (i.e. we take liberties with Descartes' law)
D) The ball is still on the incoming line, but stopped when it is tangent to the surface.
pro : only the speed/timing is messed with
con : err.... out of ideas here. Still not as precise as B.
Well, disregarding all the drawings, it is much easier to take only the centre of the ball, and consider it hits a line that is at 'radius' of the real surface (and parallel to it), so we only have mechanics for a single point. Thus from the previous image, we get the formulation in terms of the following red objects :
So what do we need to do all this ?
The undisturbed trajectory starts at point S, ends at point E (the endpoint of situation A). We will call C the collision point between both lines (red one and trajectory, thus the endpoint of trajectory D).
I will assume we are always in the case of a collision, thus the point of intersection C between the undisturbed trajectory and the surface always exists.
You will also need the vector u that is perpendicular to the surface. Be sure to take a unit vector that points towards the side where the ball is. Thus if your slope has an equation ax+by+c=0, start with the vector ( a/sqrt(a*a+b*b) , b/sqrt(a*a+b*b) ) and multiply both coordinates by -1 if it points to the wrong side.
Then, to shift the line by a distance r in the direction of u, you want the equation a(x-r*u.x)+b(y-r*u.y)+c=0 thus ax+by+c-r*(a*u.x+b*u.y)=0
So if r is the radius and ax+by+c=0 your surface, the red line's equation is ax+by+c+r*sqrt(a*a+b*b)=0
or -r if the ball is beneath the line.
I will write PQ the vector starting at point P and ending at point Q, thus coordinates of said vector will be (Q.x - P.x, Q.y - P.y) and a . between two vectors will mean a scalar product.
So you can express SE in terms of the variables you named directionX, directionY and dist.
A) Move center by SE. Yay, finished !
B) Get C. Move center by SE - 2 * (CE . u) * u : thus the total move, but removing twice the normal component of CE that goes beyond the surface, effectively mirroring the CE vector by that surface.
C) Get C. Move center by SE - (CE . u) * u : the same, but remove the normal component of CE only once, effectively projecting the CE vector on the red line.
D) Get C. Move center by SC.
From the image, from bounce position, i want to predict position p1, p2 or p3 using some angle theta 1, 2 or 3.
How can i achieve this.
Any help please.
thanks
Edit:
I am trying to implement bowling control of Cricket.
To show the bowling trajectory, i need three points
start position, bounce position and end position
Start Position = the ball position where bowler releases ball from his hand.
Bounce Position = the pitching position of ball in front of batsman
End position = behind the stump (this will be calculated on the basis of swing i.e in swing or out swing or spin)
So my question is, i know the start position of ball, bounce position of the ball and i know the swing angle by which my ball is supposed to swing.
i need to calculated the end position of the ball by this.
i hope i make it clear now.
This is really just basic trig. Using p1 for example, you know c_x, c_y, b_x, b_y. b_x and c_y make d. subtraction gets you hard numbers.
So theta_1 is the inverse tangent of b -> d divided by d -> c (sohcahTOA!). In a unit circle the tangent theta_1 becomes Y/X.
see diagram
I have no idea how to play cricket though. I know it uses a flat(ish?) bat. If you want to analyse the effect of a batters swing, that gets more complicated.
So I have a system with colliding balls that generally works, except for when they collide with similar directions, less than 90 degrees apart.
This is because the ball above tries to collide against the yellow line which is supposedly the collision plane, but it sends it off the wrong direction, and it "follows" the other ball. The general algorithm for the collision is:
dot = direction.surface;
parallel = surface * dot;
perpendicular = direction - parallel;
direction = perpendicular - parallel;
Which negates the component of the direction parallel to the surface normal, which is perpendicular to the collision plane, and the part perpendicular to the surface normal is unchanged.
Does anyone know a fix for this? Have I done something wrong?
Edit: So now I added:
average = (ball1.velocity + ball2.velocity) / 2;
ball1.velocity -= average;
ball2.velocity -= average;
Before doing the calculations above, and after that:
ball1.velocity += average;
ball2.velocity += average;
To get in the right reference frame, according to #Beta's answer. The problem now is that the speeds of the balls aren't maintained, since they both have the same speeds and masses, yet after the collisions they're different. I do not think this is supposed to happen, or is it?
Consider the 1D problem of bouncing a ball off a wall. Simple.
Now watch me bounce a ball off the forward bulkhead of a jet plane in flight. The ball is moving north at 252 m/s, the bulkhead is moving north at 250 m/s. The answer is not obvious. But shift into my coordinate frame (by subtracting the velocity of the bulkhead, 250 m/s, from everything) and the problem is trivial. Solve it, then shift the result back into the ground frame (by adding 250 m/s to everything) and you're done.
Now the 2D problem of a ball bouncing off a wall at an angle. Simple. (But verify that your code does it correctly.)
Now two balls colliding with equal and opposite momenta (I'll assume they have the same mass, for now). You can imagine a yellow wall at the collision plane, and the answer comes easily.
Now two balls colliding, but with velocities that do not add up to zero. There's still a yellow wall, but it's moving. Well, shift into the wall's frame by subtracting the average of the balls' velocities (sum/2) from everything, solve the simpler problem, then shift back by adding that same velocity back to everything, and you're done.
I'm implementing a simple Volleyball game using Box2D in Flash. I need to implement some AI for the CPU player. Let's call him Jack. So Jack needs to predict where's the ball gonna land after it has been hit by John, the human player. I have the following information :
Initial Linear Velocity (both in x & y direction) of the ball when John
hits it.
The initial position of the ball when John hits it. (x & y coordinate
values)
The value of gravity.
The value of y position of floor where's the ball's gonna fall.
The angle at which John hits the ball.
The ball follow a projectile trajectory.
So Jack needs to predict what would be the position (x value) of the ball when it hits the floor.
I think as the ball follows a projectile trajectory the problem might be seen same as that of - firing a cannon ball from some known initial position, known initial velocity with fixed gravity and predicting its landing spot. The y value of landing spot is also known. The air resistance is zero.
Is there any kind of mathematical equation which might help to predict the x value of the landing spot? I took a look at some projectile equations but most of them take 'time' as a variable. I need to have a solution that doesn't involve this 'time' variable. Any kind of work-arounds for this problem would also be appreciated. Thank you! :)
If you have an equation for z (i.e. height) in terms of t, then you need to solve that for z = 0 to get the value of t when the ball lands. You can then feed that back into the equations for x and y.
You have to solve z(x)=0 with this equation:
g is gravity, v0 is initial speed along x axis, a is the angle.
When you solve it, it gives the length of the segment joining start point and end point (choose one end point depending on the hit direction).
If you're in 3D, you'll have to do some projections to remove the 3D part of the problem, and keep only two axis.
Initial Linear Velocity (both in x & y
direction) of the ball when John hits
it.
The initial position of the ball when
John hits it. (x & y coordinate
values)
The value of gravity.
And the direction - negative y-direction, of course. 32.2 ft/sec^2 = 9.8 m/sec^2, right?
The value of y position of floor
where's the ball's gonna fall.
It'll hit at y = 0 if no other player touches it.
The angle at which John hits the ball.
I think it'd be better to say something about the force John applies to the ball and for how long.
The ball follow a projectile
trajectory.
No, you have no such thing. This is what you're trying to solve.
What you have is Newton's law: F = ma, where force is the vector of force applied to the ball, m is the mass of the ball, a is the acceleration vector applied to the ball.
The ball is accelerated by gravity in the negative y-direction, of course, but you're forgetting the force vector that the player applies when the ball is struck.
Once you have those you solve two coupled ODEs forward in time.
I'm having trouble wrapping my mind around how to calculate the normal for a moving circle in a 2d space. I've gotten as far as that I'm suppose to calculate the Normal of the Velocity(Directional Speed) of the object, but that's where my college algebra mind over-heats, any I'm working with to 2d Circles that I have the centerpoint, radius, velocity, and position.
Ultimately I'm wanting to use the Vector2.Reflect Method to get a bit more realistic physics out of this exercise.
thanks ahead of time.
EDIT: Added some code trying out suggestion(with no avail), probably misunderstanding the suggestion. Here I'm using a basketball and a baseball, hence base and basket. I also have Position, and Velocity which is being added to position to create the movement.
if ((Vector2.Distance(baseMid, basketMid)) < baseRadius + basketRadius)
{
Vector2 baseNorm = basketMid - baseMid;
baseNorm.Normalize();
Vector2 basketNorm = baseMid - basketMid;
basketNorm.Normalize();
baseVelocity = Vector2.Reflect(baseVelocity, baseNorm);
basketVelocity = Vector2.Reflect(basketVelocity, basketNorm);
}
basePos.Y += baseVelocity.Y;
basePos.X += baseVelocity.X;
basketPos.Y += basketVelocity.Y;
basketPos.X += basketVelocity.X;
basketMid = new Vector2((basketballTex.Width / 2 + basketPos.X), (basketballTex.Height / 2 + basketPos.Y));
baseMid = new Vector2((baseballTex.Width / 2 + basePos.X), (baseballTex.Height / 2 + basePos.Y));
First the reflection. If I'm reading your code right, the second argument to Vector2.Reflect is a normal to a surface. A level floor has a normal of (0,1), and a ball with velocity (4,-3) hits it and flies away with velocity (4,3). Is that right? If that's not right then we'll have to change the body of the if statement. (Note that you can save some cycles by setting basketNorm = -baseNorm.)
Now the physics. As written, when the two balls collide, each bounces off as if it had hit a glass wall tangent to both spheres, and that's not realistic. Imagine playing pool: a fast red ball hits a stationary blue ball dead center. Does the red ball rebound and leave the blue ball where it was? No, the blue ball gets knocked away and the red ball loses most of its speed (all, in the perfect case). How about a cannonball and a golf ball, both moving at the same speed but in opposite directions, colliding head-on. Will they both bounce equally? No, the cannonball will continue, barely noticing the impact, but the golf ball will reverse direction and fly away faster than it came.
To understand these collisions you have to understand momentum (and if you want collisions that aren't perfectly elastic, like when beanbags collide, you also have to understand energy). A basic physics textbook will cover this in an early chapter. If you just want to be able to simulate these things, use the center-of-mass frame:
Vector2 CMVelocity = (basket.Mass*basket.Velocity + base.Mass*base.Velocity)/(basket.Mass + base.Mass);
baseVelocity -= CMVelocity;
baseVelocity = Vector2.Reflect(baseVelocity, baseNorm);
baseVelocity += CMVelocity;
basketVelocity -= CMVelocity;
basketVelocity = Vector2.Reflect(basketVelocity, basketNorm);
basketVelocity += CMVelocity;
The normal of a circle at a given point on its edge is going to be the direction from its center to that point. Assuming that you're working with collisions of circles here, then one easy "shorthand" way to work this out would be that at the time of collision (when the circles are touching), the following will hold true:
Let A be the center of one circle and B the center of the other. The normal for circle A will be normalize(B-A) and the normal for circle B will be normalize(A-B). This is true because the point where they touch will always be colinear with the centers of the two circles.
Caveat: I'm not going to assume that this is completely correct. Physics are not my specialty.
Movement has no effect on a normal. Typically, a normal is just a normalized (length 1) vector indicating a direction, typically the direction that a poly faces on a 3d object.
What I think you want to do is find the collision normal between two circles, yes? If so, one of the cool properties of spheres is that if you find the distance between the centers of them, you can normalize that to get the normal of the sphere.
What seems correct for 2d physics is that you take the velocity * mass (energy) of a sphere, and multiply that by the normalized vector to the other sphere. Add the result to the destination sphere's energy, subtract it from the original sphere's energy, and divide each, individually, by mass to get the resulting velocity. If the other sphere is moving, do the same in reverse. You can probably simplify the math down from there, of course, but it's late and I don't feel like doing it :)
If both spheres are moving, repeat the process for the other sphere (though you could probably simplify that equation to get some more efficient math).
This is just back-of-the-napkin math, but it seems to give the correct results. And, hey, I once derived Euler angles on my own, so sometimes my back-of-the-napkin math actually works out.
This also assumes perfectly elastic collisions.
If I'm incorrect, I'd be happy to find out where :)