Vertical projectile motion, finding interersection with moving target - math

I am writing an aimbot script for my AI, I am a bit confused about how to get the vertical projectile motion formulas to help me find the time and initial velocity required to fire the projectile at so it hits its target, For the target, I have its velocity and vertical displacement, I thought a Quadratic formula to find the intersection of its displacement over time intersecting with the projectiles displacement over time would be the solution but now I am stuck because I am missing the initial velocity as well as the time, Any help would be appreciated :)

Orient your coordinate plane such that the y-axis is up/down from your perspective, and the z-axis passes through you and your target (+ being towards the target). We do not care about x. Center the origin on you.
We need to first talk about finding the time it takes a projectile to travel from you to the target. Assuming there's no air drag, the projectile will move at a constant velocity along the z axis (it may accelerate along the y-axis, however). This gives us:
df_pz = a_pz * t**2 / 2 + vi_pz * t + di_pz
df_pz : final displacement - projectile's z component
di_pz : initial displacement - projectile's z component
a_pz : acceleration - projectile's z component
vi_pz : initial velocity - projectile's z component
t : time
If we assume there's no air resistance, a_pz is zero, and since the origin is centered on you, di_pz is zero. That leaves:
df_pz = vi_pz * t
We know df_pz is the distance to the target along the z-axis, and can solve for time t for the projectile to travel there. t will be defined in terms of vi_pz, which is fine.
Now, lets talk about your target's motion. Your target will follow a trajectory:
df_ty = a_ty * t**2 / 2 + vi_ty * t + di_ty
df_ty : final displacement - target's y component
di_ty : initial displacement - target's y component
a_ty : acceleration - target's y component
vi_ty : initial velocity - target's y component
t : time
We know t however (or, have an equation we can substitute in anyways), so we can plug in and solve for the final displacement (in terms of vi_pz).
With the df_ty value, we can now determine the initial y velocity of the projectile. We'll be using a similar formula:
df_py = a_py * t**2 / 2 + vi_py * t + di_py
df_py : final displacement - projectile's y component
di_py : initial displacement - projectile's y component
a_py : acceleration - projectile's y component
vi_py : initial velocity - projectile's y component
t : time
We have time t, the a_py may or may not be equal to a_ty, depending on the game engine, but I'll assume you know that value regardless. We know di_py is zero since we're centered at the origin. That just leaves vi_py and df_py. Since we want to intercept the target, df_py equals df_ty.
We then plug in those values and solve for vi_py. This gives us the initial velocity of the projectile along the y axis, in terms of vi_pz.
Now, with this newest equation, we'll actually solve for vi_py and vi_pz. Take the equation:
|V|**2 = vi_py**2 + vi_pz**2
|V| - magnitude of the initial velocity vector
The value |V| should be constant for any shot (assuming you can't "charge" you shot to shoot the projectile faster / further).
Take whatever this value is, substitute the value for vi_py (defined in terms of vi_pz) and solve for vi_pz. This will give you a concrete value for vi_pz. Take this, plug it back into the equation for vi_py, and obtain a concrete value for vi_py. Do the same for t.
Now, there may be one issue- df_ty we used earlier may be wrong. If df_ty is so low that it places the target below the ground, we need to clamp it to ground-level. Plug in vi_pz and check. This is just a simple if statement, I won't be writing a formula for this. You do need to know what y coordinate is "ground-level" below the target.
If this happens, also recompute a new vi_py, vi_pz, and t using this new df_ty. The process will be much the same, except you already have a concrete value for df_ty now, so you can skip the part involving |V| to get vi_py.
And there you have it: vi_py, vi_pz, and t - the velocity and time necessary to intercept the target. You may have to take this one step further and calculate the angle to shoot at, which would just be arctan(vi_py/vi_pz).

Finding the time tmin where the missile and target are at the closest approach is fairly straightforward.
Consider at the time of launch t=0 the target missile is at the origin, with an initial velocity vector v and being tracked as a function of time as
p(t) = v t + 0.5 g t2
where g is the gravity vector (usually pointing downwards).
At the time of launch, the target is at position vector o, moving with velocity vector u and being tracked over time with
r(t) = o + u t + 0.5 g t2
The time of minimum distance is
tmin = (o·(v-u)) / ((v-u)·(v-u))
Here · is the vector dot product and it results in a number.So both the numerator and denominators are numbers.
The closest approach distance is
dmin = √( (o·o) - (o·(v-u))2 / ((v-u)·(v-u)) )
The next part is harder. To optimize the problem, in order to make the minimum distance zero, and find the velocity vector that fits the constraints (max. speed, or time to impact).
The insight here is that the launch velocity vector must be on the plane defined by the target velocity vector and gravity. The simplest approach here is to employ a numerical method to estimate the minimum distance as a function of the launch angle if the launch speed is fixed.
There is an analytical solution here but is very complex and it depends on some assumptions.
Furthermore, once the optimal trajectory is found, you can play around to see which launch speed works best. With some random testing I did I noticed the required speed at the optimal angle as a function of a delay from detection jumps to a really high value at some point, and then gradually decreases. I suppose this corresponds to the time the target is mostly overhead. Optimally you want to detect the target as early as possible.

Related

Calculate angle Pinball

Right now I am coding a Pinball clone in ActionScript (actually in this case the language doesn't matter). I have the following problem: I have two paddles and a ball moving with a certain speed (represented as a velocity vector). I can't figure out how to calculate the new velocity vector of the ball after hitting the paddle. All my calculations are going terribly wrong.
What I have:
Current angle of the paddle (in radians), the velocity vector of my ball and the current angle (in radians) of that vector where 1,5708 (90 degrees) is straight down (e.g. velocity vector with x = 0 and y = 5).
Does anyone have an idea how to approach this. The programming language doesn't matter here - pseudo code is also fine.
You need to mirror the velocity vector (vx,vy) on the line with direction
(c,s) = ( cos(anglePaddle), sin(anglePaddle))
so that the component orthogonal to it gets reverted and the component parallel to it remains the same. The orthogonal component is
(-s,c)*(-s*vx+c*vy)
so that the reflected vector becomes
(vx,vy) - 2*(-s,c)*(-s*vx+c*vy) = ( c2*vx + s2*vy, s2*vx - c2*vy )
where double angle trigonometric identities where used to simplify using
(c2,s2) = ( cos(2*anglePaddle), sin(2*anglePaddle)).

Gravity's acceleration between two objects

So I am making a program, where you can have two objects (circles). I want them to orbit like planets around each other, but only in 2D.
I know that using Newtons Universal Law of Gravitation I can get the force between the two objects. I also know A = F / M. My question is how would I take the A from the previous equation and change it into a vector?
You need to use vector equations:
// init values (per object)
double ax=0.0,ay=0.0,az=0.0; // acceleration [m/s^2]
double vx=0.0,vy=0.0,vz=0.0; // velocity [m/s]
double x=0.0, y=0.0, z=0.0; // position [m]
double m=1.0; // mass [kg]
// iteration inside some timer (dt [seconds] period) ...
int i; double a,dx,dy,dz; // first compute acceleration
for (ax=0.0,ay=0.0,az=0.0,i=0;i<obj.num;i++)
if (obj[i]!=this) // ignore gravity from itself
{
dx=obj[i].x-x;
dy=obj[i].y-y;
dz=obj[i].z-z;
a=sqrt((dx*dx)+(dy*dy)+(dz*dz)); // a=distance to obj[i]
a=6.67384e-11*(obj[i].m*m)/(a*a*a); // a=acceleration/distance to make dx,dy,dz unit vector
ax+=a*dx; // ax,ay,az = actual acceleration vector (integration)
ay+=a*dy;
az+=a*dz;
}
vx+=ax*dt; // update speed via integration of acceleration
vy+=ay*dt;
vz+=az*dt;
x+=vx*dt; // update position via integration of velocity
y+=vy*dt;
z+=vz*dt;
Code is taken from here
obj[] is list of all your objects
obj.num is the count of them
I recommend to create object class with all the variables inside (ax,ay,az,...m), init them once and then continuously update (iteration) in some timer. If you want more accuracy then you should compute ax,ay,az for all objects first and only after update speed and position (to avoid change of position of objects during gravity computation). If you want to drive an object (like with truster) then just add its acceleration to ax,ay,az vector)
Now to setup an orbit just:
place planet object
must be massive enough and also set its position / velocity to what you want
place satellite
Initial position should be somewhere near planet. It should not be too massive. Init also speed vector with tangent direction to orbiting trajectory. If speed is too low it will collapse into planet and if speed is too high it will escape from planet otherwise will be orbiting (circle or ellipse)
timer
lower the interval better the simulation usually 10ms is OK but for massive and far objects is also 100ms and more OK. If you want particles or something then use 1ms (very dynamic sceene).
I strongly recommend to read this related QA:
Is it possible to make realistic n-body solar system simulation in matter of size and mass?
especially [edit3] about the integration precision and creating orbital data.
With two objects you are probably best using an ellipse which is the path the objects will follow about their common center of mass. Read Kepler's laws of planetary motion which gives the background.
If one object is a much greater mass than the other, i.e. a sun and a planet you can have one stationary and the other taking an elliptical path. The equation of the ellipse is given by
r = K e / ( 1 + e cos(theta))
K is a constant giving the size and e is the eccentricity. If you want an elliptical orbit have 0 < e < 1 the smaller it is the more circular the orbit. To get x, y coordinates from this use, x = r cos(theta), y = r sin(theta). The missing bit is time and how the angle is dependant on time. This is where the second and third laws come in. If a and b are the semi-major and semi-minor lengths of the ellipse, and P is the period then
0.5 * P * r^2 theta'= pi a b
theta' is the rate of change of angle with respect to time (d theta/d t). You can use this to get how much theta will change given a increase in time. First work out the current radius r0 given the current angle th0 if the time increment is δt then the angle increment δtheta is
δtheta = 2 pi * a * b / r^2 * δt
and the next angle is th0 + δtheta.
If the masses are of similar magnitude then see two body problem. Both objects will have elliptical orbits, there are two patterns which you can see in animations on that page. The ellipses will follow the same formula as above with the focus at the common center of mass.
If you have three object things get considerably harder and there are not generally neat solutions. See three body problem for this.

Aim at moving target (or predicting target's position at time it takes for projectile to hit it)

I have a game where I know the location and velocity of my target. I know my own location and the speed of my projectile. I want to determine either
the location of the intersection between my projectile fired and the target, or
the time taken for my projectile to intersect the target
All entities are travelling with constant speed and direction which makes life easier. I have been trying to work out the maths for some time but cannot quite get it right. I know that the predicted location of the target intersecting the projectile will be
Pp = Tp + Tv * t
Where Pp is the predicted position, Tp is the current target position, Tv is the target velocity, and t is time.
I also know that t = |Pp - Sp| / Bs
where Sp is my (source) position and Fs is the projectile (bullet) speed. But I cannot figure out a way to solve this to get either Pp or t.
Can anyone enlighten me? Thanks
I found a website detailing one method but this doesnt seem to work (http://howlingmoonsoftware.com/wordpress/leading-a-target/). My verification method to determine if it worked was to use the predicted position to determine the time for the target to reach it, and for the projectile to reach it. These should be very similar but in my game they are out by almost a factor of 2.
I managed to solve this using the cosine rule and quadratic equation at the same time as finding another solution online.
based on the cosine rule
c^2 = a^2 + b^2 -2ab.cos(C)
We know the angle C as it is the angle between the targets direction, and our relative location from the target
We know b as it is the distance between us and the target
We know a is time * target speed
We know c is time * projectile speed
this reduces down to get the quadratic
(projspeed^2 - targetvelocity^2)*t^2 + 2*targetvelocity*distancefromtarget*cos(C)*t - distancefromtarget^2 = 0
this can be solved using quadratic alternate form:
t = 2c / (-b + sqrt(b^2 -4ac))
Once we have t we can use PredictionPos = TargetPos + t * TargetVelocity
To verify the result is correct we can work out the time for the target to reach the destination and the projectile to reach the destination - these should be equal
I believe that the quadratic equation is actually t = (-b ± sqrt(b^2 - 4ac)) / 2a.
I would have added this as a comment, but I lack the required reputation.

3D Target Leading formula for a ballistic trajectory

I was wondering if there was a target leading formula for target leading in 3d with a ballistic trajectory and if not i was wondering if it is possible to convert a 2d target leading formula to work as a 3d target leading formula by aligning the plane it is on along the motion of the target?
Leading the target can be easily calculated at the time the projectile is fired, however there is no guarantee the target won't change course, accelerate, or decelerate while the projectile is in the air. In any case, when you're leading the target you can either assume that the target's velocity will remain the same, or if it is accelerating, that its acceleration will remain the same.
Here's a blog post I wrote about predicting a traveled distance over time, accounting for acceleration. And here is the code I use.
This will calculate a distance traveled, over time, given a constant acceleration. In this case constantAccel is a speed, and if your target isn't accelerating then you would just use 0.0f for that parameter.
float CalcDistanceOverTime(const float initVelocity,
const float constantAccel,
const float timeDelta)
{
return (initVelocity * timeDelta)
+ (0.5f * constantAccel * (timeDelta * timeDelta);
}
Here's an example:
Vector3 targetsVelocity(3.0f, 0.0f, 3.0f);
float targetsAcceleration = 1.0f;
float distanceTraveled = CalcDistanceOverTime(targetsVelocity, targetsAcceleration, timeDelta)
Vector3 finalPosition = targetsVelocity * distanceTraveled;
You may notice that you'll need a timeDelta to pass to this formula. This means, based on your projectile's trajectory and speed, you'll need to know about how long it will take to reach the target, however it is made more difficult by the fact that you don't know exactly how long that may take until you know where it will be. I'm not sure of the exact formula for this, but I believe using Calculus you could calculate, based on the speed and velocity of your projectile, and the speed and velocity of your target, accounting for gravity with both, that you should be able to find a point in space where these two can collide.
If the above method isn't feasible then you may be able to choose a fixed timeDelta, if you can guarantee your projectile can go at whatever angle and speed that you would like. For example, pick 3 seconds as your timeDelta, you know where the target will be in 3 seconds, and immediately fire a projectile that you know will reach that point in space within 3 seconds.
And just in case, here's a blog post about calculating ballistic trajectory in 3D. Calculating the time to target with this method should be simple, based on outgoing vertical velocity and position, just use gravity to calculate how many seconds until that position reaches the elevation at the target position.

Simple Problem - Velocity and Collisions

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.

Resources