BBC Micro Elite

# Pitching and rolling by a fixed angle

```How other ships manage to pitch and roll in space
-------------------------------------------------
References: MVS5
We can pitch and roll our ship by varying amounts, as shown by the dashboard's
DC and RL indicators, but enemy ships don't have such a luxury - it turns out
they can only orientate themselves at a fixed speed. Specifically, they can
only pitch or roll by a fixed amount each iteration of the main loop - by an
angle of 1/16 radians, or 3.6 degrees.

This fixed rotation speed makes life simpler for the game code, not only
because the angle is small enough to apply the small angle approximation, but
also because 1/16 is a power of 2. Let's see how this helps by looking at the
calculation in MVS5 in more detail.

Fixed angle calculations
------------------------
The MVS5 routine applies the same trigonometry as described in routine MVS4
(see the deep dive on "Rotating the universe" for details). In MVS5 we rotated
the ship's orientation vectors by our own pitch and roll, but this time the
angle is fixed at a very small 1/16 radians (around 3.6 degrees) so the maths
is rather simpler. If you refer to the documentation for MVS4, you can see
that the equations for rolling a point (x, y, z) through an angle a to
(x´, y´, z´) are:

x´ = x * cos(a) - y * sin(a)
y´ = y * cos(a) + x * sin(a)
z´ = z

In this case, angle a is fixed at 1/16 radians, so we can take the small angle
approximations described in MVS4, and reduce them like this:

sin a ~= a
= 1/16

cos a ~= 1 - (a * a) / 2
= 1 - (1/16 * 1/16) / 2
= 1 - (1/256) / 2
= 1 - 1/512

Plugging these into the above equations, we get:

x´ = x * cos(a) - y * sin(a)
= x * (1 - 1/512) - y / 16

y´ = y * cos(a) + x * sin(a)
= y * (1 - 1/512) + x / 16

z´ = z

so this is what routine MVS5 implements.

To clarify further, let's consider the example when X = 15 (roofv_x) and
Y = 21 (sidev_x), which applies roll to the ship. If we consider the
orientation vectors, this is how the three vectors look if we're sitting in
in the ship's cockpit:

roofv (points up out of the ship's sunroof...
^       or it would if it had one)
|
|
|
|    nosev (points forward out of the ship's nose
|   /        and into the screen)
|  /
| /
|/
+-----------------------> sidev (points out of the
ship's right view)

If we are doing a roll, then the nosev vector won't change, but roofv and
sidev will rotate around, so let's just consider the x-y plane (i.e. the
screen) and ignore the z-axis. It looks like this when we roll to the left by
angle a, rotating roofv to roofv´ and sidev to sidev´:

roofv
^
roofv´       |
\      |
\     |
\    |
\   |
\  |                 __ sidev´     <-.
\ |         __..--''                a`.
\| __..--''                          |
+-----------------------> sidev

Applying trigonometry to the above diagram, we get:

roofv´ = roofv * cos(a) - sidev * sin(a)

sidev´ = sidev * cos(a) + roofv * sin(a)

so calling MVS5 with X = 15 (roofv_x) and Y = 21 (sidev_x) and a negative
RAT2 (as the roll angle a is anticlockwise in our example), we get the
following if we do the calculation for the x coordinates in-place:

roofv_x = roofv_x * (1 - 1/512) - sidev_x / 16

sidev_x = sidev_x * (1 - 1/512) + roofv_x / 16

Subsequent calls with X = 17, Y = 23 and X = 19, Y = 25 cover the y and z
coordinates, so that's exactly what the roll section of routine MVS5 does,
with the pitch section doing the same maths, but on roofv and nosev.

```