For fun I am making Pong in Python with Pygame. I have run into some trouble with reflections.
So the ball has an angle associated with it. Since positive y is down this angle is downward. If the ball hits the top or bottom walls I can simply negate the angle and it will reflect properly, but the trouble is with the left and right walls. I cannot figure out the trigonometry for how to change the angle in this case. I am currently trying combinations of the below snippet but with no luck.
self.angle = -(self.angle - math.pi/2)
I have attached the code. You can try it for yourself easily. Just remember to take out the "framerate" module which I have not included or used yet. I would appreciate any input. Thanks!
You'll want to look into Angle of Incidence.
Basically you'll want to find the angle theta between your incoming vector and the normal of the wall the ball is hitting. Where the incoming angle is (wall normal)-theta the resulting angle is (wall normal)+theta.
The angle can be found using the dot product between your incoming vector and the normal of the wall, then taking the inverse cosine (normalize your vectors first).
You should use:
math.pi - angle
Related
Yeah, yeah, I checked out the suggested questions/answers that were given to me but most involved quaternions, or had symbols in them that I don't even HAVE on my keyboard.
I failed at high school trig, and while I understand the basic concepts of sin and cos in 2D space, I'm at a loss when throwing in a third plane to deal with.
Basically, I have these things: centerpoint, distance, and angles for each of the three axes. Given that information, I want to calculate the point that is -distance- away from the center point, at the specified angles.
I'm not sure I'm explaining this correctly. My intent is to get what amounts to electrons orbiting around a nucleus, if anyone happens to know how to do that. I am working with Java, JRE 6, if there are any utility classes in there that can help.
I don't want just an answer, but also the how and why of the answer. If I'm going to learn something, i want to learn ABOUT it as well. I am not afraid to take a lesson in trigonometry, or how quaternions work, etc. I'm not looking for an entire course on the answer, but at least some basic understanding would be cool.
If you did this in 2D, you would have a point on a plane with certain x and y coordinates. The distance from the origin would be sqrt(x^2+y^2), and the angle atan(y/2).
If you were given angle phi and distance r you would compute x= r*cos(phi); y=r*sin(phi);
To do this in three dimensions you need two angles - angle in XY plane and angle relative to Z axis. Calling these phi and theta, you compute coordinates as
X = r*cos(phi)*sin(theta);
Y = r*sin(phi)*sin(theta);
Z = r*cos(theta);
When I have a chance I will make a sketch to show how that works.
I have a complicated problem and it involves an understanding of Maths I'm not confident with.
Some slight context may help. I'm building a 3D train simulator for children and it will run in the browser using WebGL. I'm trying to create a network of points to place the track assets (see image) and provide reference for the train to move along.
To help explain my problem I have created a visual representation as I am a designer who can script and not really a programmer or a mathematician:
Basically, I have 3 shapes (Figs. A, B & C) and although they have width, can be represented as a straight line for A and curves (B & C). Curves B & C are derived (bend modified) from A so are all the same length (l) which is 112. The curves (B & C) each have a radius (r) of 285.5 and the (a) angle they were bent at was 22.5°.
Each shape (A, B & C) has a registration point (start point) illustrated by the centre of the green boxes attached to each of them.
What I am trying to do is create a network of "track" starting at 0, 0 (using standard Cartesian coordinates).
My problem is where to place the next element after a curve. If it were straight track then there is no problem as I can use the length as a constant offset along the y axis but that would be boring so I need to add curves.
Fig. D. demonstrates an example of a possible track layout but please understand that I am not looking for a static answer (based on where everything is positioned in the image), I need a formula that can be applied no matter how I configure the track.
Using Fig. D. I tried to work out where to place the second curved element after the first one. I used the formula for plotting a point of the circumference of a circle given its centre coordinates and radius (Fig. E.).
I had point 1 as that was simply a case of setting the length (y position) of the straight line. I could easily work out the centre of the circle because that's just the offset y position, the offset of the radius (r) (x position) and the angle (a) which is always 22.5° (which, incidentally, was converted to Radians as per formula requirements).
After passing the values through the formula I didn't get the correct result because the formula assumed I was working anti-clockwise starting at 3 o'clock so I had to deduct 180 from (a) and convert that to Radians to get the expected result.
That did work and if I wanted to create a 180° track curve I could use the same centre point and simply deducted 22.5° from the angle each time. Great. But I want a more dynamic track layout like in Figs. D & E.
So, how would I go about working point 5 in Fig. E. because that represents the centre point for that curve segment? I simply have no idea.
Also, as a bonus question, is this the correct way to be doing this or am I over-complicating things?
This problem is the only issue stopping me from building my game and, as you can appreciate, it is a bit of a biggie so I thank anyone for their contribution in advance.
As you build up the track, the position of the next piece of track to be placed needs to be relative to location and direction of the current end of the track.
I would store an (x,y) position and an angle a to indicate the current point (with x,y starting at 0, and a starting at pi/2 radians, which corresponds to straight up in the "anticlockwise from 3-o'clock" system).
Then construct
fx = cos(a);
fy = sin(a);
lx = -sin(a);
ly = cos(a);
which correspond to the x and y components of 'forward' and 'left' vectors relative to the direction we are currently facing. If we wanted to move our position one unit forward, we would increment (x,y) by (fx, fy).
In your case, the rule for placing a straight section of track is then:
x=x+112*fx
y=y+112*fy
The rule for placing a curve is slightly more complex. For a curve turning right, we need to move forward 112*sin(22.5°), then side-step right 112*(1-cos(22.5°), then turn clockwise by 22.5°. In code,
x=x+285.206*sin(22.5*pi/180)*fx // Move forward
y=y+285.206*sin(22.5*pi/180)*fy
x=x+285.206*(1-cos(22.5*pi/180))*(-lx) // Side-step right
y=y+285.206*(1-cos(22.5*pi/180))*(-ly)
a=a-22.5*pi/180 // Turn to face new direction
Turning left is just like turning right, but with a negative angle.
To place the subsequent pieces, just run this procedure again, calculating fx,fy, lx and ly with the now-updated value of a, and then incrementing x and y depending on what type of track piece is next.
There is one other point that you might consider; in my experience, building tracks which form closed loops with these sort of pieces usually works if you stick to making 90° turns or rather symmetric layouts. However, it's quite easy to make tracks which don't quite join up, and it's not obvious to see how they should be modified to allow them to join. Something to bear in mind perhaps if your program allows children to design their own layouts.
Point 5 is equidistant from 3 as 2, but in the opposite direction.
Okay I'm working on a Space sim and as most space sims I need to work out where the opponents ship will be (the 3d position) when my bullet reaches it. How do I calculate this from the velocity that bullets travel at and the velocity of the opponents ship?
Calculate the relative velocity vector between him and yourself: this could be considered his movement if you were standing still. Calculate his relative distance vector. Now you know that he is already D away and is moving V each time unit. You have V' to calculate, and you know it's length but not it's direction.
Now you are constructing a triangle with these two constraints, his V and your bullet's V'. In two dimensions it'd look like:
Dx+Vx*t = V'x*t
Dy+Vy*t = V'y*t
V'x^2 + V'y^2 = C^2
Which simplifies to:
(Dx/t+Vx)^2 + (Dy/t+Vx)^2 = C^2
And you can use the quadratic formula to solve that. You can apply this technique in three dimensions similarly. There are other ways to solve this, but this is just simple algebra instead of vector calculus.
Collision Detection by Kurt Miller
http://www.gamespp.com/algorithms/collisionDetection.html
Add the negative velocity of the ship to the bullet, so that only the bullet moves. Then calculate the intersection of the ship's shape and the line along which the bullet travels (*pos --> pos + vel * dt*).
The question probably shouldn't be "where the ship will be when the bullet hits it," but IF the bullet hits it. Assuming linear trajectory and constant velocity, calculate the intersection of the two vectors, one representing the projectile path and another representing that of the ship. You can then determine the time that each object (ship and bullet) reach that point by dividing the distance from the original position to the intersection position by the velocity of each. If the times match, you have a collision and the location at which it occurs.
If you need more precise collision detection, you can use something like a simple BSP tree which will give you not only a fast way to determine collisions, but what surface the collision occurred on and, if handled correctly, the exact 3d location of the collision. However, it can be challenging to maintain such a tree in a dynamic environment.
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 :)
I am trying to animate an object, let's say its a car. I want it go from point
x1,y1,z1
to point x2,y2,z2 . It moves to those points, but it appears to be drifting rather than pointing in the direction of motion. So my question is: how can I solve this issue in my updateframe() event? Could you point me in the direction of some good resources?
Thanks.
First off how do you represent the road?
I recently done exactly this thing and I used Catmull-Rom splines for the road. To orient an object and make it follow the spline path you need to interpolate the current x,y,z position from a t that walks along the spline, then orient it along the Frenet Coordinates System or Frenet Frame for that particular position.
Basically for each point you need 3 vectors: the Tangent, the Normal, and the Binormal. The Tangent will be the actual direction you will like your object (car) to point at.
I choose Catmull-Rom because they are easy to deduct the tangents at any point - just make the (vector) difference between 2 other near points to the current one. (Say you are at t, pick t-epsilon and t+epsilon - with epsilon being a small enough constant).
For the other 2 vectors, you can use this iterative method - that is you start with a known set of vectors on one end, and you work a new set based on the previous one each updateframe() ).
You need to work out the initial orientation of the car, and the final orientation of the car at its destination, then interpolate between them to determine the orientation in between for the current timestep.
This article describes the mathematics behind doing the interpolation, as well as some other things to do with rotating objects that may be of use to you. gamasutra.com in general is an excellent resource for this sort of thing.
I think interpolating is giving the drift you are seeing.
You need to model the way steering works .. your update function should 1) move the car always in the direction of where it is pointing and 2) turn the car toward the current target .. one should not affect the other so that the turning will happen and complete more rapidly than the arriving.
In general terms, the direction the car is pointing is along its velocity vector, which is the first derivative of its position vector.
For example, if the car is going in a circle (of radius r) around the origin every n seconds then the x component of the car's position is given by:
x = r.sin(2πt/n)
and the x component of its velocity vector will be:
vx = dx/dt = r.(2π/n)cos(2πt/n)
Do this for all of the x, y and z components, normalize the resulting vector and you have your direction.
Always pointing the car toward the destination point is simple and cheap, but it won't work if the car is following a curved path. In which case you need to point the car along the tangent line at its current location (see other answers, above).
going from one position to another gives an object a velocity, a velocity is a vector, and normalising that vector will give you the direction vector of the motion that you can plug into a "look at" matrix, do the cross of the up with this vector to get the side and hey presto you have a full matrix for the direction control of the object in motion.