This has been solved. Scroll to my 3rd post below.
[HR][/HR]
I wanted to know if I am implementing correctly. And is there a way to obtain the square root of a vector?
I implemented an excerpt pseudo-code from Ian Millington’s Artificial Intelligence for Games’s Firing Solution on Chapter 3.5.3. According to the pseudo-code, it goes like this:
function firingSolution (start, target, muzzle_v, gravity) {
// Calculate vector back from target to start
delta = target - start
// Real-valued coefficents of quadratic equation
a = gravity * gravity
b = -4 * (gravity * d + muzzle_v * muzzle_v)
c = 4 * delta * delta
// Check for no real solutions
if ( 4 * a * c > b * b ) return null
// Find short and long times to target
disc = sqrt (b * b - 4 * a *c)
t1 = sqrt ( ( -b + disc ) / (2 * a ))
t2 = sqrt ( ( -b - disc ) / (2 * a ))
// Pick shortest valid time to target (ttt)
if ( t1 < 0 ) && ( t2 < 0) return null // No valid times
if ( t1 < 0 ) ttt = t2 else
if ( t2 < 0 ) ttt = t1 else
ttt = min ( t1, t2 )
// Return firing vector
return ( 2 * delta - gravity * ttt * ttt ) / ( 2 * muzzle_v * ttt )
}
Where gravity, delta, and muzzle_v are vectors. At the end of the excerpt, the book mentioned that ***** may represent dot product.
Here’s my code written in UE4:
FVector MuzzleVelocity = FVector(1024.0f);
FVector Gravity = FVector(0.0f, 0.0f, -9.8f);
FVector Delta = CannonLocation - CurrentLocation;
float gravity = -9.8f;
float distance = FVector::Dist(CannonLocation, CurrentLocation);
float velocity = 215.0f;
float a = Gravity | Gravity;
float b = -4.0f * ((Delta | Gravity) + (velocity * velocity));
float c = 4.0f * (Delta | Delta);
//No solutions
if (FMath::Sqrt(((Gravity | Delta) + 1024.0f * 1024.0f)) < ((Gravity | Gravity) * (Delta | Delta))){
LOG("No solutions.");
return;
}
float disc = FMath::Sqrt((b*b) - (4.0f * a*c));
float time0 = FMath::Sqrt((-b + disc / (2 * a)));
float time1 = FMath::Sqrt((-b - disc / (2 * a)));
float PlusMinus = FMath::Sqrt(FMath::Square<float>((Gravity | Delta) + (velocity * velocity)) - ((Gravity | Gravity)*(Delta | Delta)));
float time2 = 2.0f * FMath::Square<float>((((Gravity | Delta) + (velocity * velocity) + PlusMinus) / (2.0f * (Gravity | Gravity))));
float time3 = 2.0f * FMath::Square<float>((((Gravity | Delta) + (velocity * velocity) - PlusMinus) / (2.0f * (Gravity | Gravity))));
float ttt = 0.0f;
if (time2 < 0.0f && time3 < 0.0f) { LOG("No valid times."); return; }
if (time2 < 0.0f && time3 >= 0.0f) { ttt = time2; }
if (time2 > 0.0f && time3 < 0.0f) { ttt = time3; }
if (time2 > 0.0f && time3 >= 0.0f) { ttt = FMath::Min<float>(time2, time3); }
FVector Result = ((2.0f * Delta) - (Gravity * FMath::Square<float>(ttt))) / (2.0f * velocity * ttt);
I feel like I did the right thing. The end result is that I can fire at an angle, but the angle is too sensitive. One slight bump, and the trajectory goes off by a lot. Does anyone know what other ways to tweak the values in order to get the trajectory correct?