Aviator on the BBC Micro

# Flight model: ApplyAerodynamics (Part 2 of 3)

```       Name: ApplyAerodynamics (Part 2 of 3)                         [Show more]
Type: Subroutine
Category: Flight model
Summary: Check whether the plane is stalling, and if it is, simulate one
wing stalling before the other, and make the stalling sound
Deep dive: The flight model
Stalling and recovery
Context: See this subroutine in context in the source code
References: No direct references to this subroutine in this source file

This part does the following:

* If we are already stalling and not going fast enough to pull out of the
stall, make the stalling sound and move on

* If we are not already stalling, or we are possibly going fast enough to
pull out of the stall (zVelocityPHi >= 11), we perform the stall check:

zVelocityP <= |yVelocityP| * 4

If this is true, then we are stalling.

* If we have just started stalling (i.e. we weren't already stalling but we
are now), check that we are not too close to the ground (yPlaneLo >= 20),
and assuming we aren't, apply a roll to the plane to simulate one of the
wings stalling before the other:

zTurn = zTurn +/- (A 0) >> 5

where:

* The +/- sign is the sign of yTurn

* A = xTurnTop EOR #%00111111

* Set the force factor for yLiftDrag according to the stalling state.

\ stalling beep if both of these are true:
\
\   * The force factor for yLiftDrag = 39, which
\     indicates that we are already stalling
\
\   * zVelocityPHi < 11, which indicates that the
\     forward speed of the plane is too low to pull us
\     out of the current stall
\
\ In other words, if we are already stalling and the
\ speed is not yet high enough to stop the stall, we
\ jump straight to the part of the routine that makes
\ the stalling sound

LDA forceFactor+4      \ If the force factor for yLiftDrag <> 39, skip the
CMP #39                \ following three instructions as we are not currently
BNE aero6              \ stalling

LDA zVelocityPHi       \ If zVelocityPHi < 11, jump to aero9 as the plane is
CMP #11                \ stalling
BCC aero9

.aero6

\ If we get here then we are either not stalling, or we
\ are already stalling but are possibly going fast
\ enough to pull out of the stall, so we now perform the
\ stalling check
\
\ The plane stalls if this is true:
\
\   zVelocityP <= |yVelocityP| * 4
\
\ in other words, when the plane is moving forwards at
\ less than a quarter of the speed at which it is moving
\ up or down, we stall
\
\ When we first stall, then the plane rolls slightly to
\ simulate one of the wings stalling before the other
\ (though this is skipped if the plane is flying very
\ low, at less than 20 feet above the ground)
\
\ A reminder that we set the following in part 1:
\
\   (J I) = |yVelocityP| * 4
\
\ We now compare the two 16-bit values in (J I) and
\ zVelocityP, by first comparing the high bytes, and if
\ they are equal, comparing the low bytes
\
\ If it turns out that (J I) < zVelocityP, we jump to
\ aero10 to maintain normal flight, so that's when:
\
\   |yVelocityP| * 4 < zVelocityP
\
\ but if (J I) >= zVelocityP, we are stalling, so that's
\ when:
\
\   zVelocityP <= |yVelocityP| * 4

LDA J                  \ If J < zVelocityPHi, then (J I) < zVelocityP, so jump
CMP zVelocityPHi       \ to aero10 to maintain normal flight
BCC aero10

BNE aero7              \ If J <> zVelocityPHi, i.e. J > zVelocityPHi, then
\ (J I) > zVelocity so jump to aero7 as we are going
\ slowly enough to stall

\ If we get here then J = zVelocityPHi, so now we
\ compare the low bytes

LDA I                  \ If I < zVelocityPLo, then (J I) < zVelocityP, so jump
CMP zVelocityPLo       \ to aero10 to maintain normal flight
BCC aero10

.aero7

\ If we get here then (J I) >= zVelocityP, so:
\
\   zVelocityP <= |yVelocityP| * 4
\
\ which means we are stalling
\
\ We now check the plane's height above the ground in
\ yPlane, as we don't roll the plane if it is less than
\ 20 feet from the ground (probably as this would kill
\ us instantly as the wings hit the ground, which would
\ be a bit unfair, even if this is what would happen in
\ real life)

LDA yPlaneHi           \ If yPlaneHi is non-zero, i.e. yPlane >= 256, then jump
BNE aero8              \ to aero8 to skip the following three instructions, as
\ we are high enough off the ground to roll the plane

LDA yPlaneLo           \ If yPlaneLo < 20, jump to aero9 to skip the roll, as
CMP #20                \ we are too close to the ground
BCC aero9

.aero8

LDA forceFactor+4      \ If the force factor for yLiftDrag = 39 then we are
BEQ aero9              \ stalling sound without applying any roll

\ Otherwise we are not already stalling, but we are now,
\ so we apply a roll to the plane to simulate one of the
\ wings stalling before the other

LDA yTurnTop           \ Set the C flag to the sign bit of yTurn so we can pass
ASL A                  \ it to the AddScaled routine, so the roll will be in
\ direction of the current yaw (i.e. the wing dips as
\ the plane slips in that direction)

LDY #4                 \ Set the scale factor in Y so we add or subtract
\ (A 0) >> 5

LDX #2                 \ Set X so the call to AddScaled updates the zTurn
\ variable

LDA xTurnTop           \ Set A = xTurnTop with bits 0 to 5 flipped, so (A 0) is
EOR #%00111111         \ larger when the current pitch rate is smaller, and
\ vice versa

JSR AddScaled          \ Set zTurn = zTurn +/- (A 0) >> 5
\
\ which applies a roll in the direction of the current
\ yaw, with the amount of roll being inversely
\ proportional to the current rate of pitch

.aero9

LDA L                  \ Fetch the current value of onGround

BNE aero10             \ If onGround is non-zero then we are on the ground, so
\ skip the following, as we can't be stalling if we are
\ on the ground

LDA #4                 \ Make sound #4, a short, low beep to indicate that the
JSR MakeSound          \ plane is stalling

LDA #39                \ Set A = 39 so that the force factor for yLiftDrag is
BNE aero11             \ set to 39 below (this BNE is effectively a JMP as A is
\ never zero)

.aero10

LDA #156               \ Set A = 156 so that the force factor for yLiftDrag is
\ set to 156 below

.aero11

STA forceFactor+4      \ Set the force factor for yLiftDrag to the value in A,
\ which will be either 39 (if we are stalling) or 156
\ (in normal flight)
```