3
$\begingroup$

I have a situation where I am trying to calculate a leading shot for a character in a 2D top down game. The enemy character moves with a certain speed $s$, which is applied to its normalized direction vector each game tick--so the game ticks are discrete units of "time" as opposed to actual time.

I have my character, which shoots a bullet with speed $z$. During my leading shot calculation, I can aim my character towards the enemy character, and calculate $\phi$ between the line drawn directly between the enemy and my character.

I need to somehow calculate $\theta$, the angle I need to shoot the bullet in order to hit the enemy character...the unknowns are: $t$, $\theta$, and the third angle.

Can't remember how to do this.

Here is a picture of the situation: enter image description here

$\endgroup$
  • $\begingroup$ $${\sin (\theta)\over s*t} = {\sin (\phi)\over z*t}$$ $\endgroup$ – A---B Jul 7 '16 at 13:33
  • $\begingroup$ thought it was something simple like that...but I refused to believe. lol $\endgroup$ – donlan Jul 7 '16 at 13:34
  • $\begingroup$ same with me :) $\endgroup$ – A---B Jul 7 '16 at 13:35
1
$\begingroup$

By the Law of sines, we have $$ \frac{\sin \theta}{s\cdot t} = \frac{\sin \phi}{z\cdot t} $$ We can cancel the common factors of $t$ and isolate $$ \sin\theta = \frac{s}{z} \sin\phi $$ This should help you find $\theta$.

$\endgroup$
  • $\begingroup$ @MatthewLeingang i think you should have wrote your own answer, instead of doing complete revamp of mine. Anyway i don't have a problem with it. $\endgroup$ – A---B Jul 7 '16 at 16:59
  • $\begingroup$ my only additional contribution was to cite the Law of sines and cancel a t. Your answer was CW so it seemed greedy to post the same thing under my own name. In any case, the question has an answer. $\endgroup$ – Matthew Leingang Jul 7 '16 at 23:05
  • $\begingroup$ @MatthewLeingang wound up uncovering an issue when you try to solve the whole problem. $\endgroup$ – donlan Jul 8 '16 at 13:21
2
$\begingroup$

After seeing the answer above, I was able to mostly solve the problem. There was an issue, however, in that the sign of $\theta$ is always positive when you actually go through the whole solution--calculating the vectors, then $\phi$, then $\theta$ using the law of sines.

So the issue is: which side of the character face vector is the enemy direction vector (assuming the character is facing the enemy). There doesn't seem to be a trivial way to figure this out, given two arbitrary vectors, using the tools a computer has.

The simplest, most straight forward way that I found to accomplish this--without any kind of logic or pattern recognition--was to just use the sign of the determinant of the two vectors--so $\operatorname{sign}(x_1*y_2 - y_1*x_2)$. The asymmetry gives you a left and right with only 2 multiplies and a subtraction (important when you are in a game loop that is doing 120 fps).


Anyhow, here is how it worked out:


In order to calculate $\phi$ in the drawing above, I used the dot product:

$$ \mathbf{A}\bullet\mathbf{B} = ||A||\operatorname{cos}\phi $$

Where $\mathbf{A}$ is the unit vector pointing from the enemy to my character (in the drawing), and $\mathbf{B}$ is the unit vector pointing in the enemy's direction of travel.

Having solved for $\phi$ by taking the $\operatorname{arccos}$ of the dot product result, I calculated $\theta$ in the drawing above with the law of sines,

$$ z*t*\operatorname{sin}\theta = s*t*\operatorname{sin}\phi\\ \theta = \operatorname{arcsin}(\frac{s}{z}\operatorname{sin}\phi) $$

But there was a problem: $\theta$ was always positive. The issue was the range of the $\operatorname{arccos}$ function: $[0,\pi]$. As a result of the $\operatorname{arccos}$ range, $\phi$ was always positive, and the character would only lead the enemy when the angular velocity of the enemy relative to the character was positive.


So, in order to recapture the "sign" of the angle, I think that what you need is the sign of the determinant of the two vectors (did not find an authority or proof...just thought about it and tested).

So,

$$ \theta' = \operatorname{sign}(\operatorname{det} \begin{bmatrix} A_x & A_y \\ B_x & B_y \end{bmatrix} ) * \theta $$

Will give you back the "sign" of the angle.

$\endgroup$
  • $\begingroup$ I did not read your answer full but here is my idea to deal with it. You can get the direction the enemy is travelling, that is either left or right of the player and so if it is right then positive and if left then negative. $\endgroup$ – A---B Jul 8 '16 at 13:47
  • 1
    $\begingroup$ @ritwiksinha yeah, the determinant was the easiest way to figure out right and left sides...because when it is just two arbitrary vectors in any random direction, it is kind of hard to say for sure what left and right is--rotate back to 0, then see what quadrant the vector is in was the only way I could think of that was robust...but it is a gui screen, so X and Y are pixels counting from the top left, so rotation is problematic... The determinant is going to capture L/R in two multiplies and one subtraction, while an abstract "left" and "right" is going to take a lot of work in code. $\endgroup$ – donlan Jul 8 '16 at 20:20
  • $\begingroup$ It wont take too much but yes the determinant is easier. Anyway thanks, i don't do much programming but once i encountered a similar problem and i calculated left and right instead of using determinants. $\endgroup$ – A---B Jul 8 '16 at 20:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.