Refining atan
In this chapter, we will make our monkey aim correctly. We will identify and fix the bugs that cause atan to give the wrong angles.
Currently, your monkey will attempt to aim wherever you press in the game. However, if you click on the left side of the monkey, it will get the wrong angle. And if you click in just the right places, the game will crash.
Let's look at our angle-finding process. This will change throughout the chapter.

We're going to add checks for two situations into this process:
- Divide-by-zero errors
- Negative coordinates
Don't Divide by Zero
In your game, you will get a divide-by-zero error if your dx is precisely 0. This is because we divide dy by dx before we run atan.
angle = atan( Y / X )
angle = atan( 1 / 0 ) ???
You can't divide by zero. The result is undefined. Computers will throw errors, and mathematicians will get upset.
Fortunately, we can tell this bug is coming. We know dx before we run atan. If dx is precisely 0, we don't need to run atan. We can supply some other answer instead.
What should that answer be? You can figure this out by graphing the problem. First, let's look at a vector (1, 0). This is an arrow pointing straight down. We know that this is precisely 90 degrees.

Next, let's look at the vector (-1, 0). This points in the opposite direction and is precisely -90 degrees.

These two vectors describe all possible angles for vectors with X component 0.
Let's add a check to our game, and get rid of pesky divide-by-zero errors.
- Add an
ifconditional block just beforeangle. - Add an
elsecase to theifblock. - Move the
angleatanline into theelsebracket. - In the condition slot, add
dx=0. - In the
dobracket, add a secondif... elseblock. - For the second
ifcondition, checkdy<0. - If true,
set angle-90. - Else,
set angle90.
Have you seen
if elseblocks before? You start with a normalifblock, then click the settings cog to configure it. Just drag anelseblock into theifsection. It goes like this:
Your code should look like this:

Now test your game. You should be unable to get divide-by-zero errors.
Negative Coordinates
When you try to aim to the left, your monkey gets confused. Why is this?
The answer has to do with vectors and division.
First, let's look at the vector (1, 1).
angle = atan( 1 / 1 )
angle = atan( 1 )
angle = 45 degrees

So far so good. Now let's look at a vector pointing in the opposite direction, (-1, -1).
angle = atan( -1 / -1 )
angle = atan( 1 )
angle = 45 degrees

Uh-oh. That's wrong.
Can you see the reason? Both (1, 1) and (-1, -1) resolve to 1 before we run atan. If we put the same number in, we get the same number out. The operation isn't magic.
In fact, atan will give the wrong answer any time X is negative. It will only return angles between -90 and 90 degrees. You will never receive angles between -180 and -90, or between 90 and 180. Half the arc of angles is impossible!
Fortunately, we know the exact nature of the error. When X is negative, the answer is off by precisely 180 degrees.
So if we know X is negative, we can just add 180 to the output of atan and get the correct result every time.
Let's do this now.
- Directly after our
angleatanline, add anotherifblock. Do not add anelsecase. - If
dx<0... - ...
set angletoangle+180.
Your code should now look like this:

Play your game, and press all over the game. Your monkey will now shoot wherever you press.
Congratulations! You understand the failure modes of atan, and how to get the right answer under any circumstances.
