There are two stages to solving this problem:
- Calculate the required launch direction of the projectile to hit the moving target
- Compute a screen coordinate that corresponds to firing in this direction
You can use standard equations of motion to approach the first stage:
f
= the projectile’s speed (number)
s
= the target’s current displacement (vector: start position to target position)
m
= the target’s velocity (vector: assumes this stays constant)
v
= our launch velocity (vector: we are going to calculate this)
t
= time (number: we are going to calculate this - it will equal the time taken for the projectile to hit)
(1) vt = s + mt
This means that after time t
, moving at velocity v
, the projectile will have reached the point where the target is at that time (this ensures we have a collision).
(2) vx^2 + vy^2 + vz^2 = f^2
This means that the squared length of the velocity vector must be equal to the square of the projectile’s speed. You may have noticed that we are applying the Pythagorean Theorem here.
We want to solve for t
, and to do that we need to eliminate the unknown v
. We can do this by first squaring equation (1)
. Note that squaring a vector here can be considered the same as taking a dot product (•) of the vector with itself.
(3) (v•v)t^2 = (s + mt)^2
(3) (v•v)t^2 = s•s + 2t(m•s) + (m•m)t^2
We can also rewrite equation (2)
in dot product form (see the algebraic definition of the dot product).
(4) v•v = f^2
Now we can substitute equation (4)
into equation (3)
.
(5) f^2t^2 = s•s + 2t(m•s) + (m•m)t^2
Now we can rearrange this to express it in terms of t
(this is what we are solving for).
(5) t^2(f^2 - m•m) - t(2 * m•s) - s•s = 0
Expressed in this form, we can apply the Quadratic Formula to solve for t
.
a = f^2 - m•m
b = -2 * m•s
c = -s•s
A preliminary step is to calculate the discriminant and check its value to determine if a solution exists.
d = b^2 - 4*a*c
If d is less than zero, there are no solutions - this means it’s impossible to hit the moving target.
We can now solve for two values of t
.
t0 = (-b + sqrt(d)) / (2 * a)
t1 = (-b - sqrt(d)) / (2 * a)
If both values are less than zero, then there are no solutions. If one value is less than zero and the other is not, choose the one which is greater than zero. If both values are greater than zero, then there are two possible launch directions. You can decide which to use / display.
Having calculated t
, we can plug this back into (1)
to solve for the launch velocity, v
.
(6) v = (s + mt) / t
(6) v = s / t + m
The launch direction is simply the normalized v
vector (in Roblox Lua, you can get this with v.unit
).
I’ll leave the second problem for you or someone else to solve.
Hopefully I understood your question correctly and haven’t made any mistakes in my explanation - please let me know if I have (or if there is a much better way to do this)!