Elite on the BBC Micro and NES

# Pitching and rolling by a fixed angle

## How other ships manage to pitch and roll in space

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.

For example, here's a video showing the space station rotating around its central axis, which is achieved by rotating the station by a small, fixed amount on each iteration of the main loop:

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 anti-clockwise 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.